<commit_before>/* TOOD: Implement for other kqueue based systems
 */

use {Error, Result};
use errno::Errno;
use libc::{timespec, time_t, c_int, c_long, uintptr_t};
use std::os::unix::io::RawFd;

pub use self::ffi::kevent as KEvent;

mod ffi {
    pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec};
    use super::{EventFilter, EventFlag, FilterFlag};

    #[derive(Clone, Copy)]
    #[repr(C)]
    pub struct kevent {
        pub ident: uintptr_t,       // 8
        pub filter: EventFilter,    // 2
        pub flags: EventFlag,       // 2
        pub fflags: FilterFlag,     // 4
        pub data: intptr_t,         // 8
        pub udata: usize             // 8
    }

    // Bug in rustc, cannot determine that kevent is #[repr(C)]
    #[allow(improper_ctypes)]
    extern {
        pub fn kqueue() -> c_int;

        pub fn kevent(
            kq: c_int,
            changelist: *const kevent,
            nchanges: c_int,
            eventlist: *mut kevent,
            nevents: c_int,
            timeout: *const timespec) -> c_int;
    }
}

#[cfg(not(target_os = "dragonfly"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_MACHPORT = -8,
    EVFILT_FS = -9,
    EVFILT_USER = -10,
    // -11: unused
    EVFILT_VM = -12,
    EVFILT_SYSCOUNT = 13
}

#[cfg(target_os = "dragonfly")]
#[repr(i16)] // u_short
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_EXCEPT = -8,
    EVFILT_USER = -9,
}

#[cfg(not(target_os = "dragonfly"))]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = 0x0001,
        const EV_DELETE    = 0x0002,
        const EV_ENABLE    = 0x0004,
        const EV_DISABLE   = 0x0008,
        const EV_RECEIPT   = 0x0040,
        const EV_ONESHOT   = 0x0010,
        const EV_CLEAR     = 0x0020,
        const EV_DISPATCH  = 0x0080,
        const EV_SYSFLAGS  = 0xF000,
        const EV_FLAG0     = 0x1000,
        const EV_FLAG1     = 0x2000,
        const EV_EOF       = 0x8000,
        const EV_ERROR     = 0x4000
    }
);

#[cfg(target_os = "dragonfly")]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = 0x0001,
        const EV_DELETE    = 0x0002,
        const EV_ENABLE    = 0x0004,
        const EV_DISABLE   = 0x0008,
        const EV_RECEIPT   = 0x0040,
        const EV_ONESHOT   = 0x0010,
        const EV_CLEAR     = 0x0020,
        const EV_SYSFLAGS  = 0xF000,
        const EV_NODATA    = 0x1000,
        const EV_FLAG1     = 0x2000,
        const EV_EOF       = 0x8000,
        const EV_ERROR     = 0x4000
    }
);

#[cfg(not(target_os = "dragonfly"))]
bitflags!(
    flags FilterFlag: u32 {
        const NOTE_TRIGGER                         = 0x01000000,
        const NOTE_FFNOP                           = 0x00000000,
        const NOTE_FFAND                           = 0x40000000,
        const NOTE_FFOR                            = 0x80000000,
        const NOTE_FFCOPY                          = 0xc0000000,
        const NOTE_FFCTRLMASK                      = 0xc0000000,
        const NOTE_FFLAGSMASK                      = 0x00ffffff,
        const NOTE_LOWAT                           = 0x00000001,
        const NOTE_DELETE                          = 0x00000001,
        const NOTE_WRITE                           = 0x00000002,
        const NOTE_EXTEND                          = 0x00000004,
        const NOTE_ATTRIB                          = 0x00000008,
        const NOTE_LINK                            = 0x00000010,
        const NOTE_RENAME                          = 0x00000020,
        const NOTE_REVOKE                          = 0x00000040,
        const NOTE_NONE                            = 0x00000080,
        const NOTE_EXIT                            = 0x80000000,
        const NOTE_FORK                            = 0x40000000,
        const NOTE_EXEC                            = 0x20000000,
        const NOTE_REAP                            = 0x10000000,
        const NOTE_SIGNAL                          = 0x08000000,
        const NOTE_EXITSTATUS                      = 0x04000000,
        const NOTE_RESOURCEEND                     = 0x02000000,
        const NOTE_APPACTIVE                       = 0x00800000,
        const NOTE_APPBACKGROUND                   = 0x00400000,
        const NOTE_APPNONUI                        = 0x00200000,
        const NOTE_APPINACTIVE                     = 0x00100000,
        const NOTE_APPALLSTATES                    = 0x00f00000,
        const NOTE_PDATAMASK                       = 0x000fffff,
        const NOTE_PCTRLMASK                       = 0xfff00000,
        const NOTE_EXIT_REPARENTED                 = 0x00080000,
        const NOTE_VM_PRESSURE                     = 0x80000000,
        const NOTE_VM_PRESSURE_TERMINATE           = 0x40000000,
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = 0x20000000,
        const NOTE_VM_ERROR                        = 0x10000000,
        const NOTE_SECONDS                         = 0x00000001,
        const NOTE_USECONDS                        = 0x00000002,
        const NOTE_NSECONDS                        = 0x00000004,
        const NOTE_ABSOLUTE                        = 0x00000008,
        const NOTE_TRACK                           = 0x00000001,
        const NOTE_TRACKERR                        = 0x00000002,
        const NOTE_CHILD                           = 0x00000004
    }
);

#[cfg(target_os = "dragonfly")]
bitflags!(
    flags FilterFlag: u32 {
        const NOTE_TRIGGER                         = 0x01000000,
        const NOTE_FFNOP                           = 0x00000000,
        const NOTE_FFAND                           = 0x40000000,
        const NOTE_FFOR                            = 0x80000000,
        const NOTE_FFCOPY                          = 0xc0000000,
        const NOTE_FFCTRLMASK                      = 0xc0000000,
        const NOTE_FFLAGSMASK                      = 0x00ffffff,
        const NOTE_LOWAT                           = 0x00000001,
        const NOTE_DELETE                          = 0x00000001,
        const NOTE_WRITE                           = 0x00000002,
        const NOTE_EXTEND                          = 0x00000004,
        const NOTE_ATTRIB                          = 0x00000008,
        const NOTE_LINK                            = 0x00000010,
        const NOTE_RENAME                          = 0x00000020,
        const NOTE_REVOKE                          = 0x00000040,
        const NOTE_EXIT                            = 0x80000000,
        const NOTE_FORK                            = 0x40000000,
        const NOTE_EXEC                            = 0x20000000,
        const NOTE_SIGNAL                          = 0x08000000,
        const NOTE_PDATAMASK                       = 0x000fffff,
        const NOTE_PCTRLMASK                       = 0xf0000000, // NOTE: FreeBSD uses 0xfff00000,
        const NOTE_TRACK                           = 0x00000001,
        const NOTE_TRACKERR                        = 0x00000002,
        const NOTE_CHILD                           = 0x00000004
    }
);

#[cfg(not(target_os = "dragonfly"))]
pub const EV_POLL: EventFlag = EV_FLAG0;

#[cfg(not(target_os = "dragonfly"))]
pub const EV_OOBAND: EventFlag = EV_FLAG1;

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { ffi::kqueue() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    let res = unsafe {
        ffi::kevent(
            kq,
            changelist.as_ptr(),
            changelist.len() as c_int,
            eventlist.as_mut_ptr(),
            eventlist.len() as c_int,
            &timeout as *const timespec)
    };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: usize) {

    ev.ident  = ident as uintptr_t;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<commit_msg>sys/event: add kevent_ts to better expose kevent timeout<commit_after>/* TOOD: Implement for other kqueue based systems
 */

use {Error, Result};
use errno::Errno;
use libc::{timespec, time_t, c_int, c_long, uintptr_t};
use std::os::unix::io::RawFd;
use std::ptr;

pub use self::ffi::kevent as KEvent;

mod ffi {
    pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec};
    use super::{EventFilter, EventFlag, FilterFlag};

    #[derive(Clone, Copy)]
    #[repr(C)]
    pub struct kevent {
        pub ident: uintptr_t,       // 8
        pub filter: EventFilter,    // 2
        pub flags: EventFlag,       // 2
        pub fflags: FilterFlag,     // 4
        pub data: intptr_t,         // 8
        pub udata: usize             // 8
    }

    // Bug in rustc, cannot determine that kevent is #[repr(C)]
    #[allow(improper_ctypes)]
    extern {
        pub fn kqueue() -> c_int;

        pub fn kevent(
            kq: c_int,
            changelist: *const kevent,
            nchanges: c_int,
            eventlist: *mut kevent,
            nevents: c_int,
            timeout: *const timespec) -> c_int;
    }
}

#[cfg(not(target_os = "dragonfly"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_MACHPORT = -8,
    EVFILT_FS = -9,
    EVFILT_USER = -10,
    // -11: unused
    EVFILT_VM = -12,
    EVFILT_SYSCOUNT = 13
}

#[cfg(target_os = "dragonfly")]
#[repr(i16)] // u_short
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_EXCEPT = -8,
    EVFILT_USER = -9,
}

#[cfg(not(target_os = "dragonfly"))]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = 0x0001,
        const EV_DELETE    = 0x0002,
        const EV_ENABLE    = 0x0004,
        const EV_DISABLE   = 0x0008,
        const EV_RECEIPT   = 0x0040,
        const EV_ONESHOT   = 0x0010,
        const EV_CLEAR     = 0x0020,
        const EV_DISPATCH  = 0x0080,
        const EV_SYSFLAGS  = 0xF000,
        const EV_FLAG0     = 0x1000,
        const EV_FLAG1     = 0x2000,
        const EV_EOF       = 0x8000,
        const EV_ERROR     = 0x4000
    }
);

#[cfg(target_os = "dragonfly")]
bitflags!(
    flags EventFlag: u16 {
        const EV_ADD       = 0x0001,
        const EV_DELETE    = 0x0002,
        const EV_ENABLE    = 0x0004,
        const EV_DISABLE   = 0x0008,
        const EV_RECEIPT   = 0x0040,
        const EV_ONESHOT   = 0x0010,
        const EV_CLEAR     = 0x0020,
        const EV_SYSFLAGS  = 0xF000,
        const EV_NODATA    = 0x1000,
        const EV_FLAG1     = 0x2000,
        const EV_EOF       = 0x8000,
        const EV_ERROR     = 0x4000
    }
);

#[cfg(not(target_os = "dragonfly"))]
bitflags!(
    flags FilterFlag: u32 {
        const NOTE_TRIGGER                         = 0x01000000,
        const NOTE_FFNOP                           = 0x00000000,
        const NOTE_FFAND                           = 0x40000000,
        const NOTE_FFOR                            = 0x80000000,
        const NOTE_FFCOPY                          = 0xc0000000,
        const NOTE_FFCTRLMASK                      = 0xc0000000,
        const NOTE_FFLAGSMASK                      = 0x00ffffff,
        const NOTE_LOWAT                           = 0x00000001,
        const NOTE_DELETE                          = 0x00000001,
        const NOTE_WRITE                           = 0x00000002,
        const NOTE_EXTEND                          = 0x00000004,
        const NOTE_ATTRIB                          = 0x00000008,
        const NOTE_LINK                            = 0x00000010,
        const NOTE_RENAME                          = 0x00000020,
        const NOTE_REVOKE                          = 0x00000040,
        const NOTE_NONE                            = 0x00000080,
        const NOTE_EXIT                            = 0x80000000,
        const NOTE_FORK                            = 0x40000000,
        const NOTE_EXEC                            = 0x20000000,
        const NOTE_REAP                            = 0x10000000,
        const NOTE_SIGNAL                          = 0x08000000,
        const NOTE_EXITSTATUS                      = 0x04000000,
        const NOTE_RESOURCEEND                     = 0x02000000,
        const NOTE_APPACTIVE                       = 0x00800000,
        const NOTE_APPBACKGROUND                   = 0x00400000,
        const NOTE_APPNONUI                        = 0x00200000,
        const NOTE_APPINACTIVE                     = 0x00100000,
        const NOTE_APPALLSTATES                    = 0x00f00000,
        const NOTE_PDATAMASK                       = 0x000fffff,
        const NOTE_PCTRLMASK                       = 0xfff00000,
        const NOTE_EXIT_REPARENTED                 = 0x00080000,
        const NOTE_VM_PRESSURE                     = 0x80000000,
        const NOTE_VM_PRESSURE_TERMINATE           = 0x40000000,
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = 0x20000000,
        const NOTE_VM_ERROR                        = 0x10000000,
        const NOTE_SECONDS                         = 0x00000001,
        const NOTE_USECONDS                        = 0x00000002,
        const NOTE_NSECONDS                        = 0x00000004,
        const NOTE_ABSOLUTE                        = 0x00000008,
        const NOTE_TRACK                           = 0x00000001,
        const NOTE_TRACKERR                        = 0x00000002,
        const NOTE_CHILD                           = 0x00000004
    }
);

#[cfg(target_os = "dragonfly")]
bitflags!(
    flags FilterFlag: u32 {
        const NOTE_TRIGGER                         = 0x01000000,
        const NOTE_FFNOP                           = 0x00000000,
        const NOTE_FFAND                           = 0x40000000,
        const NOTE_FFOR                            = 0x80000000,
        const NOTE_FFCOPY                          = 0xc0000000,
        const NOTE_FFCTRLMASK                      = 0xc0000000,
        const NOTE_FFLAGSMASK                      = 0x00ffffff,
        const NOTE_LOWAT                           = 0x00000001,
        const NOTE_DELETE                          = 0x00000001,
        const NOTE_WRITE                           = 0x00000002,
        const NOTE_EXTEND                          = 0x00000004,
        const NOTE_ATTRIB                          = 0x00000008,
        const NOTE_LINK                            = 0x00000010,
        const NOTE_RENAME                          = 0x00000020,
        const NOTE_REVOKE                          = 0x00000040,
        const NOTE_EXIT                            = 0x80000000,
        const NOTE_FORK                            = 0x40000000,
        const NOTE_EXEC                            = 0x20000000,
        const NOTE_SIGNAL                          = 0x08000000,
        const NOTE_PDATAMASK                       = 0x000fffff,
        const NOTE_PCTRLMASK                       = 0xf0000000, // NOTE: FreeBSD uses 0xfff00000,
        const NOTE_TRACK                           = 0x00000001,
        const NOTE_TRACKERR                        = 0x00000002,
        const NOTE_CHILD                           = 0x00000004
    }
);

#[cfg(not(target_os = "dragonfly"))]
pub const EV_POLL: EventFlag = EV_FLAG0;

#[cfg(not(target_os = "dragonfly"))]
pub const EV_OOBAND: EventFlag = EV_FLAG1;

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { ffi::kqueue() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    kevent_ts(kq, changelist, eventlist, Some(timeout))
}

pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {
    let res = unsafe {
        ffi::kevent(
            kq,
            changelist.as_ptr(),
            changelist.len() as c_int,
            eventlist.as_mut_ptr(),
            eventlist.len() as c_int,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: usize) {

    ev.ident  = ident as uintptr_t;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<|endoftext|>


<commit_before>extern crate sourcemap;

use std::collections::HashMap;
use sourcemap::SourceMapIndex;

#[test]
fn test_basic_indexed_sourcemap() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "min.js",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ]
    }"#;
    let file1 : Vec<&'static str> = r#"function add(a, b) {
 "use strict";
 return a + b; // fôo
}
"#.lines().collect();
    let file2 : Vec<&'static str> = r#"function multiply(a, b) {
 "use strict";
 return a * b;
}
function divide(a, b) {
 "use strict";
 try {
  return multiply(add(a, b), a, b) / c;
 } catch (e) {
  Raven.captureException(e);
 }
}
"#.lines().collect();

    println!("{:?}", file1);
    let mut files = HashMap::new();
    files.insert("file1.js", file1);
    files.insert("file2.js", file2);

    let ism = SourceMapIndex::from_reader(input).unwrap();
    let flat_map = ism.flatten().unwrap();

    for token in flat_map.tokens() {
        let src = files.get(token.get_source().unwrap()).unwrap();
        println!("{:?}", token);
        if let Some(name) = token.get_name() {
            let line = src[token.get_src_line() as usize];
            let idx = token.get_src_col() as usize;
            let span = &line[idx..idx + name.len()];
            assert_eq!(span, name);
        }
    }
}
<commit_msg>Reintented tests<commit_after>extern crate sourcemap;

use std::collections::HashMap;
use sourcemap::SourceMapIndex;

#[test]
fn test_basic_indexed_sourcemap() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "min.js",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ]
    }"#;

    let file1 : Vec<_> = "function add(a, b) {\n \"use strict\";\n \
                          return a + b; // fôo\n}".lines().collect();
    let file2 : Vec<_> = "function multiply(a, b) {\n \"use strict\";\n \
                          return a * b;\n}\nfunction divide(a, b) {\n \
                          \"use strict\";\n try {\n  return multiply(add(a, \
                          b), a, b) / c;\n } catch (e) {\n  \
                          Raven.captureException(e);\n }\n}".lines().collect();

    let mut files = HashMap::new();
    files.insert("file1.js", file1);
    files.insert("file2.js", file2);

    let ism = SourceMapIndex::from_reader(input).unwrap();
    let flat_map = ism.flatten().unwrap();

    for token in flat_map.tokens() {
        let src = files.get(token.get_source().unwrap()).unwrap();
        if let Some(name) = token.get_name() {
            let line = src[token.get_src_line() as usize];
            let idx = token.get_src_col() as usize;
            let span = &line[idx..idx + name.len()];
            assert_eq!(span, name);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustyspans;

use rustyspans::Range;
use rustyspans::Bound::*;

#[test]
fn from_i32_range() {
    assert_eq!(
        Range::new(Inclusive(1), Exclusive(10)),
        Range::from(1..10));
}

#[test]
fn contains() {
    assert!(!Range::from(1..10).contains(&0));
    assert!(Range::from(1..10).contains(&1));
    assert!(Range::from(1..10).contains(&9));
    assert!(!Range::from(1..10).contains(&10));
}
<commit_msg>Added tests for Range methods and traits<commit_after>#![deny(dead_code)]
extern crate rustyspans;

use std::cmp::Ordering;

use rustyspans::Range;
use rustyspans::Bound::*;

#[test]
fn from_i32_range() {
    assert_eq!(
        Range::new(Inclusive(1), Exclusive(10)),
        Range::from(1..10));
}

#[test]
fn lower_inf() {
    assert!(!Range::Empty::<i32>.lower_inf());
    assert!(!Range::from(1..10).lower_inf());
    assert!(!Range::from(1..).lower_inf());
    assert!(Range::from(..10).lower_inf());
    assert!(Range::<i32>::from(..).lower_inf());
}

#[test]
fn upper_inf() {
    assert!(!Range::Empty::<i32>.upper_inf());
    assert!(!Range::from(1..10).upper_inf());
    assert!(Range::from(1..).upper_inf());
    assert!(!Range::from(..10).upper_inf());
    assert!(Range::<i32>::from(..).upper_inf());
}

#[test]
fn is_bounded() {
    assert!(Range::Empty::<i32>.is_bounded());
    assert!(Range::from(1..10).is_bounded());
    assert!(!Range::from(1..).is_bounded());
    assert!(!Range::from(..10).is_bounded());
    assert!(!Range::<i32>::from(..).is_bounded());
}

#[test]
fn contains() {
    assert!(!Range::from(1..10).contains(&0));
    assert!(Range::from(1..10).contains(&1));
    assert!(Range::from(1..10).contains(&9));
    assert!(!Range::from(1..10).contains(&10));
}

#[test]
fn fmt_display() {
    assert_eq!("(empty)", format!("{}", Range::Empty::<i32>));
    assert_eq!("(,)", format!("{}", Range::<i32>::from(..)));

    assert_eq!("[1,10)", format!("{}", Range::from(1..10)));
    assert_eq!("[1,)", format!("{}", Range::from(1..)));
    assert_eq!("(,10)", format!("{}", Range::from(..10)));

    assert_eq!("(1,10]", format!("{}", Range::from(Exclusive(1)..Inclusive(10))));
}

#[test]
fn partial_cmp() {
    let undef: Option<Ordering> = None;
    let lt = Some(Ordering::Less);
    let eq = Some(Ordering::Equal);
    let gt = Some(Ordering::Greater);

    let empty = Range::Empty::<i32>;
    let unbounded = Range::<i32>::from(..);
    let r1_10 = Range::from(1..10);
    let r1_100 = Range::from(1..100);
    let r1_ = Range::from(1..);
    let r_10 = Range::from(..10);

    assert_eq!(undef, empty.partial_cmp(&empty));
    assert_eq!(undef, empty.partial_cmp(&unbounded));
    assert_eq!(undef, empty.partial_cmp(&r1_10));
    assert_eq!(undef, empty.partial_cmp(&r1_100));
    assert_eq!(undef, empty.partial_cmp(&r1_));
    assert_eq!(undef, empty.partial_cmp(&r_10));

    assert_eq!(eq, unbounded.partial_cmp(&unbounded));
    assert_eq!(lt, unbounded.partial_cmp(&r1_10));
    assert_eq!(lt, unbounded.partial_cmp(&r1_100));
    assert_eq!(lt, unbounded.partial_cmp(&r1_));
    assert_eq!(gt, unbounded.partial_cmp(&r_10));

    assert_eq!(eq, r1_10.partial_cmp(&r1_10));
    assert_eq!(lt, r1_10.partial_cmp(&r1_100));
    assert_eq!(gt, r1_100.partial_cmp(&r1_10));
    assert_eq!(gt, r1_10.partial_cmp(&r_10));
    assert_eq!(lt, r1_10.partial_cmp(&r1_));
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate lutario;
extern crate netlib_src;
extern crate rand;
extern crate test;

use std::env;
use std::sync::Arc;
use lutario::{imsrg, nuclei};
use lutario::j_scheme::{JAtlas, JScheme, new_mop_j012, rand_mop_j012};
use lutario::op::VectorMut;
use rand::SeedableRng;

const RNG_SEED: [u32; 4] = [
    0x193a6754,
    0xa8a7d469,
    0x97830e05,
    0x113ba7bb,
];

fn scheme_o16() -> Arc<JScheme> {
    JAtlas::new(&nuclei::SimpleNucleus {
        e_max: env::var("LT_EMAX")
            .map(|s| s.parse().unwrap())
            .unwrap_or(4),
        e_fermi_n: 1,
        e_fermi_p: 1,
        orbs: "",
    }.to_nucleus().unwrap().basis()).scheme().clone()
}

#[bench]
fn bench_commut_o16_011_022(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.0 = 0.0;
        imsrg::c011(alpha, &a.1, &b.1, &mut c.0);
        imsrg::c022(alpha, &a.2, &b.2, &mut c.0);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_111_112_121(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.1.set_zero();
        imsrg::c111(alpha, &a.1, &b.1, &mut c.1);
        imsrg::c112(alpha, &a.1, &b.2, &mut c.1);
        imsrg::c121(alpha, &a.2, &b.1, &mut c.1);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_122(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.1.set_zero();
        imsrg::c1220(alpha, &a.2, &b.2, &mut c.1);
        imsrg::c1221(alpha, &a.2, &b.2, &mut c.1);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_212_221(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c212(alpha, &a.1, &b.2, &mut c.2);
        imsrg::c221(alpha, &a.2, &b.1, &mut c.2);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_2220_2222(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c2220(alpha, &a.2, &b.2, &mut c.2);
        imsrg::c2222(alpha, &a.2, &b.2, &mut c.2);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_2221(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    let mut w6j_ctx = Default::default();
    // warm up the w6j_ctx
    imsrg::c2221(&mut w6j_ctx, alpha, &a.2, &b.2, &mut c.2);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c2221(&mut w6j_ctx, alpha, &a.2, &b.2, &mut c.2);
        test::black_box(&mut c);
    });
}
<commit_msg>Add benchmarks for hf_transform_h2<commit_after>#![feature(test)]

extern crate lutario;
extern crate netlib_src;
extern crate rand;
extern crate test;

use std::env;
use std::sync::Arc;
use lutario::{hf, imsrg, nuclei};
use lutario::j_scheme::{JAtlas, JScheme, new_mop_j012, rand_mop_j012};
use lutario::op::VectorMut;
use rand::SeedableRng;

const RNG_SEED: [u32; 4] = [
    0x193a6754,
    0xa8a7d469,
    0x97830e05,
    0x113ba7bb,
];

fn scheme_o16() -> Arc<JScheme> {
    JAtlas::new(&nuclei::SimpleNucleus {
        e_max: env::var("LT_EMAX")
            .map(|s| s.parse().unwrap())
            .unwrap_or(4),
        e_fermi_n: 1,
        e_fermi_p: 1,
        orbs: "",
    }.to_nucleus().unwrap().basis()).scheme().clone()
}

#[bench]
fn bench_hf_transform_h2(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.2.set_zero();
        hf::transform_h2(&b.2, &a.1, &mut c.2);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_011_022(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.0 = 0.0;
        imsrg::c011(alpha, &a.1, &b.1, &mut c.0);
        imsrg::c022(alpha, &a.2, &b.2, &mut c.0);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_111_112_121(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.1.set_zero();
        imsrg::c111(alpha, &a.1, &b.1, &mut c.1);
        imsrg::c112(alpha, &a.1, &b.2, &mut c.1);
        imsrg::c121(alpha, &a.2, &b.1, &mut c.1);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_122(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.1.set_zero();
        imsrg::c1220(alpha, &a.2, &b.2, &mut c.1);
        imsrg::c1221(alpha, &a.2, &b.2, &mut c.1);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_212_221(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c212(alpha, &a.1, &b.2, &mut c.2);
        imsrg::c221(alpha, &a.2, &b.1, &mut c.2);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_2220_2222(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c2220(alpha, &a.2, &b.2, &mut c.2);
        imsrg::c2222(alpha, &a.2, &b.2, &mut c.2);
        test::black_box(&mut c);
    });
}

#[bench]
fn bench_commut_o16_2221(bencher: &mut test::Bencher) {
    let mut rng = rand::XorShiftRng::from_seed(RNG_SEED);
    let scheme = &scheme_o16();
    let alpha = test::black_box(-1.0);
    let a = rand_mop_j012(scheme, &mut rng);
    let b = rand_mop_j012(scheme, &mut rng);
    let mut c = new_mop_j012(scheme);
    let mut w6j_ctx = Default::default();
    // warm up the w6j_ctx
    imsrg::c2221(&mut w6j_ctx, alpha, &a.2, &b.2, &mut c.2);
    bencher.iter(|| {
        c.2.set_zero();
        imsrg::c2221(&mut w6j_ctx, alpha, &a.2, &b.2, &mut c.2);
        test::black_box(&mut c);
    });
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use toml::Value;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::toml_ext::TomlValueExt;
use libimagentrylink::internal::InternalLinker;
use libimagerror::into::IntoError;

use result::Result;
use error::AnnotationErrorKind as AEK;
use error::MapErrInto;

pub trait Annotateable {

    /// Add an annotation to `Self`, that is a `FileLockEntry` which is linked to `Self` (link as in
    /// libimagentrylink).
    ///
    /// A new annotation also has the field `annotation.is_annotation` set to `true`.
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>>;

}

impl Annotateable for Entry {

    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>> {
        store.retrieve(PathBuf::from(ann_name))
            .map_err_into(AEK::StoreWriteError)
            .and_then(|mut anno| {
                anno.get_header_mut()
                    .insert("annotation.is_annotation", Value::Boolean(true))
                    .map_err_into(AEK::StoreWriteError)
                    .and_then(|succeeded| {
                        if succeeded {
                            Ok(anno)
                        } else {
                            Err(AEK::HeaderWriteError.into_error())
                        }
                    })
            })
            .and_then(|mut anno| {
                anno.add_internal_link(self)
                    .map_err_into(AEK::LinkingError)
                    .map(|_| anno)
            })
    }

}

<commit_msg>Add Annotateable::is_annotation()<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use toml::Value;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::toml_ext::TomlValueExt;
use libimagentrylink::internal::InternalLinker;
use libimagerror::into::IntoError;

use result::Result;
use error::AnnotationErrorKind as AEK;
use error::MapErrInto;

pub trait Annotateable {

    /// Add an annotation to `Self`, that is a `FileLockEntry` which is linked to `Self` (link as in
    /// libimagentrylink).
    ///
    /// A new annotation also has the field `annotation.is_annotation` set to `true`.
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>>;

    /// Check whether an entry is an annotation
    fn is_annotation(&self) -> Result<bool>;

}

impl Annotateable for Entry {

    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>> {
        store.retrieve(PathBuf::from(ann_name))
            .map_err_into(AEK::StoreWriteError)
            .and_then(|mut anno| {
                anno.get_header_mut()
                    .insert("annotation.is_annotation", Value::Boolean(true))
                    .map_err_into(AEK::StoreWriteError)
                    .and_then(|succeeded| {
                        if succeeded {
                            Ok(anno)
                        } else {
                            Err(AEK::HeaderWriteError.into_error())
                        }
                    })
            })
            .and_then(|mut anno| {
                anno.add_internal_link(self)
                    .map_err_into(AEK::LinkingError)
                    .map(|_| anno)
            })
    }

    fn is_annotation(&self) -> Result<bool> {
        self.get_header()
            .read("annotation.is_annotation")
            .map_err_into(AEK::StoreReadError)
            .and_then(|res| match res {
                Some(Value::Boolean(b)) => Ok(b),
                None                    => Ok(false),
                _                       => Err(AEK::HeaderTypeError.into_error()),
            })
    }

}

<|endoftext|>


<commit_before>use std::io::File;
use std::fmt;
use std::mem;
use std::os;

#[repr(C)]
struct Complex {
    re: f32,
    im: f32,
}

#[link(name = "m")]
extern {
    fn csqrtf(z: Complex) -> Complex;
}

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
        // code below is temporary
        let z = Complex { re: -1.0, im: 0.0 };
        let z_sqrt = unsafe {
            csqrtf(z)
        };
        println!("the square root of {} is {}", z, z_sqrt);
    }
}

impl fmt::Show for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}
<commit_msg>Prepare for zlib usage, remove example code for csqrtf() (using complex numbers) call.<commit_after>extern crate libc;

use libc::types;
use std::io::File;
use std::fmt;
use std::mem;
use std::os;

#[link(name = "z")]
extern {
    fn gzopen(path: *const types::os::arch::c95::c_char,
              mode: *const types::os::arch::c95::c_char)
              -> types::common::c95::c_void;
}

#[link(name = "z")]
extern {
    fn gzread(file: types::common::c95::c_void,
              buf:  types::common::c95::c_void,
              len:  uint)
              -> int;
}

#[link(name = "z")]
extern {
    fn gzclose(file: types::common::c95::c_void) -> int;
}

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
    }
}
<|endoftext|>


<commit_before>// this module adds some functionality based on the required implementations here
// like: `LinkedList::pop_back`, `Clone` and `IntoIterator` for `LinkedList<T>`
// You are free to use anything in it, but it's primarily for the test framework.
mod pre_implemented;

use std::ptr::NonNull;

type NodePtr<T> = NonNull<Node<T>>;
type OptNodePtr<T> = Option<NodePtr<T>>;

pub struct LinkedList<T> {
    back: OptNodePtr<T>,
    front: OptNodePtr<T>,
    len: usize,
    // The PhantomData signals dropck that we actually own `T`
    // I'm only aware of one case where this actually matters, which is when
    // using the dropck_eyepatch feature in Drop. We aren't using that here, so this is likely
    // unnecessary.
    // It can't hurt however and I'm not entirely certain that dropck_eyepatch is the only
    // case where it matters
    marker: std::marker::PhantomData<Box<T>>,
}

unsafe impl<T: Send> Send for LinkedList<T> {}
unsafe impl<T: Sync> Sync for LinkedList<T> {}

pub struct Cursor<'a, T> {
    list: &'a mut LinkedList<T>,
    node: OptNodePtr<T>,
}

struct Node<T> {
    element: T,
    next: OptNodePtr<T>,
    prev: OptNodePtr<T>,
}

impl<T> Node<T> {
    fn new_linkless(element: T) -> NodePtr<T> {
        Self::allocate(element, None, None)
    }

    fn allocate(element: T, prev: OptNodePtr<T>, next: OptNodePtr<T>) -> NodePtr<T> {
        unsafe {
            NonNull::new_unchecked(Box::into_raw(Box::new(Self {
                element,
                next,
                prev,
            })))
        }
    }
}

trait NodePtrHelper<T> {
    fn get_next(&mut self) -> &mut OptNodePtr<T>;
    fn get_prev(&mut self) -> &mut OptNodePtr<T>;
    fn link(left: NodePtr<T>, right: NodePtr<T>);
    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> NodePtr<T>;
    fn insert_new_after(self, element: T) -> NodePtr<T>;
    fn insert_new_before(self, element: T) -> NodePtr<T>;
    fn unlink_next(&mut self) -> OptNodePtr<T>;
    fn unlink_prev(&mut self) -> OptNodePtr<T>;
    fn into_inner(self) -> T;
}

impl<T> NodePtrHelper<T> for NodePtr<T> {
    fn get_next(&mut self) -> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().next }
    }

    fn get_prev(&mut self) -> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().prev }
    }

    fn link(mut left: NodePtr<T>, mut right: NodePtr<T>) {
        *left.get_next() = Some(right);
        *right.get_prev() = Some(left);
    }

    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> Self {
        Self::link(prev, self);
        Self::link(self, next);
        self
    }

    fn insert_new_after(mut self, element: T) -> Self {
        if let Some(next) = *self.get_next() {
            Node::new_linkless(element)
                .insert_between(self, next)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(self, new_node);
            new_node
        }
    }

    fn insert_new_before(mut self, element: T) -> Self {
        if let Some(prev) = *self.get_prev() {
            Node::new_linkless(element)
                .insert_between(prev, self)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(new_node, self);
            new_node
        }
    }

    // returns next of self, if it exists
    // leaves self untouched
    fn unlink_next(&mut self) -> OptNodePtr<T> {
        self.get_next().map(|mut next| {
            *next.get_prev() = None;
            next
        })
    }

    // see unlink_next
    fn unlink_prev(&mut self) -> OptNodePtr<T> {
        self.get_prev().map(|mut prev| {
            *prev.get_next() = None;
            prev
        })
    }

    // must not be linked to from other pointers
    // own links are irrelevant
    fn into_inner(self) -> T {
        unsafe {
            Box::from_raw(self.as_ptr()).element
        }
    }
}

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        LinkedList {
            back: None,
            front: None,
            len: 0,
            marker: std::marker::PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn cursor_front(&mut self) -> Cursor<T> {
        Cursor {
            node: self.front,
            list: self,
        }
    }

    pub fn cursor_back(&mut self) -> Cursor<T> {
        Cursor {
            node: self.back,
            list: self,
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            next_node: self.front,
            marker: std::marker::PhantomData,
        }
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        let mut cursor = self.cursor_front();
        while let Some(_) = cursor.take() {}
    }
}

pub struct Iter<'a, T> {
    next_node: OptNodePtr<T>,
    marker: std::marker::PhantomData<&'a LinkedList<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let node_ptr = self.next_node?;
        unsafe {
            let current_node = &*node_ptr.as_ptr();
            self.next_node = current_node.next;
            Some(&current_node.element)
        }
    }
}

impl<T> Cursor<'_, T> {
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unsafe {
            self.node.map(|node| &mut (*node.as_ptr()).element)
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        self._step(NodePtr::get_next)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        self._step(NodePtr::get_prev)
    }

    fn _step(
        &mut self,
        get_next: impl Fn(&mut NodePtr<T>) -> &mut OptNodePtr<T>
    ) -> Option<&mut T> {
        unsafe {
            if let Some(new_pos) = *get_next(self.node.as_mut()?) {
                self.node = Some(new_pos);
                Some(&mut (*new_pos.as_ptr()).element)
            } else {
                None
            }
        }
    }

    pub fn take(&mut self) -> Option<T> {
        let mut node = self.node?;
        let next = node.unlink_next();
        let prev = node.unlink_prev();

        match (prev, next) {
            (Some(prev), Some(next)) => {
                self.node = Some(next);
                NodePtr::link(prev, next);
            },
            (Some(_), None) => {
                self.node = prev;
                self.list.back = prev;
            },
            (None, Some(_)) => {
                self.node = next;
                self.list.front = next;
            },
            _ => {
                self.node = None;
                self.list.back = None;
                self.list.front = None;
            },
        };
        self.list.len -= 1;
        Some(node.into_inner())
    }

    pub fn insert_after(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_after(element);
            if list.back == Some(cursor_node) {
                list.back = Some(new_node);
            }
        });
    }

    pub fn insert_before(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_before(element);
            if list.front == Some(cursor_node) {
                list.front = Some(new_node);
            }
        });
    }

    // put into list, if empty, else do whatever callback says
    fn _insert(&mut self, element: T, callback: impl Fn(&mut LinkedList<T>, NodePtr<T>, T)) {
        let cursor_node = match self.node {
            Some(node) => node,
            None => { // list empty
                self.node = Some(Node::new_linkless(element));
                self.list.back = self.node;
                self.list.front = self.node;
                self.list.len += 1;
                return
            }
        };
        callback(&mut self.list, cursor_node, element);
        self.list.len += 1;
    }
}
<commit_msg>refactor example, document invariants and unsafe<commit_after>// this module adds some functionality based on the required implementations here
// like: `LinkedList::pop_back`, `Clone` and `IntoIterator` for `LinkedList<T>`
// You are free to use anything in it, but it's primarily for the test framework.
mod pre_implemented;

use std::ptr::NonNull;

type NodePtr<T> = NonNull<Node<T>>;
type OptNodePtr<T> = Option<NodePtr<T>>;

// Invariants we need to uphold
// L1. Every stored NodePtr is valid.
// L2. The nodes form a chain
//     L2.1 If Node B is `next` of A, then A is `prev` of B (see Node struct members)
//     L2.2 No cycles
// L3. `front` points to first element, `back` to last.
// (L4.) `len` should match number of elements, but unsafe code can't depend on it.
pub struct LinkedList<T> {
    back: OptNodePtr<T>,
    front: OptNodePtr<T>,
    len: usize,
    // The PhantomData signals dropck that we actually own `T`
    // I'm only aware of one case where this actually matters, which is when
    // using the dropck_eyepatch feature in Drop. We aren't using that here, so this is likely
    // unnecessary.
    // It can't hurt however and I'm not entirely certain that dropck_eyepatch is the only
    // case where it matters
    marker: std::marker::PhantomData<Box<T>>,
}

// We don't have any shared mutable state nor any thread dependent data.
// Trait bounds for Send/Sync are the same as for Box<T>
unsafe impl<T: Send> Send for LinkedList<T> {}
unsafe impl<T: Sync> Sync for LinkedList<T> {}

// Invariants we need to uphold
// C1. Never hand out more than one mutable reference at a time.
//     If we did, we couldn't guarantee non-aliasing mutable references
//     without additional book keeping as a cursor can move forwards and backwards
pub struct Cursor<'a, T> {
    list: &'a mut LinkedList<T>,
    node: OptNodePtr<T>,
}

struct Node<T> {
    element: T,
    next: OptNodePtr<T>,
    prev: OptNodePtr<T>,
}

impl<T> Node<T> {
    fn new_linkless(element: T) -> NodePtr<T> {
        unsafe {
            // new_unchecked() is trivially safe as we have just allocated a new Box
            NonNull::new_unchecked(Box::into_raw(Box::new(Self {
                element,
                prev: None,
                next: None,
            })))
        }
    }

    // `left` and `right` must point to adjacent nodes
    unsafe fn link(mut left: NodePtr<T>, mut right: NodePtr<T>) {
        left.as_mut().next = Some(right);
        right.as_mut().prev = Some(left);
    }
}

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        LinkedList {
            back: None,
            front: None,
            len: 0,
            marker: std::marker::PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn cursor_front(&mut self) -> Cursor<'_, T> {
        Cursor {
            node: self.front,
            list: self,
        }
    }

    pub fn cursor_back(&mut self) -> Cursor<'_, T> {
        Cursor {
            node: self.back,
            list: self,
        }
    }

    pub fn iter(&self) -> Iter<'_, T> {
        Iter {
            next_node: self.front,
            marker: std::marker::PhantomData,
        }
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        let mut cursor = self.cursor_front();
        while let Some(_) = cursor.take() {}
    }
}

pub struct Iter<'a, T> {
    next_node: OptNodePtr<T>,
    marker: std::marker::PhantomData<&'a LinkedList<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let node_ptr = self.next_node?;
        unsafe {
            // Dereferencing node.as_ptr() is safe due to invariant L1: all NodePtrs are valid.
            // Extending the lifetime to 'a is safe because the list is borrowed for 'a via Iter<'a, T>
            let current_node = &*node_ptr.as_ptr();
            self.next_node = current_node.next;
            Some(&current_node.element)
        }
    }
}

impl<T> Cursor<'_, T> {
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unsafe {
            // This is safe, because all NodePtrs are valid (L1) and the list and cursor
            // are mutably borrowed for as long as the reference is alive.
            self.node.map(|node| &mut (*node.as_ptr()).element)
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        // safe as node.next is a valid potential pointer
        unsafe { self._step(|node| node.next) }
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        // safe as node.prev is a valid potential pointer
        unsafe { self._step(|node| node.prev) }
    }

    // Moves location to the node returned by `get_next`, if it exists and returns
    // a mutable reference to its element.
    // `get_next` must return None or a pointer owned by the linked list
    unsafe fn _step(&mut self, get_next: impl Fn(&Node<T>) -> OptNodePtr<T>) -> Option<&mut T> {
        // safe due to L1: All NodePtrs are valid
        let new_pos = get_next(self.node?.as_ref())?;
        self.node = Some(new_pos);
        // returning a mutable reference is safe for the same reason peek_mut() is safe
        Some(&mut (*new_pos.as_ptr()).element)
    }

    pub fn take(&mut self) -> Option<T> {
        unsafe {
            // First remove all links to current node and close the hole, then deallocate and
            // return the element within.
            // All ptr accesses are safe because of L1: all NodePtrs are valid.
            let mut node = self.node?;
            let &mut Node { prev, next, .. } = node.as_mut();

            self.node = next.or(prev);
            // if the first and/or last element is taken, update the respective pointer(s) (L3)
            match next {
                Some(mut next) => next.as_mut().prev = prev,
                None => self.list.back = prev,
            };
            match prev {
                Some(mut prev) => prev.as_mut().next = next,
                None => self.list.front = next,
            }

            self.list.len -= 1;
            Some(Box::from_raw(node.as_ptr()).element)
        }
    }

    pub fn insert_after(&mut self, element: T) {
        unsafe {
            self._insert(
                element,
                // cursor_node <-> Option<next>
                // => cursor_node <-> new_element <-> Option<next>
                // This maintains the L2 invariant.
                // If `cursor_node` == `back`, `list.back` needs to be updated (L3).
                |list| &mut list.back,
                |mut cursor_node, new_node| {
                    if let Some(next) = cursor_node.as_mut().next {
                        Node::link(new_node, next);
                    }
                    Node::link(cursor_node, new_node);
                },
            );
        }
    }

    pub fn insert_before(&mut self, element: T) {
        unsafe {
            self._insert(
                element,
                // safe for the same reason as insert_after()
                // but in the other direction
                |list| &mut list.front,
                |mut cursor_node, new_node| {
                    if let Some(prev) = cursor_node.as_mut().prev {
                        Node::link(prev, new_node);
                    }
                    Node::link(new_node, cursor_node);
                },
            );
        }
    }

    // If list is empty, insert_after and insert_before are the same. Insert element directly.
    // Otherwise, let `link_new_node` callback do it and if the cursor is at the front or back node
    // given by `end_node`, update it to the new node.
    // Caller is responsible for choosing callbacks such that LinkedList invariants will hold.
    unsafe fn _insert(
        &mut self,
        element: T,
        // Should return reference to `front` or `back` member of LinkedList
        // that could have been replaced by `insert_element`.
        end_node: impl Fn(&mut LinkedList<T>) -> &mut OptNodePtr<T>,
        link_new_node: impl Fn(NodePtr<T>, NodePtr<T>),
    ) {
        // allocate new Node first.
        // if allocation panics, list is still in valid state.
        let new_node = Node::new_linkless(element);

        let cursor_node = match self.node {
            Some(node) => node,
            None => {
                // list empty
                self.node = Some(new_node);
                self.list.back = self.node;
                self.list.front = self.node;
                self.list.len += 1;
                return;
            }
        };
        link_new_node(cursor_node, new_node);
        let end_node = end_node(&mut self.list);
        if *end_node == Some(cursor_node) {
            *end_node = Some(new_node);
        }
        self.list.len += 1;
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Generic types that share their serialization implementations
//! for both specified and computed values.

use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss};
use super::CustomIdent;
use values::specified::url::SpecifiedUrl;

pub mod background;
pub mod basic_shape;
pub mod border;
pub mod effects;
pub mod flex;
#[cfg(feature = "gecko")]
pub mod gecko;
pub mod grid;
pub mod image;
pub mod position;
pub mod rect;
pub mod text;
pub mod transform;

// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
define_css_keyword_enum! { SymbolsType:
    "cyclic" => Cyclic,
    "numeric" => Numeric,
    "alphabetic" => Alphabetic,
    "symbolic" => Symbolic,
    "fixed" => Fixed,
}
add_impls_for_keyword_enum!(SymbolsType);

#[cfg(feature = "gecko")]
impl SymbolsType {
    /// Convert symbols type to their corresponding Gecko values.
    pub fn to_gecko_keyword(self) -> u8 {
        use gecko_bindings::structs;
        match self {
            SymbolsType::Cyclic => structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as u8,
            SymbolsType::Numeric => structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as u8,
            SymbolsType::Alphabetic => structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as u8,
            SymbolsType::Symbolic => structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as u8,
            SymbolsType::Fixed => structs::NS_STYLE_COUNTER_SYSTEM_FIXED as u8,
        }
    }
}

/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever <counter-style> is used, 'none' is a valid value as
/// well, we combine them into one type to make code simpler.
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub enum CounterStyleOrNone {
    /// `none`
    None,
    /// `<counter-style-name>`
    Name(CustomIdent),
    /// `symbols()`
    #[css(function)]
    Symbols(SymbolsType, Symbols),
}

impl CounterStyleOrNone {
    /// disc value
    pub fn disc() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
    }

    /// decimal value
    pub fn decimal() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
    }
}

no_viewport_percentage!(CounterStyleOrNone);

impl Parse for CounterStyleOrNone {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
            return Ok(CounterStyleOrNone::Name(name));
        }
        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
            return Ok(CounterStyleOrNone::None);
        }
        if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
            return input.parse_nested_block(|input| {
                let symbols_type = input.try(|i| SymbolsType::parse(i))
                    .unwrap_or(SymbolsType::Symbolic);
                let symbols = Symbols::parse(context, input)?;
                // There must be at least two symbols for alphabetic or
                // numeric system.
                if (symbols_type == SymbolsType::Alphabetic ||
                    symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
                    return Err(StyleParseError::UnspecifiedError.into());
                }
                // Identifier is not allowed in symbols() function.
                if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
                    return Err(StyleParseError::UnspecifiedError.into());
                }
                Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
            });
        }
        Err(StyleParseError::UnspecifiedError.into())
    }
}

/// A settings tag, defined by a four-character tag and a setting value
///
/// For font-feature-settings, this is a tag and an integer,
/// for font-variation-settings this is a tag and a float
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTag<T> {
    /// A four-character tag, packed into a u32 (one byte per character)
    pub tag: u32,
    /// The value
    pub value: T,
}

impl<T> OneOrMoreSeparated for FontSettingTag<T> {
    type S = Comma;
}

impl<T: ToCss> ToCss for FontSettingTag<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        use byteorder::{BigEndian, ByteOrder};
        use std::str;

        let mut raw = [0u8; 4];
        BigEndian::write_u32(&mut raw, self.tag);
        str::from_utf8(&raw).unwrap_or_default().to_css(dest)?;

        self.value.to_css(dest)
    }
}

impl<T: Parse> Parse for FontSettingTag<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    /// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
    /// settings-control-the-font-variation-settings-property
    /// <string> [ on | off | <integer> ]
    /// <string> <number>
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        use byteorder::{ReadBytesExt, BigEndian};
        use std::io::Cursor;

        let tag = input.expect_string()?;

        // allowed strings of length 4 containing chars: <U+20, U+7E>
        if tag.len() != 4 ||
           tag.chars().any(|c| c < ' ' || c > '~')
        {
            return Err(StyleParseError::UnspecifiedError.into())
        }

        let mut raw = Cursor::new(tag.as_bytes());
        let u_tag = raw.read_u32::<BigEndian>().unwrap();

        Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
    }
}

/// A font settings value for font-variation-settings or font-feature-settings
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub enum FontSettings<T> {
    /// No settings (default)
    Normal,
    /// Set of settings
    Tag(Vec<FontSettingTag<T>>)
}

impl<T: Parse> Parse for FontSettings<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(FontSettings::Normal);
        }
        Vec::parse(context, input).map(FontSettings::Tag)
    }
}

/// An integer that can also parse "on" and "off",
/// for font-feature-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagInt(pub u32);
/// A number value to be used for font-variation-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagFloat(pub f32);

impl ToCss for FontSettingTagInt {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self.0 {
            1 => Ok(()),
            0 => dest.write_str(" off"),
            x => write!(dest, " {}", x)
        }
    }
}

impl Parse for FontSettingTagInt {
    fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(value) = input.try(|input| input.expect_integer()) {
            // handle integer, throw if it is negative
            if value >= 0 {
                Ok(FontSettingTagInt(value as u32))
            } else {
                Err(StyleParseError::UnspecifiedError.into())
            }
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
            // on is an alias for '1'
            Ok(FontSettingTagInt(1))
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
            // off is an alias for '0'
            Ok(FontSettingTagInt(0))
        } else {
            // empty value is an alias for '1'
            Ok(FontSettingTagInt(1))
        }
    }
}

impl Parse for FontSettingTagFloat {
    fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
    }
}

impl ToCss for FontSettingTagFloat {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str(" ")?;
        self.0.to_css(dest)
    }
}

/// An SVG paint value
///
/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue)]
pub struct SVGPaint<ColorType> {
    /// The paint source
    pub kind: SVGPaintKind<ColorType>,
    /// The fallback color
    pub fallback: Option<ColorType>,
}

/// An SVG paint value without the fallback
///
/// Whereas the spec only allows PaintServer
/// to have a fallback, Gecko lets the context
/// properties have a fallback as well.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum SVGPaintKind<ColorType> {
    /// `none`
    None,
    /// `<color>`
    Color(ColorType),
    /// `url(...)`
    PaintServer(SpecifiedUrl),
    /// `context-fill`
    ContextFill,
    /// `context-stroke`
    ContextStroke,
}

impl<ColorType> SVGPaintKind<ColorType> {
    /// Parse a keyword value only
    fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
            "none" => Ok(SVGPaintKind::None),
            "context-fill" => Ok(SVGPaintKind::ContextFill),
            "context-stroke" => Ok(SVGPaintKind::ContextStroke),
        }
    }
}

/// Parse SVGPaint's fallback.
/// fallback is keyword(none) or Color.
/// https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint
fn parse_fallback<'i, 't, ColorType: Parse>(context: &ParserContext,
                                            input: &mut Parser<'i, 't>)
                                            -> Option<ColorType> {
    if input.try(|i| i.expect_ident_matching("none")).is_ok() {
        None
    } else {
        input.try(|i| ColorType::parse(context, i)).ok()
    }
}

impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
            Ok(SVGPaint {
                kind: SVGPaintKind::PaintServer(url),
                fallback: parse_fallback(context, input),
            })
        } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) {
            if let SVGPaintKind::None = kind {
                Ok(SVGPaint {
                    kind: kind,
                    fallback: None,
                })
            } else {
                Ok(SVGPaint {
                    kind: kind,
                    fallback: parse_fallback(context, input),
                })
            }
        } else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
            Ok(SVGPaint {
                kind: SVGPaintKind::Color(color),
                fallback: None,
            })
        } else {
            Err(StyleParseError::UnspecifiedError.into())
        }
    }
}

impl<ColorType: ToCss> ToCss for SVGPaint<ColorType> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.kind.to_css(dest)?;
        if let Some(ref fallback) = self.fallback {
            fallback.to_css(dest)?;
        }
        Ok(())
    }
}

<commit_msg>Derive ToCss for SVGPaint<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Generic types that share their serialization implementations
//! for both specified and computed values.

use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss};
use super::CustomIdent;
use values::specified::url::SpecifiedUrl;

pub mod background;
pub mod basic_shape;
pub mod border;
pub mod effects;
pub mod flex;
#[cfg(feature = "gecko")]
pub mod gecko;
pub mod grid;
pub mod image;
pub mod position;
pub mod rect;
pub mod text;
pub mod transform;

// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
define_css_keyword_enum! { SymbolsType:
    "cyclic" => Cyclic,
    "numeric" => Numeric,
    "alphabetic" => Alphabetic,
    "symbolic" => Symbolic,
    "fixed" => Fixed,
}
add_impls_for_keyword_enum!(SymbolsType);

#[cfg(feature = "gecko")]
impl SymbolsType {
    /// Convert symbols type to their corresponding Gecko values.
    pub fn to_gecko_keyword(self) -> u8 {
        use gecko_bindings::structs;
        match self {
            SymbolsType::Cyclic => structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as u8,
            SymbolsType::Numeric => structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as u8,
            SymbolsType::Alphabetic => structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as u8,
            SymbolsType::Symbolic => structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as u8,
            SymbolsType::Fixed => structs::NS_STYLE_COUNTER_SYSTEM_FIXED as u8,
        }
    }
}

/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever <counter-style> is used, 'none' is a valid value as
/// well, we combine them into one type to make code simpler.
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub enum CounterStyleOrNone {
    /// `none`
    None,
    /// `<counter-style-name>`
    Name(CustomIdent),
    /// `symbols()`
    #[css(function)]
    Symbols(SymbolsType, Symbols),
}

impl CounterStyleOrNone {
    /// disc value
    pub fn disc() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
    }

    /// decimal value
    pub fn decimal() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
    }
}

no_viewport_percentage!(CounterStyleOrNone);

impl Parse for CounterStyleOrNone {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
            return Ok(CounterStyleOrNone::Name(name));
        }
        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
            return Ok(CounterStyleOrNone::None);
        }
        if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
            return input.parse_nested_block(|input| {
                let symbols_type = input.try(|i| SymbolsType::parse(i))
                    .unwrap_or(SymbolsType::Symbolic);
                let symbols = Symbols::parse(context, input)?;
                // There must be at least two symbols for alphabetic or
                // numeric system.
                if (symbols_type == SymbolsType::Alphabetic ||
                    symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
                    return Err(StyleParseError::UnspecifiedError.into());
                }
                // Identifier is not allowed in symbols() function.
                if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
                    return Err(StyleParseError::UnspecifiedError.into());
                }
                Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
            });
        }
        Err(StyleParseError::UnspecifiedError.into())
    }
}

/// A settings tag, defined by a four-character tag and a setting value
///
/// For font-feature-settings, this is a tag and an integer,
/// for font-variation-settings this is a tag and a float
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTag<T> {
    /// A four-character tag, packed into a u32 (one byte per character)
    pub tag: u32,
    /// The value
    pub value: T,
}

impl<T> OneOrMoreSeparated for FontSettingTag<T> {
    type S = Comma;
}

impl<T: ToCss> ToCss for FontSettingTag<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        use byteorder::{BigEndian, ByteOrder};
        use std::str;

        let mut raw = [0u8; 4];
        BigEndian::write_u32(&mut raw, self.tag);
        str::from_utf8(&raw).unwrap_or_default().to_css(dest)?;

        self.value.to_css(dest)
    }
}

impl<T: Parse> Parse for FontSettingTag<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    /// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
    /// settings-control-the-font-variation-settings-property
    /// <string> [ on | off | <integer> ]
    /// <string> <number>
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        use byteorder::{ReadBytesExt, BigEndian};
        use std::io::Cursor;

        let tag = input.expect_string()?;

        // allowed strings of length 4 containing chars: <U+20, U+7E>
        if tag.len() != 4 ||
           tag.chars().any(|c| c < ' ' || c > '~')
        {
            return Err(StyleParseError::UnspecifiedError.into())
        }

        let mut raw = Cursor::new(tag.as_bytes());
        let u_tag = raw.read_u32::<BigEndian>().unwrap();

        Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
    }
}

/// A font settings value for font-variation-settings or font-feature-settings
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub enum FontSettings<T> {
    /// No settings (default)
    Normal,
    /// Set of settings
    Tag(Vec<FontSettingTag<T>>)
}

impl<T: Parse> Parse for FontSettings<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(FontSettings::Normal);
        }
        Vec::parse(context, input).map(FontSettings::Tag)
    }
}

/// An integer that can also parse "on" and "off",
/// for font-feature-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagInt(pub u32);
/// A number value to be used for font-variation-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagFloat(pub f32);

impl ToCss for FontSettingTagInt {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self.0 {
            1 => Ok(()),
            0 => dest.write_str(" off"),
            x => write!(dest, " {}", x)
        }
    }
}

impl Parse for FontSettingTagInt {
    fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(value) = input.try(|input| input.expect_integer()) {
            // handle integer, throw if it is negative
            if value >= 0 {
                Ok(FontSettingTagInt(value as u32))
            } else {
                Err(StyleParseError::UnspecifiedError.into())
            }
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
            // on is an alias for '1'
            Ok(FontSettingTagInt(1))
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
            // off is an alias for '0'
            Ok(FontSettingTagInt(0))
        } else {
            // empty value is an alias for '1'
            Ok(FontSettingTagInt(1))
        }
    }
}

impl Parse for FontSettingTagFloat {
    fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
    }
}

impl ToCss for FontSettingTagFloat {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str(" ")?;
        self.0.to_css(dest)
    }
}

/// An SVG paint value
///
/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
pub struct SVGPaint<ColorType> {
    /// The paint source
    pub kind: SVGPaintKind<ColorType>,
    /// The fallback color
    pub fallback: Option<ColorType>,
}

/// An SVG paint value without the fallback
///
/// Whereas the spec only allows PaintServer
/// to have a fallback, Gecko lets the context
/// properties have a fallback as well.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum SVGPaintKind<ColorType> {
    /// `none`
    None,
    /// `<color>`
    Color(ColorType),
    /// `url(...)`
    PaintServer(SpecifiedUrl),
    /// `context-fill`
    ContextFill,
    /// `context-stroke`
    ContextStroke,
}

impl<ColorType> SVGPaintKind<ColorType> {
    /// Parse a keyword value only
    fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
            "none" => Ok(SVGPaintKind::None),
            "context-fill" => Ok(SVGPaintKind::ContextFill),
            "context-stroke" => Ok(SVGPaintKind::ContextStroke),
        }
    }
}

/// Parse SVGPaint's fallback.
/// fallback is keyword(none) or Color.
/// https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint
fn parse_fallback<'i, 't, ColorType: Parse>(context: &ParserContext,
                                            input: &mut Parser<'i, 't>)
                                            -> Option<ColorType> {
    if input.try(|i| i.expect_ident_matching("none")).is_ok() {
        None
    } else {
        input.try(|i| ColorType::parse(context, i)).ok()
    }
}

impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
            Ok(SVGPaint {
                kind: SVGPaintKind::PaintServer(url),
                fallback: parse_fallback(context, input),
            })
        } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) {
            if let SVGPaintKind::None = kind {
                Ok(SVGPaint {
                    kind: kind,
                    fallback: None,
                })
            } else {
                Ok(SVGPaint {
                    kind: kind,
                    fallback: parse_fallback(context, input),
                })
            }
        } else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
            Ok(SVGPaint {
                kind: SVGPaintKind::Color(color),
                fallback: None,
            })
        } else {
            Err(StyleParseError::UnspecifiedError.into())
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind, VisibilityKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

declare_clippy_lint! {
    /// **What it does:** Checks for items declared `pub(crate)` that are not crate visible because they
    /// are inside a private module.
    ///
    /// **Why is this bad?** Writing `pub(crate)` is misleading when it's redundant due to the parent
    /// module's visibility.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// mod internal {
    ///     pub(crate) fn internal_fn() { }
    /// }
    /// ```
    /// This function is not visible outside the module and it can be declared with `pub` or
    /// private visibility
    /// ```rust
    /// mod internal {
    ///     pub fn internal_fn() { }
    /// }
    /// ```
    pub REDUNDANT_PUB_CRATE,
    nursery,
    "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them."
}

#[derive(Default)]
pub struct RedundantPubCrate {
    is_exported: Vec<bool>,
}

impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let VisibilityKind::Crate { .. } = item.vis.node {
            if !cx.access_levels.is_exported(item.hir_id) {
                if let Some(false) = self.is_exported.last() {
                    let span = item.span.with_hi(item.ident.span.hi());
                    span_lint_and_then(
                        cx,
                        REDUNDANT_PUB_CRATE,
                        span,
                        &format!("pub(crate) {} inside private module", item.kind.descr()),
                        |diag| {
                            diag.span_suggestion(
                                item.vis.span,
                                "consider using",
                                "pub".to_string(),
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        }

        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.push(cx.access_levels.is_exported(item.hir_id));
        }
    }

    fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.pop().expect("unbalanced check_item/check_item_post");
        }
    }
}
<commit_msg>rustup to https://github.com/rust-lang/rust/pull/70043<commit_after>use crate::utils::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind, VisibilityKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

declare_clippy_lint! {
    /// **What it does:** Checks for items declared `pub(crate)` that are not crate visible because they
    /// are inside a private module.
    ///
    /// **Why is this bad?** Writing `pub(crate)` is misleading when it's redundant due to the parent
    /// module's visibility.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// mod internal {
    ///     pub(crate) fn internal_fn() { }
    /// }
    /// ```
    /// This function is not visible outside the module and it can be declared with `pub` or
    /// private visibility
    /// ```rust
    /// mod internal {
    ///     pub fn internal_fn() { }
    /// }
    /// ```
    pub REDUNDANT_PUB_CRATE,
    nursery,
    "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them."
}

#[derive(Default)]
pub struct RedundantPubCrate {
    is_exported: Vec<bool>,
}

impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let VisibilityKind::Crate { .. } = item.vis.node {
            if !cx.access_levels.is_exported(item.hir_id) {
                if let Some(false) = self.is_exported.last() {
                    let span = item.span.with_hi(item.ident.span.hi());
                    let def_id = cx.tcx.hir().local_def_id(item.hir_id);
                    let descr = cx.tcx.def_kind(def_id).descr(def_id.to_def_id());
                    span_lint_and_then(
                        cx,
                        REDUNDANT_PUB_CRATE,
                        span,
                        &format!("pub(crate) {} inside private module", descr),
                        |diag| {
                            diag.span_suggestion(
                                item.vis.span,
                                "consider using",
                                "pub".to_string(),
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        }

        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.push(cx.access_levels.is_exported(item.hir_id));
        }
    }

    fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.pop().expect("unbalanced check_item/check_item_post");
        }
    }
}
<|endoftext|>