<commit_before>// Copyright 2014 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(plugin_registrar, quote)]

extern crate rustc;
extern crate syntax;

use std::gc::{Gc, GC};
use std::io::Command;
use std::mem;
use std::str;
use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::token::intern_and_get_ident as intern_str;

#[plugin_registrar]
pub fn registrar(reg: &mut rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("link_glfw"),
                                  base::ItemModifier(expand));
}

fn lit_str(s: token::InternedString) -> ast::Lit_ {
    ast::LitStr(s, ast::CookedStr)
}

enum LinkKind {
    Unknown,
    Framework,
}

fn attr_link(context: &mut base::ExtCtxt, span: codemap::Span,
             name: token::InternedString, kind: LinkKind) -> ast::Attribute {
    let mut meta_items = vec![
        context.meta_name_value(span, intern_str("name"), lit_str(name)),
    ];
    match kind {
        Framework => {
            meta_items.push(context.meta_name_value(
                span, intern_str("kind"),
                lit_str(intern_str("framework"))
            ));
        },
        _ => {},
    }
    let meta_list = context.meta_list(span, intern_str("link"), meta_items);
    context.attribute(span, meta_list)
}

pub fn expand(context: &mut base::ExtCtxt, span: codemap::Span,
              meta_item: Gc<ast::MetaItem>, item: Gc<ast::Item>
              ) -> Gc<ast::Item> {
    let out = Command::new("pkg-config")
        .arg("--static")
        .arg("--libs-only-l")
        .arg("--libs-only-other")
        .arg("--print-errors")
        .arg("glfw3")
        .output();
    match out {
        Ok(out) => {
            if out.status.success() {
                let mut item = (*item).clone();
                str::from_utf8(out.output.as_slice()).map(|output| {
                    let mut expect_framework = false;
                    for word in output.words() {
                        if word.starts_with("-l") {
                            item.attrs.push(attr_link(
                                context, span,
                                intern_str(word.slice_from(2)),
                                Unknown,
                            ));
                        } else if expect_framework {
                            expect_framework = false;
                            item.attrs.push(attr_link(
                                context, span,
                                intern_str(word),
                                Framework,
                            ));
                        } else if word.starts_with("-framework") {
                            expect_framework = true;
                        }
                    }
                });
                box (GC) item
            } else {
                context.span_err(
                    span,
                    format!(
                        "error returned by \
                        `pkg-config`: ({})\n\
                        `pkg-config stdout`: {}\n\
                        `pkg-config stderr`: {}",
                        out.status,
                        String::from_utf8(out.output).unwrap(),
                        String::from_utf8(out.error).unwrap())
                        .as_slice());
                item
            }
        },
        Err(e) => {
            context.span_err(span, format!("io error: {}", e).as_slice());
            item
        },
    }
}
<commit_msg>Update to nightly<commit_after>// Copyright 2014 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(plugin_registrar, quote)]

extern crate rustc;
extern crate syntax;

use std::gc::{Gc, GC};
use std::io::Command;
use std::mem;
use std::str;
use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::token::intern_and_get_ident as intern_str;

#[plugin_registrar]
pub fn registrar(reg: &mut rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("link_glfw"),
                                  base::ItemModifier(box expand));
}

fn lit_str(s: token::InternedString) -> ast::Lit_ {
    ast::LitStr(s, ast::CookedStr)
}

enum LinkKind {
    Unknown,
    Framework,
}

fn attr_link(context: &mut base::ExtCtxt, span: codemap::Span,
             name: token::InternedString, kind: LinkKind) -> ast::Attribute {
    let mut meta_items = vec![
        context.meta_name_value(span, intern_str("name"), lit_str(name)),
    ];
    match kind {
        Framework => {
            meta_items.push(context.meta_name_value(
                span, intern_str("kind"),
                lit_str(intern_str("framework"))
            ));
        },
        _ => {},
    }
    let meta_list = context.meta_list(span, intern_str("link"), meta_items);
    context.attribute(span, meta_list)
}

pub fn expand(context: &mut base::ExtCtxt, span: codemap::Span,
              meta_item: Gc<ast::MetaItem>, item: Gc<ast::Item>
              ) -> Gc<ast::Item> {
    let out = Command::new("pkg-config")
        .arg("--static")
        .arg("--libs-only-l")
        .arg("--libs-only-other")
        .arg("--print-errors")
        .arg("glfw3")
        .output();
    match out {
        Ok(out) => {
            if out.status.success() {
                let mut item = (*item).clone();
                str::from_utf8(out.output.as_slice()).map(|output| {
                    let mut expect_framework = false;
                    for word in output.words() {
                        if word.starts_with("-l") {
                            item.attrs.push(attr_link(
                                context, span,
                                intern_str(word.slice_from(2)),
                                Unknown,
                            ));
                        } else if expect_framework {
                            expect_framework = false;
                            item.attrs.push(attr_link(
                                context, span,
                                intern_str(word),
                                Framework,
                            ));
                        } else if word.starts_with("-framework") {
                            expect_framework = true;
                        }
                    }
                });
                box (GC) item
            } else {
                context.span_err(
                    span,
                    format!(
                        "error returned by \
                        `pkg-config`: ({})\n\
                        `pkg-config stdout`: {}\n\
                        `pkg-config stderr`: {}",
                        out.status,
                        String::from_utf8(out.output).unwrap(),
                        String::from_utf8(out.error).unwrap())
                        .as_slice());
                item
            }
        },
        Err(e) => {
            context.span_err(span, format!("io error: {}", e).as_slice());
            item
        },
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2019 Guillaume Gomez
//

use std::fs::File;
use std::io::Read;
use std::path::Path;

use crate::{NetworkExt, NetworksExt, NetworksIter};
use std::collections::HashMap;

/// Network interfaces.
///
/// ```no_run
/// use sysinfo::{NetworksExt, System, SystemExt};
///
/// let s = System::new_all();
/// let networks = s.get_networks();
/// ```
pub struct Networks {
    interfaces: HashMap<String, NetworkData>,
}

macro_rules! old_and_new {
    ($ty_:expr, $name:ident, $old:ident) => {{
        $ty_.$old = $ty_.$name;
        $ty_.$name = $name;
    }};
    ($ty_:expr, $name:ident, $old:ident, $path:expr) => {{
        let _tmp = $path;
        $ty_.$old = $ty_.$name;
        $ty_.$name = _tmp;
    }};
}

fn read<P: AsRef<Path>>(parent: P, path: &str, data: &mut Vec<u8>) -> u64 {
    if let Ok(mut f) = File::open(parent.as_ref().join(path)) {
        if let Ok(size) = f.read(data) {
            let mut i = 0;
            let mut ret = 0;

            while i < size && i < data.len() && data[i] >= b'0' && data[i] <= b'9' {
                ret *= 10;
                ret += (data[i] - b'0') as u64;
                i += 1;
            }
            return ret;
        }
    }
    0
}

impl Networks {
    pub(crate) fn new() -> Self {
        Networks {
            interfaces: HashMap::new(),
        }
    }
}

impl NetworksExt for Networks {
    fn iter(&self) -> NetworksIter {
        NetworksIter::new(self.interfaces.iter())
    }

    fn refresh(&mut self) {
        let mut v = vec![0; 30];

        for (interface_name, data) in self.interfaces.iter_mut() {
            data.update(interface_name, &mut v);
        }
    }

    fn refresh_networks_list(&mut self) {
        if let Ok(dir) = std::fs::read_dir("/sys/class/net/") {
            let mut data = vec![0; 30];
            for entry in dir.flatten() {
                let parent = &entry.path().join("statistics");
                let entry = match entry.file_name().into_string() {
                    Ok(entry) => entry,
                    Err(_) => continue,
                };
                let rx_bytes = read(parent, "rx_bytes", &mut data);
                let tx_bytes = read(parent, "tx_bytes", &mut data);
                let rx_packets = read(parent, "rx_packets", &mut data);
                let tx_packets = read(parent, "tx_packets", &mut data);
                let rx_errors = read(parent, "rx_errors", &mut data);
                let tx_errors = read(parent, "tx_errors", &mut data);
                // let rx_compressed = read(parent, "rx_compressed", &mut data);
                // let tx_compressed = read(parent, "tx_compressed", &mut data);
                let interface = self.interfaces.entry(entry).or_insert_with(|| NetworkData {
                    rx_bytes,
                    old_rx_bytes: rx_bytes,
                    tx_bytes,
                    old_tx_bytes: tx_bytes,
                    rx_packets,
                    old_rx_packets: rx_packets,
                    tx_packets,
                    old_tx_packets: tx_packets,
                    rx_errors,
                    old_rx_errors: rx_errors,
                    tx_errors,
                    old_tx_errors: tx_errors,
                    // rx_compressed,
                    // old_rx_compressed: rx_compressed,
                    // tx_compressed,
                    // old_tx_compressed: tx_compressed,
                });
                old_and_new!(interface, rx_bytes, old_rx_bytes);
                old_and_new!(interface, tx_bytes, old_tx_bytes);
                old_and_new!(interface, rx_packets, old_rx_packets);
                old_and_new!(interface, tx_packets, old_tx_packets);
                old_and_new!(interface, rx_errors, old_rx_errors);
                old_and_new!(interface, tx_errors, old_tx_errors);
                // old_and_new!(interface, rx_compressed, old_rx_compressed);
                // old_and_new!(interface, tx_compressed, old_tx_compressed);
            }
        }
    }
}

/// Contains network information.
pub struct NetworkData {
    /// Total number of bytes received over interface.
    rx_bytes: u64,
    old_rx_bytes: u64,
    /// Total number of bytes transmitted over interface.
    tx_bytes: u64,
    old_tx_bytes: u64,
    /// Total number of packets received.
    rx_packets: u64,
    old_rx_packets: u64,
    /// Total number of packets transmitted.
    tx_packets: u64,
    old_tx_packets: u64,
    /// Shows the total number of packets received with error. This includes
    /// too-long-frames errors, ring-buffer overflow errors, CRC errors,
    /// frame alignment errors, fifo overruns, and missed packets.
    rx_errors: u64,
    old_rx_errors: u64,
    /// similar to `rx_errors`
    tx_errors: u64,
    old_tx_errors: u64,
    // /// Indicates the number of compressed packets received by this
    // /// network device. This value might only be relevant for interfaces
    // /// that support packet compression (e.g: PPP).
    // rx_compressed: usize,
    // old_rx_compressed: usize,
    // /// Indicates the number of transmitted compressed packets. Note
    // /// this might only be relevant for devices that support
    // /// compression (e.g: PPP).
    // tx_compressed: usize,
    // old_tx_compressed: usize,
}

impl NetworkData {
    fn update(&mut self, path: &str, data: &mut Vec<u8>) {
        let path = &Path::new("/sys/class/net/").join(path).join("statistics");
        old_and_new!(self, rx_bytes, old_rx_bytes, read(path, "rx_bytes", data));
        old_and_new!(self, tx_bytes, old_tx_bytes, read(path, "tx_bytes", data));
        old_and_new!(
            self,
            rx_packets,
            old_rx_packets,
            read(path, "rx_packets", data)
        );
        old_and_new!(
            self,
            tx_packets,
            old_tx_packets,
            read(path, "tx_packets", data)
        );
        old_and_new!(
            self,
            rx_errors,
            old_rx_errors,
            read(path, "rx_errors", data)
        );
        old_and_new!(
            self,
            tx_errors,
            old_tx_errors,
            read(path, "tx_errors", data)
        );
        // old_and_new!(
        //     self,
        //     rx_compressed,
        //     old_rx_compressed,
        //     read(path, "rx_compressed", data)
        // );
        // old_and_new!(
        //     self,
        //     tx_compressed,
        //     old_tx_compressed,
        //     read(path, "tx_compressed", data)
        // );
    }
}

impl NetworkExt for NetworkData {
    fn get_received(&self) -> u64 {
        self.rx_bytes.saturating_sub(self.old_rx_bytes)
    }

    fn get_total_received(&self) -> u64 {
        self.rx_bytes
    }

    fn get_transmitted(&self) -> u64 {
        self.tx_bytes.saturating_sub(self.old_tx_bytes)
    }

    fn get_total_transmitted(&self) -> u64 {
        self.tx_bytes
    }

    fn get_packets_received(&self) -> u64 {
        self.rx_packets.saturating_sub(self.old_rx_packets)
    }

    fn get_total_packets_received(&self) -> u64 {
        self.rx_packets
    }

    fn get_packets_transmitted(&self) -> u64 {
        self.tx_packets.saturating_sub(self.old_tx_packets)
    }

    fn get_total_packets_transmitted(&self) -> u64 {
        self.tx_packets
    }

    fn get_errors_on_received(&self) -> u64 {
        self.rx_errors.saturating_sub(self.old_rx_errors)
    }

    fn get_total_errors_on_received(&self) -> u64 {
        self.rx_errors
    }

    fn get_errors_on_transmitted(&self) -> u64 {
        self.tx_errors.saturating_sub(self.old_tx_errors)
    }

    fn get_total_errors_on_transmitted(&self) -> u64 {
        self.tx_errors
    }
}
<commit_msg>Linux: Cleanup removed interfaces in refresh_networks_list (fixes #479) (#481)<commit_after>//
// Sysinfo
//
// Copyright (c) 2019 Guillaume Gomez
//

use std::fs::File;
use std::io::Read;
use std::path::Path;

use crate::{NetworkExt, NetworksExt, NetworksIter};
use std::collections::{hash_map, HashMap};

/// Network interfaces.
///
/// ```no_run
/// use sysinfo::{NetworksExt, System, SystemExt};
///
/// let s = System::new_all();
/// let networks = s.get_networks();
/// ```
pub struct Networks {
    interfaces: HashMap<String, NetworkData>,
}

macro_rules! old_and_new {
    ($ty_:expr, $name:ident, $old:ident) => {{
        $ty_.$old = $ty_.$name;
        $ty_.$name = $name;
    }};
    ($ty_:expr, $name:ident, $old:ident, $path:expr) => {{
        let _tmp = $path;
        $ty_.$old = $ty_.$name;
        $ty_.$name = _tmp;
    }};
}

fn read<P: AsRef<Path>>(parent: P, path: &str, data: &mut Vec<u8>) -> u64 {
    if let Ok(mut f) = File::open(parent.as_ref().join(path)) {
        if let Ok(size) = f.read(data) {
            let mut i = 0;
            let mut ret = 0;

            while i < size && i < data.len() && data[i] >= b'0' && data[i] <= b'9' {
                ret *= 10;
                ret += (data[i] - b'0') as u64;
                i += 1;
            }
            return ret;
        }
    }
    0
}

impl Networks {
    pub(crate) fn new() -> Self {
        Networks {
            interfaces: HashMap::new(),
        }
    }
}

fn refresh_networks_list_from_sysfs(
    interfaces: &mut HashMap<String, NetworkData>,
    sysfs_net: &Path,
) {
    if let Ok(dir) = std::fs::read_dir(sysfs_net) {
        let mut data = vec![0; 30];

        for stats in interfaces.values_mut() {
            stats.updated = false;
        }

        for entry in dir.flatten() {
            let parent = &entry.path().join("statistics");
            let entry = match entry.file_name().into_string() {
                Ok(entry) => entry,
                Err(_) => continue,
            };
            let rx_bytes = read(parent, "rx_bytes", &mut data);
            let tx_bytes = read(parent, "tx_bytes", &mut data);
            let rx_packets = read(parent, "rx_packets", &mut data);
            let tx_packets = read(parent, "tx_packets", &mut data);
            let rx_errors = read(parent, "rx_errors", &mut data);
            let tx_errors = read(parent, "tx_errors", &mut data);
            // let rx_compressed = read(parent, "rx_compressed", &mut data);
            // let tx_compressed = read(parent, "tx_compressed", &mut data);
            match interfaces.entry(entry) {
                hash_map::Entry::Occupied(mut e) => {
                    let mut interface = e.get_mut();
                    old_and_new!(interface, rx_bytes, old_rx_bytes);
                    old_and_new!(interface, tx_bytes, old_tx_bytes);
                    old_and_new!(interface, rx_packets, old_rx_packets);
                    old_and_new!(interface, tx_packets, old_tx_packets);
                    old_and_new!(interface, rx_errors, old_rx_errors);
                    old_and_new!(interface, tx_errors, old_tx_errors);
                    // old_and_new!(e, rx_compressed, old_rx_compressed);
                    // old_and_new!(e, tx_compressed, old_tx_compressed);
                    interface.updated = true;
                }
                hash_map::Entry::Vacant(e) => {
                    e.insert(NetworkData {
                        rx_bytes,
                        old_rx_bytes: rx_bytes,
                        tx_bytes,
                        old_tx_bytes: tx_bytes,
                        rx_packets,
                        old_rx_packets: rx_packets,
                        tx_packets,
                        old_tx_packets: tx_packets,
                        rx_errors,
                        old_rx_errors: rx_errors,
                        tx_errors,
                        old_tx_errors: tx_errors,
                        // rx_compressed,
                        // old_rx_compressed: rx_compressed,
                        // tx_compressed,
                        // old_tx_compressed: tx_compressed,
                        updated: true,
                    });
                }
            };
        }

        // Remove interfaces that are gone
        interfaces.retain(|_n, d| d.updated);
    }
}

impl NetworksExt for Networks {
    fn iter(&self) -> NetworksIter {
        NetworksIter::new(self.interfaces.iter())
    }

    fn refresh(&mut self) {
        let mut v = vec![0; 30];

        for (interface_name, data) in self.interfaces.iter_mut() {
            data.update(interface_name, &mut v);
        }
    }

    fn refresh_networks_list(&mut self) {
        refresh_networks_list_from_sysfs(&mut self.interfaces, Path::new("/sys/class/net/"));
    }
}

/// Contains network information.
pub struct NetworkData {
    /// Total number of bytes received over interface.
    rx_bytes: u64,
    old_rx_bytes: u64,
    /// Total number of bytes transmitted over interface.
    tx_bytes: u64,
    old_tx_bytes: u64,
    /// Total number of packets received.
    rx_packets: u64,
    old_rx_packets: u64,
    /// Total number of packets transmitted.
    tx_packets: u64,
    old_tx_packets: u64,
    /// Shows the total number of packets received with error. This includes
    /// too-long-frames errors, ring-buffer overflow errors, CRC errors,
    /// frame alignment errors, fifo overruns, and missed packets.
    rx_errors: u64,
    old_rx_errors: u64,
    /// similar to `rx_errors`
    tx_errors: u64,
    old_tx_errors: u64,
    // /// Indicates the number of compressed packets received by this
    // /// network device. This value might only be relevant for interfaces
    // /// that support packet compression (e.g: PPP).
    // rx_compressed: usize,
    // old_rx_compressed: usize,
    // /// Indicates the number of transmitted compressed packets. Note
    // /// this might only be relevant for devices that support
    // /// compression (e.g: PPP).
    // tx_compressed: usize,
    // old_tx_compressed: usize,
    /// Whether or not the above data has been updated during refresh
    updated: bool,
}

impl NetworkData {
    fn update(&mut self, path: &str, data: &mut Vec<u8>) {
        let path = &Path::new("/sys/class/net/").join(path).join("statistics");
        old_and_new!(self, rx_bytes, old_rx_bytes, read(path, "rx_bytes", data));
        old_and_new!(self, tx_bytes, old_tx_bytes, read(path, "tx_bytes", data));
        old_and_new!(
            self,
            rx_packets,
            old_rx_packets,
            read(path, "rx_packets", data)
        );
        old_and_new!(
            self,
            tx_packets,
            old_tx_packets,
            read(path, "tx_packets", data)
        );
        old_and_new!(
            self,
            rx_errors,
            old_rx_errors,
            read(path, "rx_errors", data)
        );
        old_and_new!(
            self,
            tx_errors,
            old_tx_errors,
            read(path, "tx_errors", data)
        );
        // old_and_new!(
        //     self,
        //     rx_compressed,
        //     old_rx_compressed,
        //     read(path, "rx_compressed", data)
        // );
        // old_and_new!(
        //     self,
        //     tx_compressed,
        //     old_tx_compressed,
        //     read(path, "tx_compressed", data)
        // );
    }
}

impl NetworkExt for NetworkData {
    fn get_received(&self) -> u64 {
        self.rx_bytes.saturating_sub(self.old_rx_bytes)
    }

    fn get_total_received(&self) -> u64 {
        self.rx_bytes
    }

    fn get_transmitted(&self) -> u64 {
        self.tx_bytes.saturating_sub(self.old_tx_bytes)
    }

    fn get_total_transmitted(&self) -> u64 {
        self.tx_bytes
    }

    fn get_packets_received(&self) -> u64 {
        self.rx_packets.saturating_sub(self.old_rx_packets)
    }

    fn get_total_packets_received(&self) -> u64 {
        self.rx_packets
    }

    fn get_packets_transmitted(&self) -> u64 {
        self.tx_packets.saturating_sub(self.old_tx_packets)
    }

    fn get_total_packets_transmitted(&self) -> u64 {
        self.tx_packets
    }

    fn get_errors_on_received(&self) -> u64 {
        self.rx_errors.saturating_sub(self.old_rx_errors)
    }

    fn get_total_errors_on_received(&self) -> u64 {
        self.rx_errors
    }

    fn get_errors_on_transmitted(&self) -> u64 {
        self.tx_errors.saturating_sub(self.old_tx_errors)
    }

    fn get_total_errors_on_transmitted(&self) -> u64 {
        self.tx_errors
    }
}

#[cfg(test)]
mod test {
    use super::refresh_networks_list_from_sysfs;
    use std::collections::HashMap;
    use std::fs;

    #[test]
    fn refresh_networks_list_add_interface() {
        let sys_net_dir = tempfile::tempdir().expect("failed to create temporary directory");

        fs::create_dir(sys_net_dir.path().join("itf1")).expect("failed to create subdirectory");

        let mut interfaces = HashMap::new();

        refresh_networks_list_from_sysfs(&mut interfaces, sys_net_dir.path());
        assert_eq!(interfaces.keys().collect::<Vec<_>>(), ["itf1"]);

        fs::create_dir(sys_net_dir.path().join("itf2")).expect("failed to create subdirectory");

        refresh_networks_list_from_sysfs(&mut interfaces, sys_net_dir.path());
        let mut itf_names: Vec<String> = interfaces.keys().map(|n| n.to_owned()).collect();
        itf_names.sort();
        assert_eq!(itf_names, ["itf1", "itf2"]);
    }

    #[test]
    fn refresh_networks_list_remove_interface() {
        let sys_net_dir = tempfile::tempdir().expect("failed to create temporary directory");

        let itf1_dir = sys_net_dir.path().join("itf1");
        let itf2_dir = sys_net_dir.path().join("itf2");
        fs::create_dir(&itf1_dir).expect("failed to create subdirectory");
        fs::create_dir(&itf2_dir).expect("failed to create subdirectory");

        let mut interfaces = HashMap::new();

        refresh_networks_list_from_sysfs(&mut interfaces, sys_net_dir.path());
        let mut itf_names: Vec<String> = interfaces.keys().map(|n| n.to_owned()).collect();
        itf_names.sort();
        assert_eq!(itf_names, ["itf1", "itf2"]);

        fs::remove_dir(&itf1_dir).expect("failed to remove subdirectory");

        refresh_networks_list_from_sysfs(&mut interfaces, sys_net_dir.path());
        assert_eq!(interfaces.keys().collect::<Vec<_>>(), ["itf2"]);
    }
}
<|endoftext|>


<commit_before>#![unstable(issue = "none", feature = "windows_stdio")]

use crate::io;
use crate::mem::ManuallyDrop;
use crate::os::windows::io::FromRawHandle;
use crate::sys::c;
use crate::sys::handle::Handle;

pub struct Stdin {}
pub struct Stdout;
pub struct Stderr;

const MAX_BUFFER_SIZE: usize = 8192;
pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;

pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
    let handle = unsafe { c::GetStdHandle(handle_id) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
    } else {
        Ok(handle)
    }
}

fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
    let handle = get_handle(handle_id)?;
    let handle = unsafe { Handle::from_raw_handle(handle) };
    ManuallyDrop::new(handle).write(data)
}

impl Stdin {
    pub const fn new() -> Stdin {
        Stdin {}
    }
}

impl io::Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = get_handle(c::STD_INPUT_HANDLE)?;
        let handle = unsafe { Handle::from_raw_handle(handle) };
        ManuallyDrop::new(handle).read(buf)
    }
}

impl Stdout {
    pub const fn new() -> Stdout {
        Stdout
    }
}

impl io::Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_OUTPUT_HANDLE, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub const fn new() -> Stderr {
        Stderr
    }
}

impl io::Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_ERROR_HANDLE, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Some(Stderr::new())
}
<commit_msg>Reason safety for unsafe blocks for uwp stdin<commit_after>#![unstable(issue = "none", feature = "windows_stdio")]

use crate::io;
use crate::mem::ManuallyDrop;
use crate::os::windows::io::FromRawHandle;
use crate::sys::c;
use crate::sys::handle::Handle;

pub struct Stdin {}
pub struct Stdout;
pub struct Stderr;

const MAX_BUFFER_SIZE: usize = 8192;
pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;

pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
    let handle = unsafe { c::GetStdHandle(handle_id) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
    } else {
        Ok(handle)
    }
}

fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
    let handle = get_handle(handle_id)?;
    // SAFETY: The handle returned from `get_handle` must be valid and non-null.
    let handle = unsafe { Handle::from_raw_handle(handle) };
    ManuallyDrop::new(handle).write(data)
}

impl Stdin {
    pub const fn new() -> Stdin {
        Stdin {}
    }
}

impl io::Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = get_handle(c::STD_INPUT_HANDLE)?;
        // SAFETY: The handle returned from `get_handle` must be valid and non-null.
        let handle = unsafe { Handle::from_raw_handle(handle) };
        ManuallyDrop::new(handle).read(buf)
    }
}

impl Stdout {
    pub const fn new() -> Stdout {
        Stdout
    }
}

impl io::Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_OUTPUT_HANDLE, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub const fn new() -> Stderr {
        Stderr
    }
}

impl io::Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_ERROR_HANDLE, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Some(Stderr::new())
}
<|endoftext|>


<commit_before>use nix::sys::time::{TimeSpec, TimeValLike};
use nix::sys::timerfd::{
    ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags,
};
use std::time::Instant;

#[test]
pub fn test_timerfd_oneshot() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    let before = Instant::now();

    timer
        .set(
            Expiration::OneShot(TimeSpec::seconds(1)),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.wait().unwrap();

    let millis = before.elapsed().as_millis();
    assert!(millis > 900);
}

#[test]
pub fn test_timerfd_interval() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    let before = Instant::now();
    timer
        .set(
            Expiration::IntervalDelayed(
                TimeSpec::seconds(1),
                TimeSpec::seconds(2),
            ),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.wait().unwrap();

    let start_delay = before.elapsed().as_millis();
    assert!(start_delay > 900);

    timer.wait().unwrap();

    let interval_delay = before.elapsed().as_millis();
    assert!(interval_delay > 2900);
}

#[test]
pub fn test_timerfd_unset() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    timer
        .set(
            Expiration::OneShot(TimeSpec::seconds(1)),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.unset().unwrap();

    assert!(timer.get().unwrap() == None);
}
<commit_msg>Fix a new clippy lint<commit_after>use nix::sys::time::{TimeSpec, TimeValLike};
use nix::sys::timerfd::{
    ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags,
};
use std::time::Instant;

#[test]
pub fn test_timerfd_oneshot() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    let before = Instant::now();

    timer
        .set(
            Expiration::OneShot(TimeSpec::seconds(1)),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.wait().unwrap();

    let millis = before.elapsed().as_millis();
    assert!(millis > 900);
}

#[test]
pub fn test_timerfd_interval() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    let before = Instant::now();
    timer
        .set(
            Expiration::IntervalDelayed(
                TimeSpec::seconds(1),
                TimeSpec::seconds(2),
            ),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.wait().unwrap();

    let start_delay = before.elapsed().as_millis();
    assert!(start_delay > 900);

    timer.wait().unwrap();

    let interval_delay = before.elapsed().as_millis();
    assert!(interval_delay > 2900);
}

#[test]
pub fn test_timerfd_unset() {
    let timer =
        TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();

    timer
        .set(
            Expiration::OneShot(TimeSpec::seconds(1)),
            TimerSetTimeFlags::empty(),
        )
        .unwrap();

    timer.unset().unwrap();

    assert!(timer.get().unwrap().is_none());
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (paths) sublink subwords

use crate::common::util::*;

const SUB_DIR: &str = "subdir/deeper";
const SUB_DIR_LINKS: &str = "subdir/links";
const SUB_FILE: &str = "subdir/links/subwords.txt";
const SUB_LINK: &str = "subdir/links/sublink.txt";

#[test]
fn test_du_basics() {
    new_ucmd!().succeeds().no_stderr();
}
#[cfg(target_vendor = "apple")]
fn _du_basics(s: &str) {
    let answer = "32\t./subdir
8\t./subdir/deeper
24\t./subdir/links
40\t./
";
    assert_eq!(s, answer);
}
#[cfg(not(target_vendor = "apple"))]
fn _du_basics(s: &str) {
    let answer = "28\t./subdir
8\t./subdir/deeper
16\t./subdir/links
36\t./
";
    assert_eq!(s, answer);
}

#[test]
fn test_du_basics_subdir() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg(SUB_DIR).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_basics_subdir(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "4\tsubdir/deeper\n");
}
#[cfg(target_os = "windows")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "0\tsubdir/deeper\n");
}
#[cfg(target_os = "freebsd")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "8\tsubdir/deeper\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_basics_subdir(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "8\tsubdir/deeper\n");
    } else {
        assert_eq!(s, "0\tsubdir/deeper\n");
    }
}

#[test]
fn test_du_invalid_size() {
    new_ucmd!()
        .arg("--block-size=1fb4t")
        .arg("/tmp")
        .fails()
        .code_is(1)
        .stderr_only("du: invalid --block-size argument '1fb4t'");
    #[cfg(not(target_pointer_width = "128"))]
    new_ucmd!()
        .arg("--block-size=1Y")
        .arg("/tmp")
        .fails()
        .code_is(1)
        .stderr_only("du: --block-size argument '1Y' too large");
}

#[test]
fn test_du_basics_bad_name() {
    new_ucmd!()
        .arg("bad_name")
        .succeeds() // TODO: replace with ".fails()" once `du` is fixed
        .stderr_only("du: bad_name: No such file or directory\n");
}

#[test]
fn test_du_soft_link() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.symlink_file(SUB_FILE, SUB_LINK);

    let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_soft_link(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_soft_link(s: &str) {
    // 'macos' host variants may have `du` output variation for soft links
    assert!((s == "12\tsubdir/links\n") || (s == "16\tsubdir/links\n"));
}
#[cfg(target_os = "windows")]
fn _du_soft_link(s: &str) {
    assert_eq!(s, "8\tsubdir/links\n");
}
#[cfg(target_os = "freebsd")]
fn _du_soft_link(s: &str) {
    assert_eq!(s, "16\tsubdir/links\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_soft_link(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "16\tsubdir/links\n");
    } else {
        assert_eq!(s, "8\tsubdir/links\n");
    }
}

#[test]
fn test_du_hard_link() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.hard_link(SUB_FILE, SUB_LINK);

    let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    // We do not double count hard links as the inodes are identical
    _du_hard_link(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "12\tsubdir/links\n")
}
#[cfg(target_os = "windows")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "8\tsubdir/links\n")
}
#[cfg(target_os = "freebsd")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "16\tsubdir/links\n")
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_hard_link(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "16\tsubdir/links\n");
    } else {
        assert_eq!(s, "8\tsubdir/links\n");
    }
}

#[test]
fn test_du_d_flag() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("-d1").succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg("-d1").run();
        if result_reference.succeeded() {
            assert_eq!(
                // TODO: gnu `du` doesn't use trailing "/" here
                // result.stdout_str(), result_reference.stdout_str()
                result.stdout_str().trim_end_matches("/\n"),
                result_reference.stdout_str().trim_end_matches('\n')
            );
            return;
        }
    }
    _du_d_flag(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "16\t./subdir\n20\t./\n");
}
#[cfg(target_os = "windows")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "8\t./subdir\n8\t./\n");
}
#[cfg(target_os = "freebsd")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "28\t./subdir\n36\t./\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_d_flag(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "28\t./subdir\n36\t./\n");
    } else {
        assert_eq!(s, "8\t./subdir\n8\t./\n");
    }
}

#[test]
fn test_du_h_flag_empty_file() {
    new_ucmd!()
        .arg("-h")
        .arg("empty.txt")
        .succeeds()
        .stdout_only("0\tempty.txt\n");
}

#[cfg(feature = "touch")]
#[test]
fn test_du_time() {
    let scene = TestScenario::new(util_name!());

    scene
        .ccmd("touch")
        .arg("-a")
        .arg("-t")
        .arg("201505150000")
        .arg("date_test")
        .succeeds();

    scene
        .ccmd("touch")
        .arg("-m")
        .arg("-t")
        .arg("201606160000")
        .arg("date_test")
        .succeeds();

    let result = scene.ucmd().arg("--time").arg("date_test").succeeds();
    result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");

    let result = scene.ucmd().arg("--time=atime").arg("date_test").succeeds();
    result.stdout_only("0\t2015-05-15 00:00\tdate_test\n");

    let result = scene.ucmd().arg("--time=ctime").arg("date_test").succeeds();
    result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");

    #[cfg(not(target_env = "musl"))]
    {
        use regex::Regex;

        let re_birth =
            Regex::new(r"0\t[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\tdate_test").unwrap();
        let result = scene.ucmd().arg("--time=birth").arg("date_test").succeeds();
        result.stdout_matches(&re_birth);
    }
}

#[cfg(not(target_os = "windows"))]
#[cfg(feature = "chmod")]
#[test]
fn test_du_no_permission() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.mkdir_all(SUB_DIR_LINKS);

    scene.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds();

    let result = scene.ucmd().arg(SUB_DIR_LINKS).run(); // TODO: replace with ".fails()" once `du` is fixed
    result.stderr_contains(
        "du: cannot read directory ‘subdir/links‘: Permission denied (os error 13)",
    );

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).fails();
        if result_reference
            .stderr_str()
            .contains("du: cannot read directory 'subdir/links': Permission denied")
        {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }

    _du_no_permission(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_no_permission(s: &str) {
    assert_eq!(s, "0\tsubdir/links\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_no_permission(s: &str) {
    assert_eq!(s, "4\tsubdir/links\n");
}

#[test]
fn test_du_one_file_system() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("-x").arg(SUB_DIR).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg("-x").arg(SUB_DIR).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_basics_subdir(result.stdout_str());
}
<commit_msg>tests: Add test for du threshold feature<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (paths) sublink subwords

use crate::common::util::*;

const SUB_DIR: &str = "subdir/deeper";
const SUB_DIR_LINKS: &str = "subdir/links";
const SUB_FILE: &str = "subdir/links/subwords.txt";
const SUB_LINK: &str = "subdir/links/sublink.txt";

#[test]
fn test_du_basics() {
    new_ucmd!().succeeds().no_stderr();
}
#[cfg(target_vendor = "apple")]
fn _du_basics(s: &str) {
    let answer = "32\t./subdir
8\t./subdir/deeper
24\t./subdir/links
40\t./
";
    assert_eq!(s, answer);
}
#[cfg(not(target_vendor = "apple"))]
fn _du_basics(s: &str) {
    let answer = "28\t./subdir
8\t./subdir/deeper
16\t./subdir/links
36\t./
";
    assert_eq!(s, answer);
}

#[test]
fn test_du_basics_subdir() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg(SUB_DIR).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_basics_subdir(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "4\tsubdir/deeper\n");
}
#[cfg(target_os = "windows")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "0\tsubdir/deeper\n");
}
#[cfg(target_os = "freebsd")]
fn _du_basics_subdir(s: &str) {
    assert_eq!(s, "8\tsubdir/deeper\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_basics_subdir(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "8\tsubdir/deeper\n");
    } else {
        assert_eq!(s, "0\tsubdir/deeper\n");
    }
}

#[test]
fn test_du_invalid_size() {
    let args = &["block-size", "threshold"];
    for s in args {
        new_ucmd!()
            .arg(format!("--{}=1fb4t", s))
            .arg("/tmp")
            .fails()
            .code_is(1)
            .stderr_only(format!("du: invalid --{} argument '1fb4t'", s));
        #[cfg(not(target_pointer_width = "128"))]
        new_ucmd!()
            .arg(format!("--{}=1Y", s))
            .arg("/tmp")
            .fails()
            .code_is(1)
            .stderr_only(format!("du: --{} argument '1Y' too large", s));
    }
}

#[test]
fn test_du_basics_bad_name() {
    new_ucmd!()
        .arg("bad_name")
        .succeeds() // TODO: replace with ".fails()" once `du` is fixed
        .stderr_only("du: bad_name: No such file or directory\n");
}

#[test]
fn test_du_soft_link() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.symlink_file(SUB_FILE, SUB_LINK);

    let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_soft_link(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_soft_link(s: &str) {
    // 'macos' host variants may have `du` output variation for soft links
    assert!((s == "12\tsubdir/links\n") || (s == "16\tsubdir/links\n"));
}
#[cfg(target_os = "windows")]
fn _du_soft_link(s: &str) {
    assert_eq!(s, "8\tsubdir/links\n");
}
#[cfg(target_os = "freebsd")]
fn _du_soft_link(s: &str) {
    assert_eq!(s, "16\tsubdir/links\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_soft_link(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "16\tsubdir/links\n");
    } else {
        assert_eq!(s, "8\tsubdir/links\n");
    }
}

#[test]
fn test_du_hard_link() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.hard_link(SUB_FILE, SUB_LINK);

    let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    // We do not double count hard links as the inodes are identical
    _du_hard_link(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "12\tsubdir/links\n")
}
#[cfg(target_os = "windows")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "8\tsubdir/links\n")
}
#[cfg(target_os = "freebsd")]
fn _du_hard_link(s: &str) {
    assert_eq!(s, "16\tsubdir/links\n")
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_hard_link(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "16\tsubdir/links\n");
    } else {
        assert_eq!(s, "8\tsubdir/links\n");
    }
}

#[test]
fn test_du_d_flag() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("-d1").succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg("-d1").run();
        if result_reference.succeeded() {
            assert_eq!(
                // TODO: gnu `du` doesn't use trailing "/" here
                // result.stdout_str(), result_reference.stdout_str()
                result.stdout_str().trim_end_matches("/\n"),
                result_reference.stdout_str().trim_end_matches('\n')
            );
            return;
        }
    }
    _du_d_flag(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "16\t./subdir\n20\t./\n");
}
#[cfg(target_os = "windows")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "8\t./subdir\n8\t./\n");
}
#[cfg(target_os = "freebsd")]
fn _du_d_flag(s: &str) {
    assert_eq!(s, "28\t./subdir\n36\t./\n");
}
#[cfg(all(
    not(target_vendor = "apple"),
    not(target_os = "windows"),
    not(target_os = "freebsd")
))]
fn _du_d_flag(s: &str) {
    // MS-WSL linux has altered expected output
    if !uucore::os::is_wsl_1() {
        assert_eq!(s, "28\t./subdir\n36\t./\n");
    } else {
        assert_eq!(s, "8\t./subdir\n8\t./\n");
    }
}

#[test]
fn test_du_h_flag_empty_file() {
    new_ucmd!()
        .arg("-h")
        .arg("empty.txt")
        .succeeds()
        .stdout_only("0\tempty.txt\n");
}

#[cfg(feature = "touch")]
#[test]
fn test_du_time() {
    let scene = TestScenario::new(util_name!());

    scene
        .ccmd("touch")
        .arg("-a")
        .arg("-t")
        .arg("201505150000")
        .arg("date_test")
        .succeeds();

    scene
        .ccmd("touch")
        .arg("-m")
        .arg("-t")
        .arg("201606160000")
        .arg("date_test")
        .succeeds();

    let result = scene.ucmd().arg("--time").arg("date_test").succeeds();
    result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");

    let result = scene.ucmd().arg("--time=atime").arg("date_test").succeeds();
    result.stdout_only("0\t2015-05-15 00:00\tdate_test\n");

    let result = scene.ucmd().arg("--time=ctime").arg("date_test").succeeds();
    result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");

    #[cfg(not(target_env = "musl"))]
    {
        use regex::Regex;

        let re_birth =
            Regex::new(r"0\t[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\tdate_test").unwrap();
        let result = scene.ucmd().arg("--time=birth").arg("date_test").succeeds();
        result.stdout_matches(&re_birth);
    }
}

#[cfg(not(target_os = "windows"))]
#[cfg(feature = "chmod")]
#[test]
fn test_du_no_permission() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.mkdir_all(SUB_DIR_LINKS);

    scene.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds();

    let result = scene.ucmd().arg(SUB_DIR_LINKS).run(); // TODO: replace with ".fails()" once `du` is fixed
    result.stderr_contains(
        "du: cannot read directory ‘subdir/links‘: Permission denied (os error 13)",
    );

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).fails();
        if result_reference
            .stderr_str()
            .contains("du: cannot read directory 'subdir/links': Permission denied")
        {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }

    _du_no_permission(result.stdout_str());
}

#[cfg(target_vendor = "apple")]
fn _du_no_permission(s: &str) {
    assert_eq!(s, "0\tsubdir/links\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_no_permission(s: &str) {
    assert_eq!(s, "4\tsubdir/links\n");
}

#[test]
fn test_du_one_file_system() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("-x").arg(SUB_DIR).succeeds();

    #[cfg(target_os = "linux")]
    {
        let result_reference = scene.cmd("du").arg("-x").arg(SUB_DIR).run();
        if result_reference.succeeded() {
            assert_eq!(result.stdout_str(), result_reference.stdout_str());
            return;
        }
    }
    _du_basics_subdir(result.stdout_str());
}

#[test]
fn test_du_threshold() {
    let scene = TestScenario::new(util_name!());

    let threshold = if cfg!(windows) { "7K" } else { "10K" };

    scene
        .ucmd()
        .arg(format!("--threshold={}", threshold))
        .succeeds()
        .stdout_contains("links")
        .stdout_does_not_contain("deeper");

    scene
        .ucmd()
        .arg(format!("--threshold=-{}", threshold))
        .succeeds()
        .stdout_does_not_contain("links")
        .stdout_contains("deeper");
}
<|endoftext|>


<commit_before>//  rtracker: bittorrent tracker
//  Copyright (C) 2019  Justin Noah <justinnoah@gmail.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License.
//
//  This program 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 Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <https://www.gnu.org/licenses/>.

// Reminder:
//
// NetworkEndian = Big Endian

use std::net::IpAddr;
use std::str::FromStr;

use bincode::{config as bin, serialized_size};

use packet_data_types::*;

pub fn parse_header(packet: &[u8]) -> PacketHeader {
    // In case we send extra by mistake, make sure to only parse the first 16 bytes
    debug!("Deserializing header of len {:?}", packet.len());

    let b: i64 = bin()
        .big_endian()
        .deserialize(&Vec::from(&packet[0..8]))
        .unwrap();
    debug!("ID Bytes: {:?}", &packet[0..8]);
    debug!("ID: {0:x}", b);

    let c: i32 = bin()
        .big_endian()
        .deserialize(&Vec::from(&packet[8..12]))
        .unwrap();
    debug!("Action Bytes: {:?}", &packet[8..12]);
    debug!("Action: {:?}", c);

    let d: i32 = bin()
        .big_endian()
        .deserialize(&Vec::from(&packet[12..]))
        .unwrap();
    debug!("TID Bytes: {:?}", &packet[12..]);
    debug!("TID: {:?}", d);

    bin()
        .big_endian()
        .deserialize::<PacketHeader>(&packet)
        .unwrap()
}

pub fn encode_server_connect(uuid: i64, tran_id: i32) -> Vec<u8> {
    let packet = ConnectionResponse {
        action: 0,
        transaction_id: tran_id,
        connection_id: uuid,
    };

    // Network Order, Bounded(16)
    let v: Vec<u8> = bin().big_endian().limit(16).serialize(&packet).unwrap();

    debug!("v: {:?}", v);
    v
}

pub fn decode_client_announce(packet: &[u8]) -> ClientAnnounce {
    let ca = ClientAnnounce::default();

    debug!("ClientAnnounce serialized size: {:?}", serialized_size(&ca));
    debug!("Deserializing Client Announce!");
    debug!("packet len : {:?}", packet.len());
    debug!("info_hash  : {:?}", &packet[..20]);
    debug!("peer_id    : {:?}", &packet[20..40]);
    debug!("downloaded : {:?}", &packet[40..48]);
    debug!("remaining  : {:?}", &packet[48..56]);
    debug!("uploaded   : {:?}", &packet[56..64]);
    debug!("event      : {:?}", &packet[64..68]);
    debug!("ip         : {:?}", &packet[68..72]);
    debug!("key        : {:?}", &packet[72..76]);
    debug!("num_want   : {:?}", &packet[76..80]);
    debug!("port       : {:?}", &packet[80..82]);
    if packet.len() > 82 {
        debug!("extensions : {:?}", &packet[82..]);
    }

    match bin().big_endian().deserialize(&packet) {
        Ok(x) => x,
        Err(p) => panic!("{:?}", p),
    }
}

pub fn encode_server_announce(
    transaction_id: i32,
    mut swarm: Vec<(String, i32)>,
    num_want: i32,
    leechers: i32,
    seeders: i32,
) -> Vec<u8> {
    let packet = ServerAnnounce {
        // Action for Announce is always 1
        action: 1,
        transaction_id,
        // 30min in secs
        interval: 1800,
        leechers,
        seeders,
    };

    let mut packet = bin().big_endian().serialize(&packet).unwrap();

    // Truncate the vector if num_want is smaller than the vector length
    if (num_want >= 0) && (num_want < swarm.len() as i32) {
        swarm.truncate(num_want as usize);
    }

    for peer in swarm {
        let (i, p): (String, i32) = peer;
        let ip = IpAddr::from_str(&i).unwrap();

        let mut ip_bytes = match ip {
            IpAddr::V4(ip4) => {
                let bytes = ip4.octets();
                let mut it: Vec<u8> = Vec::new();
                it.extend_from_slice(&bytes);
                it
            }
            IpAddr::V6(ip6) => {
                let double_bytes = ip6.segments();
                options()
                    .with_big_endian()
                    .with_limit(16)
                    .serialize(&double_bytes)
                    .unwrap()
            }
        };

        packet.append(&mut ip_bytes);
        packet.append(&mut bin().big_endian().limit(2).serialize(&(p as u16)).unwrap());
    }

    packet
}

pub fn encode_error(transaction_id: i32, error_string: &str) -> Vec<u8> {
    let err = ServerError {
        // Action (3 == Error)
        action: 3,
        transaction_id,
        error: String::from_str(error_string).unwrap(),
    };
    debug!("{:?}", err);

    // Return the packet
    bin().big_endian().serialize(error_string).unwrap()
}
<commit_msg>PacketHeader: debug parse only when debug!ing<commit_after>//  rtracker: bittorrent tracker
//  Copyright (C) 2019  Justin Noah <justinnoah@gmail.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License.
//
//  This program 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 Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <https://www.gnu.org/licenses/>.

// Reminder:
//
// NetworkEndian = Big Endian

use std::net::IpAddr;
use std::str::FromStr;

use bincode::{Options, options, serialized_size};

use packet_data_types::*;

pub fn parse_header(packet: &[u8]) -> PacketHeader {
    debug!("Deserializing header of len {:?}", packet.len());

    debug!("ID Bytes: {:?}", &packet[0..8]);
    debug!("ID: {0:x}", {
        bincode::deserialize::<i64>(&packet[0..8]).unwrap().to_be()
    });

    debug!("Action Bytes: {:?}", &packet[8..12]);
    debug!("Action: {:?}", {
        bincode::deserialize::<i32>(&packet[8..12]).unwrap().to_be()
    });

    debug!("TID Bytes: {:?}", &packet[12..16]);
    debug!("TID: {:?}", {
        bincode::deserialize::<i32>(&packet[12..16]).unwrap().to_be()
    });

    options().deserialize::<PacketHeader>(&packet[0..16]).unwrap()
}

pub fn encode_server_connect(uuid: i64, tran_id: i32) -> Vec<u8> {
    let packet = ConnectionResponse {
        action: 0,
        transaction_id: tran_id,
        connection_id: uuid,
    };

    // Network Order, Bounded(16)
    let v: Vec<u8> = bin().big_endian().limit(16).serialize(&packet).unwrap();

    debug!("v: {:?}", v);
    v
}

pub fn decode_client_announce(packet: &[u8]) -> ClientAnnounce {
    let ca = ClientAnnounce::default();

    debug!("ClientAnnounce serialized size: {:?}", serialized_size(&ca));
    debug!("Deserializing Client Announce!");
    debug!("packet len : {:?}", packet.len());
    debug!("info_hash  : {:?}", &packet[..20]);
    debug!("peer_id    : {:?}", &packet[20..40]);
    debug!("downloaded : {:?}", &packet[40..48]);
    debug!("remaining  : {:?}", &packet[48..56]);
    debug!("uploaded   : {:?}", &packet[56..64]);
    debug!("event      : {:?}", &packet[64..68]);
    debug!("ip         : {:?}", &packet[68..72]);
    debug!("key        : {:?}", &packet[72..76]);
    debug!("num_want   : {:?}", &packet[76..80]);
    debug!("port       : {:?}", &packet[80..82]);
    if packet.len() > 82 {
        debug!("extensions : {:?}", &packet[82..]);
    }

    match bin().big_endian().deserialize(&packet) {
        Ok(x) => x,
        Err(p) => panic!("{:?}", p),
    }
}

pub fn encode_server_announce(
    transaction_id: i32,
    mut swarm: Vec<(String, i32)>,
    num_want: i32,
    leechers: i32,
    seeders: i32,
) -> Vec<u8> {
    let packet = ServerAnnounce {
        // Action for Announce is always 1
        action: 1,
        transaction_id,
        // 30min in secs
        interval: 1800,
        leechers,
        seeders,
    };

    let mut packet = bin().big_endian().serialize(&packet).unwrap();

    // Truncate the vector if num_want is smaller than the vector length
    if (num_want >= 0) && (num_want < swarm.len() as i32) {
        swarm.truncate(num_want as usize);
    }

    for peer in swarm {
        let (i, p): (String, i32) = peer;
        let ip = IpAddr::from_str(&i).unwrap();

        let mut ip_bytes = match ip {
            IpAddr::V4(ip4) => {
                let bytes = ip4.octets();
                let mut it: Vec<u8> = Vec::new();
                it.extend_from_slice(&bytes);
                it
            }
            IpAddr::V6(ip6) => {
                let double_bytes = ip6.segments();
                options()
                    .with_big_endian()
                    .with_limit(16)
                    .serialize(&double_bytes)
                    .unwrap()
            }
        };

        packet.append(&mut ip_bytes);
        packet.append(&mut bin().big_endian().limit(2).serialize(&(p as u16)).unwrap());
    }

    packet
}

pub fn encode_error(transaction_id: i32, error_string: &str) -> Vec<u8> {
    let err = ServerError {
        // Action (3 == Error)
        action: 3,
        transaction_id,
        error: String::from_str(error_string).unwrap(),
    };
    debug!("{:?}", err);

    // Return the packet
    bin().big_endian().serialize(error_string).unwrap()
}
<|endoftext|>


<commit_before>use helpers::*;

#[test]
fn integers() {
    assert_eval("0", integer(0));
}

#[test]
fn booleans() {
    assert_eval("#t", bool(true));
}

#[test]
fn empty_list_() {
    assert_eval("()", empty_list());
}

#[test]
fn plus_procedure() {
    assert_eval("(+)", integer(0));
    assert_eval("(+ 2)", integer(2));
    assert_eval("(+ 2 3)", integer(5));
    assert_eval("(+ 2 3 -9)", integer(-4));
    assert_eval("(+ 2 3 -9 1)", integer(-3));

    assert_eval_err("(+ ())", wrong_argument_type(empty_list()));
}

#[test]
fn atoms() {
    assert_eval_err("atom", unbound_variable_error("atom"));
}
<commit_msg>Added tests about unappliability of booleans and integers.<commit_after>use helpers::*;

#[test]
fn integers() {
    assert_eval("0", integer(0));

    assert_eval_err("(0)", unappliable_value_error(integer(0)));
}

#[test]
fn booleans() {
    assert_eval("#t", bool(true));

    assert_eval_err("(#t)", unappliable_value_error(bool(true)));
}

#[test]
fn empty_list_() {
    assert_eval("()", empty_list());
}

#[test]
fn plus_procedure() {
    assert_eval("(+)", integer(0));
    assert_eval("(+ 2)", integer(2));
    assert_eval("(+ 2 3)", integer(5));
    assert_eval("(+ 2 3 -9)", integer(-4));
    assert_eval("(+ 2 3 -9 1)", integer(-3));

    assert_eval_err("(+ ())", wrong_argument_type(empty_list()));
}

#[test]
fn atoms() {
    assert_eval_err("atom", unbound_variable_error("atom"));
}
<|endoftext|>


<commit_before>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::{min, max};
use std::num::SignedInt;

#[derive(Eq, Show, Copy, Clone)]
pub struct Interval {
  lb: int,
  ub: int
}

impl PartialEq<Interval> for Interval
{
  fn eq(&self, other: &Interval) -> bool {
    if self.is_empty() && other.is_empty() { true }
    else { self.lb == other.lb && self.ub == other.ub }
  }
}

impl Interval
{
  pub fn new(lb: int, ub: int) -> Interval {
    Interval { lb: lb, ub: ub }
  }

  pub fn empty() -> Interval {
    Interval::new(1, 0)
  }

  pub fn singleton(x: int) -> Interval {
    Interval::new(x, x)
  }

  pub fn is_singleton(self) -> bool {
    self.lb == self.ub
  }

  pub fn size(self) -> uint {
    if self.is_empty() { 0 }
    else { (self.ub - self.lb + 1).abs() as uint }
  }

  pub fn is_empty(self) -> bool {
    self.lb > self.ub
  }

  pub fn has_member(self, x: int) -> bool {
    x >= self.lb && x <= self.ub
  }

  pub fn is_subset_of(self, i: Interval) -> bool {
    if self.is_empty() { true }
    else {
      self.lb >= i.lb && self.ub <= i.ub
    }
  }

  pub fn intersection(self, i: Interval) -> Interval {
    Interval::new(
      max(self.lb, i.lb),
      min(self.ub, i.ub)
    )
  }

  pub fn hull(self, i: Interval) -> Interval {
    if self.is_empty() { i }
    else if i.is_empty() { self }
    else {
      Interval::new(
        min(self.lb, i.lb),
        max(self.ub, i.ub)
      )
    }
  }

  fn disjoint(self, i: Interval) -> bool {
    self.lb > i.ub || i.lb > self.ub
  }
}

pub trait ToInterval {
  fn to_interval(self) -> Interval;
}

impl ToInterval for Interval {
  fn to_interval(self) -> Interval { self }
}

impl ToInterval for (int, int) {
  fn to_interval(self) -> Interval {
    let (a, b) = self;
    Interval::new(a, b)
  }
}

impl ToInterval for () {
  fn to_interval(self) -> Interval {
    Interval::empty()
  }
}

impl ToInterval for int {
  fn to_interval(self) -> Interval {
    Interval::singleton(self)
  }
}

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

  const empty: Interval = Interval {lb: 1, ub: 0};
  const invalid: Interval = Interval {lb: 10, ub: -10};
  const zero: Interval = Interval {lb: 0, ub: 0};
  const one: Interval = Interval {lb: 1, ub: 1};

  const i1_2: Interval = Interval {lb: 1, ub: 2};
  const i0_10: Interval = Interval {lb: 0, ub: 10};
  const i0_15: Interval = Interval {lb: 0, ub: 15};
  const im5_10: Interval = Interval {lb: -5, ub: 10};
  const i5_10: Interval = Interval {lb: 5, ub: 10};
  const i0_5: Interval = Interval {lb: 0, ub: 5};
  const i0_4: Interval = Interval {lb: 0, ub: 4};
  const im5_5: Interval = Interval {lb: -5, ub: 5};
  const i20_30: Interval = Interval {lb: 20, ub: 30};
  const im30_m20: Interval = Interval {lb: -30, ub: -20};

  #[test]
  fn to_interval_id_test() {
    let id = i1_2.clone().to_interval();
    assert!(i1_2 == id);
    assert!(i1_2 == Interval::new(1, 2));
  }

  #[test]
  fn equality_test() {
    assert!(empty == empty);
    assert!(empty == invalid);
    assert!(invalid == empty);
    assert!(i1_2 == i1_2);
  }

  #[test]
  fn size_test() {
    assert!(zero.size() == 1);
    assert!(one.size() == 1);
    assert!(empty.size() == 0);
    assert!(invalid.size() == 0);

    assert!(i1_2.size() == 2);
    assert!(i0_10.size() == 11);
    assert!(im30_m20.size() == 11);
  }

  #[test]
  fn member_test() {
    assert!(i1_2.has_member(1));
    assert!(i1_2.has_member(2));
    assert!(!i1_2.has_member(0));
    assert!(!i1_2.has_member(3));

    assert!(zero.has_member(0));
    assert!(!zero.has_member(1));

    assert!(!empty.has_member(0));
    assert!(!empty.has_member(1));
    assert!(!empty.has_member(5));
    assert!(!empty.has_member(-5));

    assert!(!invalid.has_member(0));
    assert!(!invalid.has_member(-11));
    assert!(!invalid.has_member(11));
  }

  #[test]
  fn is_subset_of_test() {
    let cases = vec![
      (zero, zero,          true),
      (i1_2, i1_2,          true),
      (empty, empty,        true),
      (invalid, invalid,    true)
    ];

    // For each cases (x, y, res)
    // * x and y are the values
    // * res is a tuple (r, sym) where
    //    * r is true if x is a subset of y
    //    * sym is true if y is a subset of x
    let sym_cases = vec![
      // ||
      // |-|
      (empty, zero,         (true, false)),
      (invalid, zero,       (true, false)),
      (empty, invalid,      (true, true)),
      // ||
      //|--|
      (empty, i1_2,         (true, false)),
      (invalid, i1_2,       (true, false)),
      //  |--|
      // |----|
      (i1_2, i0_10,         (true, false)),
      // |--|
      //     |--|
      (i0_4, i5_10,         (false, false)),
      // |--|
      //    |--|
      (i0_5, i5_10,         (false, false)),
      // |---|
      //   |---|
      (im5_5, i0_10,        (false, false)),
      // |--|
      //         |--|
      (i0_10, i20_30,       (false, false)),
      // |--|
      // |---|
      (i0_10, i0_15,        (true, false)),
      // |---|
      //  |--|
      (im5_10, i0_10,       (false, true))
    ];

    for (x,y,r) in cases.into_iter() {
      assert!(x.is_subset_of(y) == r, "{} is subset of {} is not equal to {}", x, y, r);
    }

    for (x,y,(r1,r2)) in sym_cases.into_iter() {
      assert!(x.is_subset_of(y) == r1, "{} is subset of {} is not equal to {}", x, y, r1);
      assert!(y.is_subset_of(x) == r2, "{} is subset of {} is not equal to {}", y, x, r2);
    }
  }

  #[test]
  fn intersection_test() {
    let cases = vec![
      (zero, zero,          zero),
      (i1_2, i1_2,          i1_2),
      (empty, empty,        empty),
      (invalid, invalid,    invalid)
    ];

    // For each cases (x, y, res)
    // * x and y are the values
    // * res is the expected result, which should be the same
    // for x intersect y and y intersect x since the intersection
    // is commutative.
    let sym_cases = vec![
      // ||
      // |-|
      (empty, zero,         empty),
      (invalid, zero,       empty),
      (empty, invalid,      empty),
      // ||
      //|--|
      (empty, i1_2,         empty),
      (invalid, i1_2,       empty),
      //  |--|
      // |----|
      (i1_2, i0_10,         i1_2),
      // |--|
      //     |--|
      (i0_4, i5_10,         empty),
      // |--|
      //    |--|
      (i0_5, i5_10,         5.to_interval()),
      // |---|
      //   |---|
      (im5_5, i0_10,        (0,5).to_interval()),
      // |--|
      //         |--|
      (i0_10, i20_30,       empty),
      // |--|
      // |---|
      (i0_10, i0_15,        i0_10),
      // |---|
      //  |--|
      (im5_10, i0_10,       i0_10)
    ];

    for (x,y,r) in cases.into_iter() {
      assert!(x.intersection(y) == r, "{} intersection {} is not equal to {}", x, y, r);
    }

    for (x,y,r) in sym_cases.into_iter() {
      assert!(x.intersection(y) == r, "{} intersection {} is not equal to {}", x, y, r);
      assert!(y.intersection(x) == r, "{} intersection {} is not equal to {}", y, x, r);
    }
  }
}<commit_msg>Add tests for the hull operation.<commit_after>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::{min, max};
use std::num::SignedInt;

#[derive(Eq, Show, Copy, Clone)]
pub struct Interval {
  lb: int,
  ub: int
}

impl PartialEq<Interval> for Interval
{
  fn eq(&self, other: &Interval) -> bool {
    if self.is_empty() && other.is_empty() { true }
    else { self.lb == other.lb && self.ub == other.ub }
  }
}

impl Interval
{
  pub fn new(lb: int, ub: int) -> Interval {
    Interval { lb: lb, ub: ub }
  }

  pub fn empty() -> Interval {
    Interval::new(1, 0)
  }

  pub fn singleton(x: int) -> Interval {
    Interval::new(x, x)
  }

  pub fn is_singleton(self) -> bool {
    self.lb == self.ub
  }

  pub fn size(self) -> uint {
    if self.is_empty() { 0 }
    else { (self.ub - self.lb + 1).abs() as uint }
  }

  pub fn is_empty(self) -> bool {
    self.lb > self.ub
  }

  pub fn has_member(self, x: int) -> bool {
    x >= self.lb && x <= self.ub
  }

  pub fn is_subset_of(self, i: Interval) -> bool {
    if self.is_empty() { true }
    else {
      self.lb >= i.lb && self.ub <= i.ub
    }
  }

  pub fn intersection(self, i: Interval) -> Interval {
    Interval::new(
      max(self.lb, i.lb),
      min(self.ub, i.ub)
    )
  }

  pub fn hull(self, i: Interval) -> Interval {
    if self.is_empty() { i }
    else if i.is_empty() { self }
    else {
      Interval::new(
        min(self.lb, i.lb),
        max(self.ub, i.ub)
      )
    }
  }

  fn disjoint(self, i: Interval) -> bool {
    self.lb > i.ub || i.lb > self.ub
  }
}

pub trait ToInterval {
  fn to_interval(self) -> Interval;
}

impl ToInterval for Interval {
  fn to_interval(self) -> Interval { self }
}

impl ToInterval for (int, int) {
  fn to_interval(self) -> Interval {
    let (a, b) = self;
    Interval::new(a, b)
  }
}

impl ToInterval for () {
  fn to_interval(self) -> Interval {
    Interval::empty()
  }
}

impl ToInterval for int {
  fn to_interval(self) -> Interval {
    Interval::singleton(self)
  }
}

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

  const empty: Interval = Interval {lb: 1, ub: 0};
  const invalid: Interval = Interval {lb: 10, ub: -10};
  const zero: Interval = Interval {lb: 0, ub: 0};
  const one: Interval = Interval {lb: 1, ub: 1};

  const i1_2: Interval = Interval {lb: 1, ub: 2};
  const i0_10: Interval = Interval {lb: 0, ub: 10};
  const i0_15: Interval = Interval {lb: 0, ub: 15};
  const im5_10: Interval = Interval {lb: -5, ub: 10};
  const i5_10: Interval = Interval {lb: 5, ub: 10};
  const i0_5: Interval = Interval {lb: 0, ub: 5};
  const i0_4: Interval = Interval {lb: 0, ub: 4};
  const im5_5: Interval = Interval {lb: -5, ub: 5};
  const i20_30: Interval = Interval {lb: 20, ub: 30};
  const im30_m20: Interval = Interval {lb: -30, ub: -20};

  #[test]
  fn to_interval_id_test() {
    let id = i1_2.clone().to_interval();
    assert!(i1_2 == id);
    assert!(i1_2 == Interval::new(1, 2));
  }

  #[test]
  fn equality_test() {
    assert!(empty == empty);
    assert!(empty == invalid);
    assert!(invalid == empty);
    assert!(i1_2 == i1_2);
  }

  #[test]
  fn size_test() {
    assert!(zero.size() == 1);
    assert!(one.size() == 1);
    assert!(empty.size() == 0);
    assert!(invalid.size() == 0);

    assert!(i1_2.size() == 2);
    assert!(i0_10.size() == 11);
    assert!(im30_m20.size() == 11);
  }

  #[test]
  fn member_test() {
    assert!(i1_2.has_member(1));
    assert!(i1_2.has_member(2));
    assert!(!i1_2.has_member(0));
    assert!(!i1_2.has_member(3));

    assert!(zero.has_member(0));
    assert!(!zero.has_member(1));

    assert!(!empty.has_member(0));
    assert!(!empty.has_member(1));
    assert!(!empty.has_member(5));
    assert!(!empty.has_member(-5));

    assert!(!invalid.has_member(0));
    assert!(!invalid.has_member(-11));
    assert!(!invalid.has_member(11));
  }

  #[test]
  fn is_subset_of_test() {
    let cases = vec![
      (zero, zero,          true),
      (i1_2, i1_2,          true),
      (empty, empty,        true),
      (invalid, invalid,    true)
    ];

    // For each cases (x, y, res)
    // * x and y are the values
    // * res is a tuple (r, sym) where
    //    * r is true if x is a subset of y
    //    * sym is true if y is a subset of x
    let sym_cases = vec![
      // ||
      // |-|
      (empty, zero,         (true, false)),
      (invalid, zero,       (true, false)),
      (empty, invalid,      (true, true)),
      // ||
      //|--|
      (empty, i1_2,         (true, false)),
      (invalid, i1_2,       (true, false)),
      //  |--|
      // |----|
      (i1_2, i0_10,         (true, false)),
      // |--|
      //     |--|
      (i0_4, i5_10,         (false, false)),
      // |--|
      //    |--|
      (i0_5, i5_10,         (false, false)),
      // |---|
      //   |---|
      (im5_5, i0_10,        (false, false)),
      // |--|
      //         |--|
      (i0_10, i20_30,       (false, false)),
      // |--|
      // |---|
      (i0_10, i0_15,        (true, false)),
      // |---|
      //  |--|
      (im5_10, i0_10,       (false, true))
    ];

    for (x,y,r) in cases.into_iter() {
      assert!(x.is_subset_of(y) == r, "{} is subset of {} is not equal to {}", x, y, r);
    }

    for (x,y,(r1,r2)) in sym_cases.into_iter() {
      assert!(x.is_subset_of(y) == r1, "{} is subset of {} is not equal to {}", x, y, r1);
      assert!(y.is_subset_of(x) == r2, "{} is subset of {} is not equal to {}", y, x, r2);
    }
  }

  #[test]
  fn intersection_test() {
    let cases = vec![
      (zero, zero,          zero),
      (i1_2, i1_2,          i1_2),
      (empty, empty,        empty),
      (invalid, invalid,    invalid)
    ];

    // For each cases (x, y, res)
    // * x and y are the values
    // * res is the expected result, which should be the same
    // for x intersect y and y intersect x since the intersection
    // is commutative.
    let sym_cases = vec![
      // ||
      // |-|
      (empty, zero,         empty),
      (invalid, zero,       empty),
      (empty, invalid,      empty),
      // ||
      //|--|
      (empty, i1_2,         empty),
      (invalid, i1_2,       empty),
      //  |--|
      // |----|
      (i1_2, i0_10,         i1_2),
      // |--|
      //     |--|
      (i0_4, i5_10,         empty),
      // |--|
      //    |--|
      (i0_5, i5_10,         5.to_interval()),
      // |---|
      //   |---|
      (im5_5, i0_10,        (0,5).to_interval()),
      // |--|
      //         |--|
      (i0_10, i20_30,       empty),
      // |--|
      // |---|
      (i0_10, i0_15,        i0_10),
      // |---|
      //  |--|
      (im5_10, i0_10,       i0_10)
    ];

    for (x,y,r) in cases.into_iter() {
      assert!(x.intersection(y) == r, "{} intersection {} is not equal to {}", x, y, r);
    }

    for (x,y,r) in sym_cases.into_iter() {
      assert!(x.intersection(y) == r, "{} intersection {} is not equal to {}", x, y, r);
      assert!(y.intersection(x) == r, "{} intersection {} is not equal to {}", y, x, r);
    }
  }

  #[test]
  fn hull_test() {
    let cases = vec![
      (zero, zero,          zero),
      (i1_2, i1_2,          i1_2),
      (empty, empty,        empty),
      (invalid, invalid,    invalid)
    ];

    // For each cases (x, y, res)
    // * x and y are the values
    // * res is the expected result, which should be the same
    // for x intersect y and y intersect x since the intersection
    // is commutative.
    let sym_cases = vec![
      // ||
      // |-|
      (empty, zero,         zero),
      (invalid, zero,       zero),
      (empty, invalid,      empty),
      // ||
      //|--|
      (empty, i1_2,         i1_2),
      (invalid, i1_2,       i1_2),
      //  |--|
      // |----|
      (i1_2, i0_10,         i0_10),
      // |--|
      //     |--|
      (i0_4, i5_10,         i0_10),
      // |--|
      //    |--|
      (i0_5, i5_10,         i0_10),
      // |---|
      //   |---|
      (im5_5, i0_10,        (-5,10).to_interval()),
      // |--|
      //         |--|
      (i0_10, i20_30,       (0,30).to_interval()),
      // |--|
      // |---|
      (i0_10, i0_15,        i0_15),
      // |---|
      //  |--|
      (im5_10, i0_10,       im5_10)
    ];

    for (x,y,r) in cases.into_iter() {
      assert!(x.hull(y) == r, "{} hull {} is not equal to {}", x, y, r);
    }

    for (x,y,r) in sym_cases.into_iter() {
      assert!(x.hull(y) == r, "{} hull {} is not equal to {}", x, y, r);
      assert!(y.hull(x) == r, "{} hull {} is not equal to {}", y, x, r);
    }
  }
}<|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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![cfg_attr(feature = "servo", feature(proc_macro))]

#![deny(warnings)]
#![cfg_attr(feature = "servo", deny(missing_docs))]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
#[macro_use] #[no_link]
extern crate cfg_if;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
extern crate num_integer;
extern crate num_traits;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate phf;
extern crate quickersort;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
#[cfg(feature = "servo")]
extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_traits;
extern crate time;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

pub mod animation;
#[allow(missing_docs)] // TODO: Under a rewrite.
pub mod atomic_refcell;
#[allow(missing_docs)] // TODO.
pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod keyframes;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
#[allow(missing_docs)]
pub mod media_queries;
pub mod owning_handle;
pub mod parallel;
pub mod parser;
pub mod restyle_hints;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_parser;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod sink;
pub mod str;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;
pub mod viewport;

use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever_atoms::Prefix;
#[cfg(feature = "servo")] pub use html5ever_atoms::LocalName;
#[cfg(feature = "servo")] pub use html5ever_atoms::Namespace;

/// The CSS properties supported by the style system.
// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Returns whether the two arguments point to the same value.
#[inline]
pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    try!(list[0].to_css(dest));

    for item in list.iter().skip(1) {
        try!(write!(dest, ", "));
        try!(item.to_css(dest));
    }

    Ok(())
}
<commit_msg>style: Require documentation also for a Gecko build.<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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![cfg_attr(feature = "servo", feature(proc_macro))]

#![deny(warnings)]
#![deny(missing_docs)]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
#[macro_use] #[no_link]
extern crate cfg_if;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
extern crate num_integer;
extern crate num_traits;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate phf;
extern crate quickersort;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
#[cfg(feature = "servo")]
extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_traits;
extern crate time;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

pub mod animation;
#[allow(missing_docs)] // TODO: Under a rewrite.
pub mod atomic_refcell;
#[allow(missing_docs)] // TODO.
pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod keyframes;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
#[allow(missing_docs)]
pub mod media_queries;
pub mod owning_handle;
pub mod parallel;
pub mod parser;
pub mod restyle_hints;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_parser;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod sink;
pub mod str;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;
pub mod viewport;

use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever_atoms::Prefix;
#[cfg(feature = "servo")] pub use html5ever_atoms::LocalName;
#[cfg(feature = "servo")] pub use html5ever_atoms::Namespace;

/// The CSS properties supported by the style system.
/// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code, missing_docs)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Returns whether the two arguments point to the same value.
#[inline]
pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    try!(list[0].to_css(dest));

    for item in list.iter().skip(1) {
        try!(write!(dest, ", "));
        try!(item.to_css(dest));
    }

    Ok(())
}
<|endoftext|>