<commit_before>use std::collections::hash_map::{HashMap, Entry};
use std::path::Path;

use url::Url;

use ffi;
use ffi::opt;
use ffi::easy::Easy;
use http::Response;
use http::body::{Body,ToBody};
use {ProgressCb,ErrCode};

use self::Method::{Get, Head, Post, Put, Patch, Delete};
use self::BodyType::{Fixed, Chunked};

const DEFAULT_TIMEOUT_MS: usize = 30_000;

pub struct Handle {
    easy: Easy,
}

impl Handle {
    pub fn new() -> Handle {
        return configure(Handle { easy: Easy::new() }
            .timeout(DEFAULT_TIMEOUT_MS)
            .connect_timeout(DEFAULT_TIMEOUT_MS));

        #[cfg(unix)]
        fn configure(handle: Handle) -> Handle {
            let probe = ::openssl::probe::probe();
            let handle = match probe.cert_file {
                Some(ref path) => handle.ssl_ca_info(path),
                None => handle,
            };
            match probe.cert_dir {
                Some(ref path) => handle.ssl_ca_path(path),
                None => handle,
            }
        }

        #[cfg(not(unix))]
        fn configure(handle: Handle) -> Handle { handle }
    }

    pub fn timeout(mut self, ms: usize) -> Handle {
        self.easy.setopt(opt::TIMEOUT_MS, ms).unwrap();
        self
    }

    pub fn connect_timeout(mut self, ms: usize) -> Handle {
        self.easy.setopt(opt::CONNECTTIMEOUT_MS, ms).unwrap();
        self
    }

    /// Set the time in seconds that the transfer speed should be below
    /// the `low_speed_limit` rate of bytes per second for the library to
    /// consider it too slow and abort.
    ///
    /// The default for this option is 0 which means that this option is
    /// disabled.
    pub fn low_speed_timeout(mut self, seconds: usize) -> Handle {
        self.easy.setopt(opt::LOW_SPEED_TIME, seconds).unwrap();
        self
    }

    /// Set the average transfer speed in bytes per second that the
    /// transfer should be below during `low_speed_timeout` seconds for
    /// libcurl to consider it to be too slow and abort.
    ///
    /// The default for this option is 0 which means that this option is
    /// disabled.
    pub fn low_speed_limit(mut self, bytes_per_second: usize) -> Handle {
        self.easy.setopt(opt::LOW_SPEED_LIMIT, bytes_per_second).unwrap();
        self
    }

    pub fn verbose(mut self) -> Handle {
        self.easy.setopt(opt::VERBOSE, 1).unwrap();
        self
    }

    pub fn proxy<U: ToUrl>(mut self, proxy: U) -> Handle {
        proxy.with_url_str(|s| {
            self.easy.setopt(opt::PROXY, s).unwrap();
        });

        self
    }

    pub fn ssl_ca_path(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::CAPATH, path).unwrap();
        self
    }

    pub fn ssl_ca_info(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::CAINFO, path).unwrap();
        self
    }

    pub fn cookie_jar(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::COOKIEJAR, path).unwrap();
        self
    }

    pub fn cookie_file(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::COOKIEFILE, path).unwrap();
        self
    }

    pub fn cookies(self, path: &Path) -> Handle {
        self.cookie_jar(path).cookie_file(path)
    }

    pub fn get<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Get).uri(uri)
    }

    pub fn head<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Head).uri(uri)
    }

    pub fn post<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Post).uri(uri).body(body)
    }

    pub fn put<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Put).uri(uri).body(body)
    }

    pub fn patch<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Patch).uri(uri).body(body)
    }

    pub fn delete<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Delete).uri(uri)
    }
}

#[derive(Copy, Clone)]
pub enum Method {
    Options,
    Get,
    Head,
    Post,
    Put,
    Patch,
    Delete,
    Trace,
    Connect
}

pub struct Request<'a, 'b> {
    err: Option<ErrCode>,
    handle: &'a mut Handle,
    method: Method,
    headers: HashMap<String, Vec<String>>,
    body: Option<Body<'b>>,
    body_type: Option<BodyType>,
    content_type: bool, // whether or not the content type was set
    expect_continue: bool, // whether to expect a 100 continue from the server
    progress: Option<Box<ProgressCb<'b>>>,
    follow: bool,
}

enum BodyType {
    Fixed(usize),
    Chunked,
}

impl<'a, 'b> Request<'a, 'b> {
    pub fn new(handle: &'a mut Handle, method: Method) -> Request<'a, 'b> {
        Request {
            err: None,
            handle: handle,
            method: method,
            headers: HashMap::new(),
            body: None,
            body_type: None,
            content_type: false,
            expect_continue: false,
            progress: None,
            follow: false,
        }
    }

    pub fn uri<U: ToUrl>(mut self, uri: U) -> Request<'a, 'b> {
        uri.with_url_str(|s| {
            match self.handle.easy.setopt(opt::URL, s) {
                Ok(_) => {}
                Err(e) => self.err = Some(e)
            }
        });

        self
    }

    pub fn body<B: ToBody<'b>>(mut self, body: B) -> Request<'a, 'b> {
        self.body = Some(body.to_body());
        self
    }

    pub fn content_type(mut self, ty: &str) -> Request<'a, 'b> {
        if !self.content_type {
            self.content_type = true;
            append_header(&mut self.headers, "Content-Type", ty);
        }

        self
    }

    pub fn content_length(mut self, len: usize) -> Request<'a, 'b> {
        self.body_type = Some(Fixed(len));
        self
    }

    pub fn chunked(mut self) -> Request<'a, 'b> {
        self.body_type = Some(Chunked);
        self
    }

    pub fn expect_continue(mut self) -> Request<'a, 'b> {
        self.expect_continue = true;
        self
    }

    pub fn header(mut self, name: &str, val: &str) -> Request<'a, 'b> {
        append_header(&mut self.headers, name, val);
        self
    }

    pub fn get_header(&self, name: &str) -> Option<&[String]> {
        self.headers.get(name).map(|a| &a[..])
    }

    pub fn headers<'c, 'd, I: Iterator<Item=(&'c str, &'d str)>>(mut self, hdrs: I) -> Request<'a, 'b> {
        for (name, val) in hdrs {
            append_header(&mut self.headers, name, val);
        }

        self
    }

    pub fn progress<F>(mut self, cb: F) -> Request<'a, 'b>
        where F: FnMut(usize, usize, usize, usize) + 'b
    {
        self.progress = Some(Box::new(cb) as Box<ProgressCb<'b>>);
        self
    }

    pub fn follow_redirects(mut self, follow: bool) -> Request<'a, 'b> {
        self.follow = follow;
        self
    }

    pub fn exec(self) -> Result<Response, ErrCode> {
        // Deconstruct the struct
        let Request {
            err,
            handle,
            method,
            mut headers,
            mut body,
            body_type,
            content_type,
            expect_continue,
            progress,
            follow,
            ..
        } = self;

        if follow {
            try!(handle.easy.setopt(opt::FOLLOWLOCATION, 1));
        }

        match err {
            Some(e) => return Err(e),
            None => {}
        }

        // Clear custom headers set from the previous request
        try!(handle.easy.setopt(opt::HTTPHEADER, 0));

        match method {
            Get => try!(handle.easy.setopt(opt::HTTPGET, 1)),
            Head => try!(handle.easy.setopt(opt::NOBODY, 1)),
            Post => try!(handle.easy.setopt(opt::POST, 1)),
            Put => try!(handle.easy.setopt(opt::UPLOAD, 1)),
            Patch => {
                try!(handle.easy.setopt(opt::CUSTOMREQUEST, "PATCH"));
                try!(handle.easy.setopt(opt::UPLOAD, 1));
            },
            Delete => {
                if body.is_some() {
                    try!(handle.easy.setopt(opt::UPLOAD, 1));
                }

                try!(handle.easy.setopt(opt::CUSTOMREQUEST, "DELETE"));
            }
            _ => unimplemented!()
        }

        match body.as_ref() {
            None => {}
            Some(body) => {
                let body_type = body_type.unwrap_or(match body.get_size() {
                    Some(len) => Fixed(len),
                    None => Chunked,
                });

                match body_type {
                    Fixed(len) => {
                        match method {
                            Post => try!(handle.easy.setopt(opt::POSTFIELDSIZE, len)),
                            Put | Patch | Delete  => try!(handle.easy.setopt(opt::INFILESIZE, len)),
                            _ => {
                                append_header(&mut headers, "Content-Length",
                                              &len.to_string());
                            }
                        }
                    }
                    Chunked => {
                        append_header(&mut headers, "Transfer-Encoding",
                                      "chunked");
                    }

                }

                if !content_type {
                    append_header(&mut headers, "Content-Type", "application/octet-stream");
                }

                if !expect_continue {
                    append_header(&mut headers, "Expect", "");
                }
            }
        }

        let mut ffi_headers = ffi::List::new();

        if !headers.is_empty() {
            let mut buf = Vec::new();

            for (k, v) in headers.iter() {
                buf.extend(k.bytes());
                buf.extend(": ".bytes());

                for v in v.iter() {
                    buf.extend(v.bytes());
                    buf.push(0);
                    ffi_headers.push_bytes(&buf);
                    buf.truncate(k.len() + 2);
                }

                buf.truncate(0);
            }

            try!(handle.easy.setopt(opt::HTTPHEADER, &ffi_headers));
        }

        handle.easy.perform(body.as_mut(), progress)
    }
}

fn append_header(map: &mut HashMap<String, Vec<String>>, key: &str, val: &str) {
    match map.entry(key.to_string()) {
        Entry::Vacant(entry) => {
            let mut values = Vec::new();
            values.push(val.to_string());
            entry.insert(values)
        },
        Entry::Occupied(entry) => entry.into_mut()
    };
}

pub trait ToUrl{
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str);
}

impl<'a> ToUrl for &'a str {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        f(self);
    }
}

impl<'a> ToUrl for &'a Url {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        self.to_string().with_url_str(f);
    }
}

impl ToUrl for String {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        self[..].with_url_str(f);
    }
}

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

    #[test]
    fn get_header() {
        let mut h = Handle::new();
        let r = h.get("/foo").header("foo", "bar");
        assert_eq!(r.get_header("foo"), Some(&["bar".to_string()][..]));
    }
}
<commit_msg>Add cookie method<commit_after>use std::collections::hash_map::{HashMap, Entry};
use std::path::Path;

use url::Url;

use ffi;
use ffi::opt;
use ffi::easy::Easy;
use http::Response;
use http::body::{Body,ToBody};
use {ProgressCb,ErrCode};

use self::Method::{Get, Head, Post, Put, Patch, Delete};
use self::BodyType::{Fixed, Chunked};

const DEFAULT_TIMEOUT_MS: usize = 30_000;

pub struct Handle {
    easy: Easy,
}

impl Handle {
    pub fn new() -> Handle {
        return configure(Handle { easy: Easy::new() }
            .timeout(DEFAULT_TIMEOUT_MS)
            .connect_timeout(DEFAULT_TIMEOUT_MS));

        #[cfg(unix)]
        fn configure(handle: Handle) -> Handle {
            let probe = ::openssl::probe::probe();
            let handle = match probe.cert_file {
                Some(ref path) => handle.ssl_ca_info(path),
                None => handle,
            };
            match probe.cert_dir {
                Some(ref path) => handle.ssl_ca_path(path),
                None => handle,
            }
        }

        #[cfg(not(unix))]
        fn configure(handle: Handle) -> Handle { handle }
    }

    pub fn timeout(mut self, ms: usize) -> Handle {
        self.easy.setopt(opt::TIMEOUT_MS, ms).unwrap();
        self
    }

    pub fn connect_timeout(mut self, ms: usize) -> Handle {
        self.easy.setopt(opt::CONNECTTIMEOUT_MS, ms).unwrap();
        self
    }

    /// Set the time in seconds that the transfer speed should be below
    /// the `low_speed_limit` rate of bytes per second for the library to
    /// consider it too slow and abort.
    ///
    /// The default for this option is 0 which means that this option is
    /// disabled.
    pub fn low_speed_timeout(mut self, seconds: usize) -> Handle {
        self.easy.setopt(opt::LOW_SPEED_TIME, seconds).unwrap();
        self
    }

    /// Set the average transfer speed in bytes per second that the
    /// transfer should be below during `low_speed_timeout` seconds for
    /// libcurl to consider it to be too slow and abort.
    ///
    /// The default for this option is 0 which means that this option is
    /// disabled.
    pub fn low_speed_limit(mut self, bytes_per_second: usize) -> Handle {
        self.easy.setopt(opt::LOW_SPEED_LIMIT, bytes_per_second).unwrap();
        self
    }

    pub fn verbose(mut self) -> Handle {
        self.easy.setopt(opt::VERBOSE, 1).unwrap();
        self
    }

    pub fn proxy<U: ToUrl>(mut self, proxy: U) -> Handle {
        proxy.with_url_str(|s| {
            self.easy.setopt(opt::PROXY, s).unwrap();
        });

        self
    }

    pub fn ssl_ca_path(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::CAPATH, path).unwrap();
        self
    }

    pub fn ssl_ca_info(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::CAINFO, path).unwrap();
        self
    }

    pub fn cookie_jar(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::COOKIEJAR, path).unwrap();
        self
    }

    pub fn cookie_file(mut self, path: &Path) -> Handle {
        self.easy.setopt(opt::COOKIEFILE, path).unwrap();
        self
    }

    pub fn cookies(self, path: &Path) -> Handle {
        self.cookie_jar(path).cookie_file(path)
    }

    pub fn cookie(mut self, cookie: &str) -> Handle {
        self.easy.setopt(opt::COOKIELIST, cookie).unwrap();
        self
    }

    pub fn get<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Get).uri(uri)
    }

    pub fn head<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Head).uri(uri)
    }

    pub fn post<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Post).uri(uri).body(body)
    }

    pub fn put<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Put).uri(uri).body(body)
    }

    pub fn patch<'a, 'b, U: ToUrl, B: ToBody<'b>>(&'a mut self, uri: U, body: B) -> Request<'a, 'b> {
        Request::new(self, Patch).uri(uri).body(body)
    }

    pub fn delete<'a, 'b, U: ToUrl>(&'a mut self, uri: U) -> Request<'a, 'b> {
        Request::new(self, Delete).uri(uri)
    }
}

#[derive(Copy, Clone)]
pub enum Method {
    Options,
    Get,
    Head,
    Post,
    Put,
    Patch,
    Delete,
    Trace,
    Connect
}

pub struct Request<'a, 'b> {
    err: Option<ErrCode>,
    handle: &'a mut Handle,
    method: Method,
    headers: HashMap<String, Vec<String>>,
    body: Option<Body<'b>>,
    body_type: Option<BodyType>,
    content_type: bool, // whether or not the content type was set
    expect_continue: bool, // whether to expect a 100 continue from the server
    progress: Option<Box<ProgressCb<'b>>>,
    follow: bool,
}

enum BodyType {
    Fixed(usize),
    Chunked,
}

impl<'a, 'b> Request<'a, 'b> {
    pub fn new(handle: &'a mut Handle, method: Method) -> Request<'a, 'b> {
        Request {
            err: None,
            handle: handle,
            method: method,
            headers: HashMap::new(),
            body: None,
            body_type: None,
            content_type: false,
            expect_continue: false,
            progress: None,
            follow: false,
        }
    }

    pub fn uri<U: ToUrl>(mut self, uri: U) -> Request<'a, 'b> {
        uri.with_url_str(|s| {
            match self.handle.easy.setopt(opt::URL, s) {
                Ok(_) => {}
                Err(e) => self.err = Some(e)
            }
        });

        self
    }

    pub fn body<B: ToBody<'b>>(mut self, body: B) -> Request<'a, 'b> {
        self.body = Some(body.to_body());
        self
    }

    pub fn content_type(mut self, ty: &str) -> Request<'a, 'b> {
        if !self.content_type {
            self.content_type = true;
            append_header(&mut self.headers, "Content-Type", ty);
        }

        self
    }

    pub fn content_length(mut self, len: usize) -> Request<'a, 'b> {
        self.body_type = Some(Fixed(len));
        self
    }

    pub fn chunked(mut self) -> Request<'a, 'b> {
        self.body_type = Some(Chunked);
        self
    }

    pub fn expect_continue(mut self) -> Request<'a, 'b> {
        self.expect_continue = true;
        self
    }

    pub fn header(mut self, name: &str, val: &str) -> Request<'a, 'b> {
        append_header(&mut self.headers, name, val);
        self
    }

    pub fn get_header(&self, name: &str) -> Option<&[String]> {
        self.headers.get(name).map(|a| &a[..])
    }

    pub fn headers<'c, 'd, I: Iterator<Item=(&'c str, &'d str)>>(mut self, hdrs: I) -> Request<'a, 'b> {
        for (name, val) in hdrs {
            append_header(&mut self.headers, name, val);
        }

        self
    }

    pub fn progress<F>(mut self, cb: F) -> Request<'a, 'b>
        where F: FnMut(usize, usize, usize, usize) + 'b
    {
        self.progress = Some(Box::new(cb) as Box<ProgressCb<'b>>);
        self
    }

    pub fn follow_redirects(mut self, follow: bool) -> Request<'a, 'b> {
        self.follow = follow;
        self
    }

    pub fn exec(self) -> Result<Response, ErrCode> {
        // Deconstruct the struct
        let Request {
            err,
            handle,
            method,
            mut headers,
            mut body,
            body_type,
            content_type,
            expect_continue,
            progress,
            follow,
            ..
        } = self;

        if follow {
            try!(handle.easy.setopt(opt::FOLLOWLOCATION, 1));
        }

        match err {
            Some(e) => return Err(e),
            None => {}
        }

        // Clear custom headers set from the previous request
        try!(handle.easy.setopt(opt::HTTPHEADER, 0));

        match method {
            Get => try!(handle.easy.setopt(opt::HTTPGET, 1)),
            Head => try!(handle.easy.setopt(opt::NOBODY, 1)),
            Post => try!(handle.easy.setopt(opt::POST, 1)),
            Put => try!(handle.easy.setopt(opt::UPLOAD, 1)),
            Patch => {
                try!(handle.easy.setopt(opt::CUSTOMREQUEST, "PATCH"));
                try!(handle.easy.setopt(opt::UPLOAD, 1));
            },
            Delete => {
                if body.is_some() {
                    try!(handle.easy.setopt(opt::UPLOAD, 1));
                }

                try!(handle.easy.setopt(opt::CUSTOMREQUEST, "DELETE"));
            }
            _ => unimplemented!()
        }

        match body.as_ref() {
            None => {}
            Some(body) => {
                let body_type = body_type.unwrap_or(match body.get_size() {
                    Some(len) => Fixed(len),
                    None => Chunked,
                });

                match body_type {
                    Fixed(len) => {
                        match method {
                            Post => try!(handle.easy.setopt(opt::POSTFIELDSIZE, len)),
                            Put | Patch | Delete  => try!(handle.easy.setopt(opt::INFILESIZE, len)),
                            _ => {
                                append_header(&mut headers, "Content-Length",
                                              &len.to_string());
                            }
                        }
                    }
                    Chunked => {
                        append_header(&mut headers, "Transfer-Encoding",
                                      "chunked");
                    }

                }

                if !content_type {
                    append_header(&mut headers, "Content-Type", "application/octet-stream");
                }

                if !expect_continue {
                    append_header(&mut headers, "Expect", "");
                }
            }
        }

        let mut ffi_headers = ffi::List::new();

        if !headers.is_empty() {
            let mut buf = Vec::new();

            for (k, v) in headers.iter() {
                buf.extend(k.bytes());
                buf.extend(": ".bytes());

                for v in v.iter() {
                    buf.extend(v.bytes());
                    buf.push(0);
                    ffi_headers.push_bytes(&buf);
                    buf.truncate(k.len() + 2);
                }

                buf.truncate(0);
            }

            try!(handle.easy.setopt(opt::HTTPHEADER, &ffi_headers));
        }

        handle.easy.perform(body.as_mut(), progress)
    }
}

fn append_header(map: &mut HashMap<String, Vec<String>>, key: &str, val: &str) {
    match map.entry(key.to_string()) {
        Entry::Vacant(entry) => {
            let mut values = Vec::new();
            values.push(val.to_string());
            entry.insert(values)
        },
        Entry::Occupied(entry) => entry.into_mut()
    };
}

pub trait ToUrl{
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str);
}

impl<'a> ToUrl for &'a str {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        f(self);
    }
}

impl<'a> ToUrl for &'a Url {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        self.to_string().with_url_str(f);
    }
}

impl ToUrl for String {
    fn with_url_str<F>(self, f: F) where F: FnOnce(&str) {
        self[..].with_url_str(f);
    }
}

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

    #[test]
    fn get_header() {
        let mut h = Handle::new();
        let r = h.get("/foo").header("foo", "bar");
        assert_eq!(r.get_header("foo"), Some(&["bar".to_string()][..]));
    }
}
<|endoftext|>


<commit_before>use crate::size_hint;
use crate::Itertools;

use alloc::vec::Vec;
use std::iter::FusedIterator;
use std::mem::replace;
use std::fmt;

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    clone_fields!(head, tail);
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // Require the right child to be present
    // This allows to find the index of the smallest child without a branch
    // that wouldn't be predicted if present
    while child + 1 < heap.len() {
        // pick the smaller of the two children
        // use aritmethic to avoid an unpredictable branch
        child += less_than(&heap[child+1], &heap[child]) as usize;

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
    // Check if the last (left) child was an only child
    // if it is then it has to be compared with the parent
    if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) {
        heap.swap(pos, child);
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](crate::Itertools::kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;

pub trait KMergePredicate<T> {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
}

#[derive(Clone, Debug)]
pub struct KMergeByLt;

impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        a < b
    }
}

impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        self(a, b)
    }
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    kmerge_by(iterable, KMergeByLt)
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](crate::Itertools::kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

impl<I, F> fmt::Debug for KMergeBy<I, F>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMergeBy, heap);
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
    KMergeBy { heap, less_than }
}

impl<I, F> Clone for KMergeBy<I, F>
    where I: Iterator + Clone,
          I::Item: Clone,
          F: Clone,
{
    clone_fields!(heap, less_than);
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}

impl<I, F> FusedIterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{}
<commit_msg>Canonicalize some free functions (3) kmerge: documentation<commit_after>use crate::size_hint;
use crate::Itertools;

use alloc::vec::Vec;
use std::iter::FusedIterator;
use std::mem::replace;
use std::fmt;

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    clone_fields!(head, tail);
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // Require the right child to be present
    // This allows to find the index of the smallest child without a branch
    // that wouldn't be predicted if present
    while child + 1 < heap.len() {
        // pick the smaller of the two children
        // use aritmethic to avoid an unpredictable branch
        child += less_than(&heap[child+1], &heap[child]) as usize;

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
    // Check if the last (left) child was an only child
    // if it is then it has to be compared with the parent
    if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) {
        heap.swap(pos, child);
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](crate::Itertools::kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;

pub trait KMergePredicate<T> {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
}

#[derive(Clone, Debug)]
pub struct KMergeByLt;

impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        a < b
    }
}

impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        self(a, b)
    }
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// [`IntoIterator`] enabled version of [`Itertools::kmerge`].
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    kmerge_by(iterable, KMergeByLt)
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](crate::Itertools::kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

impl<I, F> fmt::Debug for KMergeBy<I, F>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMergeBy, heap);
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
    KMergeBy { heap, less_than }
}

impl<I, F> Clone for KMergeBy<I, F>
    where I: Iterator + Clone,
          I::Item: Clone,
          F: Clone,
{
    clone_fields!(heap, less_than);
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}

impl<I, F> FusedIterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{}
<|endoftext|>


<commit_before>//! Memory management interface and garbage collection.
//!
//! # Finalization
//!
//! Finalizers allow Lea code to be run when a table is unreachable and would be collected by the
//! GC. They can execute arbitrary code and potentially make the table reachable again, and have
//! access to the table and its referenced objects, which means that the GC must not collect them
//! when a finalizer needs to run.
//!
//! A tables metatable can specify a `__gc` field, which will be run as a finalizer for the table
//! (if it's a function). The table should register itself for finalization in the GC when its
//! metatable is changed and contains a `__gc` field. If the metatable doesn't contain the field,
//! and it is later added to it, the table will *not* be marked for finalization, matching Lua
//! semantics.
//!
//! The GC manages a list of objects with finalizers and scans through them after the main mark
//! phase. If any object is unmarked, it will be added to a finalization list and recursively
//! marked. This makes sure that the finalization function can access the object and all reachable
//! objects. The object is removed from the finalized-object list and its finalizer is invoked.

// TODO finalizers and weak tables

extern crate aligned_alloc;

use std::any::Any;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::transmute;

use string::Str;

pub mod arena;
pub mod noop;
pub mod string;

pub type DefaultGc = noop::NoopGc;

/// A GC-managed object that may reference other GC-managed objects and keep them alive. Provides a
/// `trace` method that will be invoked by the GC to trace these references.
pub trait Traceable : Any {
    fn trace<T: Tracer>(&self, t: &mut T);
}

/// Traced reference to an object owned by the GC. This is inherently unsafe. May be stored in
/// traced structs, which will keep the referenced object alive. Cannot outlive the GC that owns
/// the object.
pub struct TracedRef<T: Any + ?Sized> {
    ptr: *const T,
}

impl<T: Any> Copy for TracedRef<T> {}

impl<T: Any> Clone for TracedRef<T> {
    fn clone(&self) -> TracedRef<T> {
        *self
    }
}

impl<T: Any> PartialEq for TracedRef<T> {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

impl<T: Any> Eq for TracedRef<T> {}

impl<T: Any> Hash for TracedRef<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_usize(self.ptr as usize);
    }
}

impl<T: Any> fmt::Debug for TracedRef<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.ptr)
    }
}

impl<T: Any> fmt::Pointer for TracedRef<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.ptr)
    }
}

/// A `Tracer` provides methods to mark objects as reachable. A `GcStrategy` will pass an object
/// that implements `Tracer` to the `trace` method of all `Traceable` and reachable objects.
pub trait Tracer {
    /// Marks a `TracedRef` as reachable without following the referenced object's own references
    /// (ie. without tracing it).
    ///
    /// This is unsafe and may only be called if the object really doesn't carry any references
    /// (currently only strings) (FIXME: Needs either some hack to work safely or specialization).
    unsafe fn mark_untraceable<T: Any>(&mut self, TracedRef<T>);

    /// Marks an object as reachable. This will also (at some undefined point in the future) trace
    /// the object, finding all transitively reachable objects.
    fn mark_traceable<T: Traceable>(&mut self, TracedRef<T>);
}

/// Contains methods called on various GC events. Must be implemented by the GC user and can
/// specify application-specific behaviour.
pub trait GcCallback {
    /// Invoke `f` on each object that is part of the root set. This is used to find the initially
    /// reachable objects when starting a collection.
    fn for_each_root<F>(&self, f: F) where F: FnMut(TracedRef<Any>);
}

/// Trait for Garbage Collector implementations.
pub trait GcStrategy {
    /// Instruct the GC to perform a collection step. This can be called by user code. A callback
    /// is passed so the GC can run finalizers and find the roots.
    fn collect_step<C: GcCallback>(&mut self, &mut C);

    /// Perform an atomic collection. The GC should try to free all currently unreachable objects.
    fn collect_atomic<C: GcCallback>(&mut self, &mut C);

    /// Called when a garbage-collected object is created. The GC should take ownership of the
    /// object and can dispose of it when collecting.
    fn register_obj<T: Any>(&mut self, T) -> TracedRef<T>;

    /// Interns a string and returns a `TracedRef` to the shared instance.
    fn intern_str<T: Into<Str>>(&mut self, T) -> TracedRef<Str>;

    /// Given a `TracedRef` of an object owned by this GC, this method unsafely returns a reference
    /// to the object.
    unsafe fn get_ref<T: Any>(&self, t: TracedRef<T>) -> &T {
        &*t.ptr
    }

    /// The mutable version of `get_ref`, returns a mutable reference to the object.
    ///
    /// This will mutably borrow the GC and thus prevent collections and aliasing references (from
    /// `get_ref`).
    unsafe fn get_mut<T: Any>(&mut self, t: TracedRef<T>) -> &mut T {
        transmute(t.ptr)
    }

    // TODO: Statistics interface
}
<commit_msg>Remove possibly outdated finalizer comment<commit_after>//! Memory management interface and garbage collection.

// TODO finalizers and weak tables

extern crate aligned_alloc;

use std::any::Any;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::transmute;

use string::Str;

pub mod arena;
pub mod noop;
pub mod string;

pub type DefaultGc = noop::NoopGc;

/// A GC-managed object that may reference other GC-managed objects and keep them alive. Provides a
/// `trace` method that will be invoked by the GC to trace these references.
pub trait Traceable : Any {
    fn trace<T: Tracer>(&self, t: &mut T);
}

/// Traced reference to an object owned by the GC. This is inherently unsafe. May be stored in
/// traced structs, which will keep the referenced object alive. Cannot outlive the GC that owns
/// the object.
pub struct TracedRef<T: Any + ?Sized> {
    ptr: *const T,
}

impl<T: Any> Copy for TracedRef<T> {}

impl<T: Any> Clone for TracedRef<T> {
    fn clone(&self) -> TracedRef<T> {
        *self
    }
}

impl<T: Any> PartialEq for TracedRef<T> {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

impl<T: Any> Eq for TracedRef<T> {}

impl<T: Any> Hash for TracedRef<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_usize(self.ptr as usize);
    }
}

impl<T: Any> fmt::Debug for TracedRef<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.ptr)
    }
}

impl<T: Any> fmt::Pointer for TracedRef<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.ptr)
    }
}

/// A `Tracer` provides methods to mark objects as reachable. A `GcStrategy` will pass an object
/// that implements `Tracer` to the `trace` method of all `Traceable` and reachable objects.
pub trait Tracer {
    /// Marks a `TracedRef` as reachable without following the referenced object's own references
    /// (ie. without tracing it).
    ///
    /// This is unsafe and may only be called if the object really doesn't carry any references
    /// (currently only strings) (FIXME: Needs either some hack to work safely or specialization).
    unsafe fn mark_untraceable<T: Any>(&mut self, TracedRef<T>);

    /// Marks an object as reachable. This will also (at some undefined point in the future) trace
    /// the object, finding all transitively reachable objects.
    fn mark_traceable<T: Traceable>(&mut self, TracedRef<T>);
}

/// Contains methods called on various GC events. Must be implemented by the GC user and can
/// specify application-specific behaviour.
pub trait GcCallback {
    /// Invoke `f` on each object that is part of the root set. This is used to find the initially
    /// reachable objects when starting a collection.
    fn for_each_root<F>(&self, f: F) where F: FnMut(TracedRef<Any>);
}

/// Trait for Garbage Collector implementations.
pub trait GcStrategy {
    /// Instruct the GC to perform a collection step. This can be called by user code. A callback
    /// is passed so the GC can run finalizers and find the roots.
    fn collect_step<C: GcCallback>(&mut self, &mut C);

    /// Perform an atomic collection. The GC should try to free all currently unreachable objects.
    fn collect_atomic<C: GcCallback>(&mut self, &mut C);

    /// Called when a garbage-collected object is created. The GC should take ownership of the
    /// object and can dispose of it when collecting.
    fn register_obj<T: Any>(&mut self, T) -> TracedRef<T>;

    /// Interns a string and returns a `TracedRef` to the shared instance.
    fn intern_str<T: Into<Str>>(&mut self, T) -> TracedRef<Str>;

    /// Given a `TracedRef` of an object owned by this GC, this method unsafely returns a reference
    /// to the object.
    unsafe fn get_ref<T: Any>(&self, t: TracedRef<T>) -> &T {
        &*t.ptr
    }

    /// The mutable version of `get_ref`, returns a mutable reference to the object.
    ///
    /// This will mutably borrow the GC and thus prevent collections and aliasing references (from
    /// `get_ref`).
    unsafe fn get_mut<T: Any>(&mut self, t: TracedRef<T>) -> &mut T {
        transmute(t.ptr)
    }

    // TODO: Statistics interface
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use internals::ast::{Container, Data, Field, Style};
use internals::attr::{EnumTag, Identifier};
use internals::Ctxt;
use syn::Member;

/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
    check_getter(cx, cont);
    check_flatten(cx, cont);
    check_identifier(cx, cont);
    check_variant_skip_attrs(cx, cont);
    check_internal_tag_field_name_conflict(cx, cont);
    check_adjacent_tag_conflict(cx, cont);
}

/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(_) => {
            if cont.data.has_getter() {
                cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
            }
        }
        Data::Struct(_, _) => {
            if cont.data.has_getter() && cont.attrs.remote().is_none() {
                cx.error(
                    "#[serde(getter = \"...\")] can only be used in structs \
                     that have #[serde(remote = \"...\")]",
                );
            }
        }
    }
}

/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(ref variants) => {
            for variant in variants {
                for field in &variant.fields {
                    check_flatten_field(cx, variant.style, field);
                }
            }
        }
        Data::Struct(style, ref fields) => {
            for field in fields {
                check_flatten_field(cx, style, field);
            }
        }
    }
}

fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
    if !field.attrs.flatten() {
        return;
    }
    match style {
        Style::Tuple => {
            cx.error("#[serde(flatten)] cannot be used on tuple structs");
        }
        Style::Newtype => {
            cx.error("#[serde(flatten)] cannot be used on newtype structs");
        }
        _ => {}
    }
    if field.attrs.skip_serializing() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_serializing)]",
        );
    } else if field.attrs.skip_serializing_if().is_some() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_serializing_if = \"...\")]",
        );
    } else if field.attrs.skip_deserializing() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_deserializing)]",
        );
    }
}

/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for (i, variant) in variants.iter().enumerate() {
        match (
            variant.style,
            cont.attrs.identifier(),
            variant.attrs.other(),
        ) {
            // The `other` attribute may only be used in a field_identifier.
            (_, Identifier::Variant, true) | (_, Identifier::No, true) => {
                cx.error("#[serde(other)] may only be used inside a field_identifier");
            }

            // Variant with `other` attribute must be the last one.
            (Style::Unit, Identifier::Field, true) => {
                if i < variants.len() - 1 {
                    cx.error("#[serde(other)] must be the last variant");
                }
            }

            // Variant with `other` attribute must be a unit variant.
            (_, Identifier::Field, true) => {
                cx.error("#[serde(other)] must be on a unit variant");
            }

            // Any sort of variant is allowed if this is not an identifier.
            (_, Identifier::No, false) => {}

            // Unit variant without `other` attribute is always fine.
            (Style::Unit, _, false) => {}

            // The last field is allowed to be a newtype catch-all.
            (Style::Newtype, Identifier::Field, false) => {
                if i < variants.len() - 1 {
                    cx.error(format!("`{}` must be the last variant", variant.ident));
                }
            }

            (_, Identifier::Field, false) => {
                cx.error("field_identifier may only contain unit variants");
            }

            (_, Identifier::Variant, false) => {
                cx.error("variant_identifier may only contain unit variants");
            }
        }
    }
}

/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for variant in variants.iter() {
        if variant.attrs.serialize_with().is_some() {
            if variant.attrs.skip_serializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(serialize_with)] and \
                     #[serde(skip_serializing)]",
                    variant.ident
                ));
            }

            for field in &variant.fields {
                let member = member_message(&field.member);

                if field.attrs.skip_serializing() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing)]",
                        variant.ident, member
                    ));
                }

                if field.attrs.skip_serializing_if().is_some() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing_if)]",
                        variant.ident, member
                    ));
                }
            }
        }

        if variant.attrs.deserialize_with().is_some() {
            if variant.attrs.skip_deserializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(deserialize_with)] and \
                     #[serde(skip_deserializing)]",
                    variant.ident
                ));
            }

            for field in &variant.fields {
                if field.attrs.skip_deserializing() {
                    let member = member_message(&field.member);

                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(deserialize_with)] \
                         and a field {} marked with #[serde(skip_deserializing)]",
                        variant.ident, member
                    ));
                }
            }
        }
    }
}

/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => return,
    };

    let tag = match *cont.attrs.tag() {
        EnumTag::Internal { ref tag } => tag.as_str(),
        EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
    };

    let diagnose_conflict = || {
        let message = format!("variant field name `{}` conflicts with internal tag", tag);
        cx.error(message);
    };

    for variant in variants {
        match variant.style {
            Style::Struct => {
                for field in &variant.fields {
                    let check_ser = !field.attrs.skip_serializing();
                    let check_de = !field.attrs.skip_deserializing();
                    let name = field.attrs.name();
                    let ser_name = name.serialize_name();
                    let de_name = name.deserialize_name();

                    if check_ser && ser_name == tag || check_de && de_name == tag {
                        diagnose_conflict();
                        return;
                    }
                }
            }
            Style::Unit | Style::Newtype | Style::Tuple => {}
        }
    }
}

/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
    let (type_tag, content_tag) = match *cont.attrs.tag() {
        EnumTag::Adjacent {
            ref tag,
            ref content,
        } => (tag, content),
        EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
    };

    if type_tag == content_tag {
        let message = format!(
            "enum tags `{}` for type and content conflict with each other",
            type_tag
        );
        cx.error(message);
    }
}

fn member_message(member: &Member) -> String {
    match *member {
        Member::Named(ref ident) => format!("`{}`", ident),
        Member::Unnamed(ref i) => i.index.to_string(),
    }
}
<commit_msg>Validate use of serde(transparent)<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use internals::ast::{Container, Data, Field, Style};
use internals::attr::{EnumTag, Identifier};
use internals::Ctxt;
use syn::Member;

/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
    check_getter(cx, cont);
    check_flatten(cx, cont);
    check_identifier(cx, cont);
    check_variant_skip_attrs(cx, cont);
    check_internal_tag_field_name_conflict(cx, cont);
    check_adjacent_tag_conflict(cx, cont);
    check_transparent(cx, cont);
}

/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(_) => {
            if cont.data.has_getter() {
                cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
            }
        }
        Data::Struct(_, _) => {
            if cont.data.has_getter() && cont.attrs.remote().is_none() {
                cx.error(
                    "#[serde(getter = \"...\")] can only be used in structs \
                     that have #[serde(remote = \"...\")]",
                );
            }
        }
    }
}

/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(ref variants) => {
            for variant in variants {
                for field in &variant.fields {
                    check_flatten_field(cx, variant.style, field);
                }
            }
        }
        Data::Struct(style, ref fields) => {
            for field in fields {
                check_flatten_field(cx, style, field);
            }
        }
    }
}

fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
    if !field.attrs.flatten() {
        return;
    }
    match style {
        Style::Tuple => {
            cx.error("#[serde(flatten)] cannot be used on tuple structs");
        }
        Style::Newtype => {
            cx.error("#[serde(flatten)] cannot be used on newtype structs");
        }
        _ => {}
    }
    if field.attrs.skip_serializing() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_serializing)]",
        );
    } else if field.attrs.skip_serializing_if().is_some() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_serializing_if = \"...\")]",
        );
    } else if field.attrs.skip_deserializing() {
        cx.error(
            "#[serde(flatten] can not be combined with \
             #[serde(skip_deserializing)]",
        );
    }
}

/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for (i, variant) in variants.iter().enumerate() {
        match (
            variant.style,
            cont.attrs.identifier(),
            variant.attrs.other(),
        ) {
            // The `other` attribute may only be used in a field_identifier.
            (_, Identifier::Variant, true) | (_, Identifier::No, true) => {
                cx.error("#[serde(other)] may only be used inside a field_identifier");
            }

            // Variant with `other` attribute must be the last one.
            (Style::Unit, Identifier::Field, true) => {
                if i < variants.len() - 1 {
                    cx.error("#[serde(other)] must be the last variant");
                }
            }

            // Variant with `other` attribute must be a unit variant.
            (_, Identifier::Field, true) => {
                cx.error("#[serde(other)] must be on a unit variant");
            }

            // Any sort of variant is allowed if this is not an identifier.
            (_, Identifier::No, false) => {}

            // Unit variant without `other` attribute is always fine.
            (Style::Unit, _, false) => {}

            // The last field is allowed to be a newtype catch-all.
            (Style::Newtype, Identifier::Field, false) => {
                if i < variants.len() - 1 {
                    cx.error(format!("`{}` must be the last variant", variant.ident));
                }
            }

            (_, Identifier::Field, false) => {
                cx.error("field_identifier may only contain unit variants");
            }

            (_, Identifier::Variant, false) => {
                cx.error("variant_identifier may only contain unit variants");
            }
        }
    }
}

/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for variant in variants.iter() {
        if variant.attrs.serialize_with().is_some() {
            if variant.attrs.skip_serializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(serialize_with)] and \
                     #[serde(skip_serializing)]",
                    variant.ident
                ));
            }

            for field in &variant.fields {
                let member = member_message(&field.member);

                if field.attrs.skip_serializing() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing)]",
                        variant.ident, member
                    ));
                }

                if field.attrs.skip_serializing_if().is_some() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing_if)]",
                        variant.ident, member
                    ));
                }
            }
        }

        if variant.attrs.deserialize_with().is_some() {
            if variant.attrs.skip_deserializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(deserialize_with)] and \
                     #[serde(skip_deserializing)]",
                    variant.ident
                ));
            }

            for field in &variant.fields {
                if field.attrs.skip_deserializing() {
                    let member = member_message(&field.member);

                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(deserialize_with)] \
                         and a field {} marked with #[serde(skip_deserializing)]",
                        variant.ident, member
                    ));
                }
            }
        }
    }
}

/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => return,
    };

    let tag = match *cont.attrs.tag() {
        EnumTag::Internal { ref tag } => tag.as_str(),
        EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
    };

    let diagnose_conflict = || {
        let message = format!("variant field name `{}` conflicts with internal tag", tag);
        cx.error(message);
    };

    for variant in variants {
        match variant.style {
            Style::Struct => {
                for field in &variant.fields {
                    let check_ser = !field.attrs.skip_serializing();
                    let check_de = !field.attrs.skip_deserializing();
                    let name = field.attrs.name();
                    let ser_name = name.serialize_name();
                    let de_name = name.deserialize_name();

                    if check_ser && ser_name == tag || check_de && de_name == tag {
                        diagnose_conflict();
                        return;
                    }
                }
            }
            Style::Unit | Style::Newtype | Style::Tuple => {}
        }
    }
}

/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
    let (type_tag, content_tag) = match *cont.attrs.tag() {
        EnumTag::Adjacent {
            ref tag,
            ref content,
        } => (tag, content),
        EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
    };

    if type_tag == content_tag {
        let message = format!(
            "enum tags `{}` for type and content conflict with each other",
            type_tag
        );
        cx.error(message);
    }
}

/// Enums and unit structs cannot be transparent.
fn check_transparent(cx: &Ctxt, cont: &Container) {
    if !cont.attrs.transparent() {
        return;
    }

    if cont.attrs.type_from().is_some() {
        cx.error("#[serde(transparent)] is not allowed with #[serde(from = \"...\")]");
    }

    if cont.attrs.type_into().is_some() {
        cx.error("#[serde(transparent)] is not allowed with #[serde(into = \"...\")]");
    }

    match cont.data {
        Data::Enum(_) => {
            cx.error("#[serde(transparent)] is not allowed on an enum");
        }
        Data::Struct(Style::Unit, _) => {
            cx.error("#[serde(transparent)] is not allowed on a unit struct");
        }
        _ => {}
    }
}

fn member_message(member: &Member) -> String {
    match *member {
        Member::Named(ref ident) => format!("`{}`", ident),
        Member::Unnamed(ref i) => i.index.to_string(),
    }
}
<|endoftext|>


<commit_before>use std;

fn main() {

    obj a() {
        fn foo() -> int {
            ret 2;
        }
        fn bar() -> int {
            ret self.foo();
        }
    }

    auto my_a = a();

    // Extending an object with a new method that contains a simple
    // self-call.  Adding support for this is issue #540.

    auto my_b = obj {
        fn baz() -> int {
            ret self.foo();
        }
        with my_a
    };

    assert (my_b.baz() == 2);

}
<commit_msg>Getting rid of obsolete comments.<commit_after>use std;

fn main() {

    obj a() {
        fn foo() -> int {
            ret 2;
        }
        fn bar() -> int {
            ret self.foo();
        }
    }

    auto my_a = a();

    auto my_b = obj {
        fn baz() -> int {
            ret self.foo();
        }
        with my_a
    };

    assert (my_b.baz() == 2);

}
<|endoftext|>


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

#![allow(unused_mut)]
// ignore-wasm32
// ignore-emscripten

// compile-flags: -C debug_assertions=yes

#![stable(feature = "rustc", since = "1.0.0")]
#![feature(const_fn, libc, staged_api, rustc_attrs)]
#![allow(const_err)]

extern crate libc;

use std::env;
use std::process::{Command, Stdio};

// this will panic in debug mode and overflow in release mode
#[stable(feature = "rustc", since = "1.0.0")]
#[rustc_promotable]
const fn bar() -> usize { 0 - 1 }

fn foo() {
    let _: &'static _ = &bar();
}

#[cfg(unix)]
fn check_status(status: std::process::ExitStatus)
{
    use libc;
    use std::os::unix::process::ExitStatusExt;

    assert!(status.signal() == Some(libc::SIGILL)
            || status.signal() == Some(libc::SIGABRT));
}

#[cfg(not(unix))]
fn check_status(status: std::process::ExitStatus)
{
    assert!(!status.success());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        foo();
        return;
    }

    let mut p = Command::new(&args[0])
        .stdout(Stdio::piped())
        .stdin(Stdio::piped())
        .arg("test").output().unwrap();
    check_status(p.status);
}
<commit_msg>Fix invalid_const_promotion test on some archs<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(unused_mut)]
// ignore-wasm32
// ignore-emscripten

// compile-flags: -C debug_assertions=yes

#![stable(feature = "rustc", since = "1.0.0")]
#![feature(const_fn, libc, staged_api, rustc_attrs)]
#![allow(const_err)]

extern crate libc;

use std::env;
use std::process::{Command, Stdio};

// this will panic in debug mode and overflow in release mode
#[stable(feature = "rustc", since = "1.0.0")]
#[rustc_promotable]
const fn bar() -> usize { 0 - 1 }

fn foo() {
    let _: &'static _ = &bar();
}

#[cfg(unix)]
fn check_status(status: std::process::ExitStatus)
{
    use libc;
    use std::os::unix::process::ExitStatusExt;

    assert!(status.signal() == Some(libc::SIGILL)
            || status.signal() == Some(libc::SIGTRAP)
            || status.signal() == Some(libc::SIGABRT));
}

#[cfg(not(unix))]
fn check_status(status: std::process::ExitStatus)
{
    assert!(!status.success());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        foo();
        return;
    }

    let mut p = Command::new(&args[0])
        .stdout(Stdio::piped())
        .stdin(Stdio::piped())
        .arg("test").output().unwrap();
    check_status(p.status);
}
<|endoftext|>


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

//! The Rust core library
//!
//! This library is meant to represent the core functionality of rust that is
//! maximally portable to other platforms. To that extent, this library has no
//! knowledge of things like allocation, threads, I/O, etc. This library is
//! built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these funcitons. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by `librlibc` which is distributed with the standard rust
//!   distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
//!   the failure message, the file at which failure was invoked, and the line.
//!   It is up to consumers of this core library to define this failure
//!   function; it is only required to never return.
//!
//! Currently, it is *not* recommended to use the core library. The stable
//! functionality of libcore is exported directly into the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time, only the interface exposed through libstd is
//! intended to be stable.

#![crate_id = "core#0.11.0-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes, phase)]
#![deny(missing_doc)]

#[cfg(test)] extern crate realcore = "core";
#[cfg(test)] extern crate libc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate realstd = "std";

#[cfg(test)] pub use cmp = realcore::cmp;
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use ty = realcore::ty;

mod macros;

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

#[cfg(not(test))] pub mod kinds;
#[cfg(not(test))] pub mod ops;
#[cfg(not(test))] pub mod ty;
#[cfg(not(test))] pub mod cmp;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
pub mod any;
pub mod atomics;
pub mod bool;
pub mod cell;
pub mod char;
pub mod failure;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod fmt;

// FIXME: this module should not exist. Once owned allocations are no longer a
//        language type, this module can move outside to the owned allocation
//        crate.
mod should_not_exist;

mod core {
    pub use failure;
}

mod std {
    pub use clone;
    pub use cmp;
    pub use kinds;
    pub use option;
    pub use fmt;

    #[cfg(test)] pub use realstd::rt;     // needed for fail!()
    // #[cfg(test)] pub use realstd::option; // needed for fail!()
    // #[cfg(test)] pub use realstd::fmt;    // needed for fail!()
    #[cfg(test)] pub use realstd::os;     // needed for tests
    #[cfg(test)] pub use realstd::slice;  // needed for tests
    #[cfg(test)] pub use realstd::vec;    // needed for vec![]
}
<commit_msg>auto merge of #14292 : limeburst/rust/master, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust core library
//!
//! This library is meant to represent the core functionality of rust that is
//! maximally portable to other platforms. To that extent, this library has no
//! knowledge of things like allocation, threads, I/O, etc. This library is
//! built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by `librlibc` which is distributed with the standard rust
//!   distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
//!   the failure message, the file at which failure was invoked, and the line.
//!   It is up to consumers of this core library to define this failure
//!   function; it is only required to never return.
//!
//! Currently, it is *not* recommended to use the core library. The stable
//! functionality of libcore is exported directly into the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time, only the interface exposed through libstd is
//! intended to be stable.

#![crate_id = "core#0.11.0-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes, phase)]
#![deny(missing_doc)]

#[cfg(test)] extern crate realcore = "core";
#[cfg(test)] extern crate libc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate realstd = "std";

#[cfg(test)] pub use cmp = realcore::cmp;
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use ty = realcore::ty;

mod macros;

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

#[cfg(not(test))] pub mod kinds;
#[cfg(not(test))] pub mod ops;
#[cfg(not(test))] pub mod ty;
#[cfg(not(test))] pub mod cmp;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
pub mod any;
pub mod atomics;
pub mod bool;
pub mod cell;
pub mod char;
pub mod failure;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod fmt;

// FIXME: this module should not exist. Once owned allocations are no longer a
//        language type, this module can move outside to the owned allocation
//        crate.
mod should_not_exist;

mod core {
    pub use failure;
}

mod std {
    pub use clone;
    pub use cmp;
    pub use kinds;
    pub use option;
    pub use fmt;

    #[cfg(test)] pub use realstd::rt;     // needed for fail!()
    // #[cfg(test)] pub use realstd::option; // needed for fail!()
    // #[cfg(test)] pub use realstd::fmt;    // needed for fail!()
    #[cfg(test)] pub use realstd::os;     // needed for tests
    #[cfg(test)] pub use realstd::slice;  // needed for tests
    #[cfg(test)] pub use realstd::vec;    // needed for vec![]
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate sysinfo;
extern crate test;

use sysinfo::get_current_pid;
use sysinfo::SystemExt;

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_new_all(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new_all();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_processes(); // to load the whole processes list a first time.
    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    // to be sure it'll exist for at least as long as we run
    let pid = get_current_pid().expect("failed to get current pid");
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disks_lists(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks_list();
    });
}

#[bench]
fn bench_refresh_networks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_networks();
    });
}

#[bench]
fn bench_refresh_networks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_networks_list();
    });
}

#[bench]
fn bench_refresh_memory(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_memory();
    });
}

#[bench]
fn bench_refresh_cpu(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_cpu();
    });
}

#[bench]
fn bench_refresh_temperatures(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_temperatures();
    });
}
<commit_msg>Update benchmarks<commit_after>#![feature(test)]

extern crate sysinfo;
extern crate test;

use sysinfo::get_current_pid;
use sysinfo::SystemExt;

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_new_all(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new_all();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_processes(); // to load the whole processes list a first time.
    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    // to be sure it'll exist for at least as long as we run
    let pid = get_current_pid().expect("failed to get current pid");
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disks_lists(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks_list();
    });
}

#[bench]
fn bench_refresh_networks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_networks();
    });
}

#[bench]
fn bench_refresh_networks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_networks_list();
    });
}

#[bench]
fn bench_refresh_memory(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_memory();
    });
}

#[bench]
fn bench_refresh_cpu(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_cpu();
    });
}

#[bench]
fn bench_refresh_components(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components();
    });
}

#[bench]
fn bench_refresh_components_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components_list();
    });
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;

extern crate gluon;
extern crate gluon_base as base;
extern crate gluon_check as check;
extern crate gluon_parser as parser;

use std::fs;

use criterion::{Bencher, Criterion};

use gluon::compiler_pipeline::*;
use gluon::{new_vm, Compiler};

fn typecheck_prelude(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let MacroValue { expr } = {
        let text = fs::read_to_string("std/prelude.glu").unwrap();
        text.expand_macro(&mut compiler, &vm, "std.prelude", &text)
            .unwrap_or_else(|(_, err)| panic!("{}", err))
    };
    b.iter(|| {
        let result = MacroValue { expr: expr.clone() }.typecheck(&mut compiler, &vm, "<top>", "");
        if let Err(ref err) = result {
            println!("{}", err);
            assert!(false);
        }
        result
    })
}

fn clone_prelude(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let TypecheckValue { expr, .. } = {
        let text = fs::read_to_string("std/prelude.glu").unwrap();
        text.typecheck(&mut compiler, &vm, "std.prelude", &text)
            .unwrap_or_else(|err| panic!("{}", err))
    };
    b.iter(|| expr.clone())
}

fn typecheck_24(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let MacroValue { expr } = {
        let text = fs::read_to_string("examples/24.glu").unwrap();
        text.expand_macro(&mut compiler, &vm, "examples.24", &text)
            .unwrap_or_else(|(_, err)| panic!("{}", err))
    };
    b.iter(|| {
        let result = MacroValue { expr: expr.clone() }.typecheck(&mut compiler, &vm, "<top>", "");
        if let Err(ref err) = result {
            println!("{}", err);
            assert!(false);
        }
        result
    })
}

fn clone_benchmark(c: &mut Criterion) {
    c.bench_function("clone prelude", clone_prelude);
}

fn typecheck_benchmark(c: &mut Criterion) {
    c.bench_function("std/prelude", typecheck_prelude);
    c.bench_function("examples/24", typecheck_24);
}

criterion_group!(check, typecheck_benchmark, clone_benchmark);
criterion_main!(check);
<commit_msg>chore: Shorten the time to run check benchmarks<commit_after>#[macro_use]
extern crate criterion;

extern crate gluon;
extern crate gluon_base as base;
extern crate gluon_check as check;
extern crate gluon_parser as parser;

use std::fs;

use criterion::{Bencher, Criterion};

use gluon::compiler_pipeline::*;
use gluon::{new_vm, Compiler};

fn typecheck_prelude(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let MacroValue { expr } = {
        let text = fs::read_to_string("std/prelude.glu").unwrap();
        text.expand_macro(&mut compiler, &vm, "std.prelude", &text)
            .unwrap_or_else(|(_, err)| panic!("{}", err))
    };
    b.iter(|| {
        let result = MacroValue { expr: expr.clone() }.typecheck(&mut compiler, &vm, "<top>", "");
        if let Err(ref err) = result {
            println!("{}", err);
            assert!(false);
        }
        result
    })
}

fn clone_prelude(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let TypecheckValue { expr, .. } = {
        let text = fs::read_to_string("std/prelude.glu").unwrap();
        text.typecheck(&mut compiler, &vm, "std.prelude", &text)
            .unwrap_or_else(|err| panic!("{}", err))
    };
    b.iter(|| expr.clone())
}

fn typecheck_24(b: &mut Bencher) {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    let MacroValue { expr } = {
        let text = fs::read_to_string("examples/24.glu").unwrap();
        text.expand_macro(&mut compiler, &vm, "examples.24", &text)
            .unwrap_or_else(|(_, err)| panic!("{}", err))
    };
    b.iter(|| {
        let result = MacroValue { expr: expr.clone() }.typecheck(&mut compiler, &vm, "<top>", "");
        if let Err(ref err) = result {
            println!("{}", err);
            assert!(false);
        }
        result
    })
}

fn clone_benchmark(c: &mut Criterion) {
    c.bench_function("clone prelude", clone_prelude);
}

fn typecheck_benchmark(c: &mut Criterion) {
    c.bench_function("std/prelude", typecheck_prelude);
    c.bench_function("examples/24", typecheck_24);
}

criterion_group!(
    name = check;
    config = Criterion::default().sample_size(20).configure_from_args();
    targets = typecheck_benchmark, clone_benchmark
);
criterion_main!(check);
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Handle_a_signal
//
// Note that this solution only works on Unix.
#![allow(unstable)]

extern crate libc;
extern crate time;

#[cfg(all(unix, not(test)))]
fn main()
{
    use libc::consts::os::posix88::SIGINT;
    use libc::funcs::posix01::signal;
    use std::io::timer::Timer;
    use std::mem;
    use std::sync::atomic::{self, AtomicBool, ATOMIC_BOOL_INIT, Ordering};
    use std::time::duration::Duration;

    // The time between ticks of our counter.
    let duration = Duration::seconds(1) / 2;
    let mut timer = Timer::new().unwrap();
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        signal::signal(SIGINT, mem::transmute(handle_sigint));
    }
    let periodic = timer.periodic(duration);
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    for _ in periodic.iter() {
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } { break }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::nanoseconds((end - start) as i64);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff);
}

#[cfg(not(unix))]
fn main()
{
    println!("Not supported on this platform");
}
<commit_msg>Fix unused import warning<commit_after>// Implements http://rosettacode.org/wiki/Handle_a_signal
//
// Note that this solution only works on Unix.
#![allow(unstable)]

extern crate libc;
extern crate time;

#[cfg(all(unix, not(test)))]
fn main()
{
    use libc::consts::os::posix88::SIGINT;
    use libc::funcs::posix01::signal;
    use std::io::timer::Timer;
    use std::mem;
    use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
    use std::time::duration::Duration;

    // The time between ticks of our counter.
    let duration = Duration::seconds(1) / 2;
    let mut timer = Timer::new().unwrap();
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        signal::signal(SIGINT, mem::transmute(handle_sigint));
    }
    let periodic = timer.periodic(duration);
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    for _ in periodic.iter() {
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } { break }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::nanoseconds((end - start) as i64);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff);
}

#[cfg(not(unix))]
fn main()
{
    println!("Not supported on this platform");
}
<|endoftext|>


<commit_before>
pub struct Task {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

impl Task {
        pub fn to_str(&self) -> ~str {
                return format!("{:d} {:b} ({:c}) '{:s}' \"{:s}\"",
                                self.id, self.finished, self.priority,
                                self.todo, self.raw_todo)
        }

        pub fn create(todo: ~str, id: int) -> Task {
                let mut task = Task{id: id, raw_todo: todo.clone(), todo: todo.clone(),
                                        finished: false, priority: '^',
                                        contexts: &[], projects: &[]};

                let mut t = todo.clone();

                if (t.slice(0, 2) == "x ") {
                        task.finished = true;
                        t = t.slice(2, t.len()).to_owned();
                }

                //if (todo[0])
                task.todo = t;

                return task;
        }
}

#[test]
fn simple_todo_create_test() {
        let t = Task::create(~"some important task", 1);

        assert_eq!(t.id , 1);
        assert_eq!(t.priority , '^');
        assert_eq!(t.finished , false);
        assert_eq!(t.todo , ~"some important task");
        assert_eq!(t.raw_todo , ~"some important task");
}

#[test]
fn simple_todo_with_priority_test() {
        let t = Task::create(~"(A) some important task with priority", 1);

        assert_eq!(t.id , 1);
        assert_eq!(t.priority , '^');
        assert_eq!(t.finished , false);
        assert_eq!(t.todo , ~"some important task with priority");
        assert_eq!(t.raw_todo , ~"(A) some important task with priority");
}

#[test]
fn todo_to_str_test() {
        let t = Task::create(~"some important task", 1);

        assert_eq!(t.to_str(), ~"1 false (^) 'some important task' \"some important task\"")

        let x = Task::create(~"x some important task", 1);
        assert_eq!(x.to_str(), ~"1 true (^) 'some important task' \"x some important task\"")
}
<commit_msg>renamed<commit_after>
pub struct Task {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

impl Task {
        pub fn to_str(&self) -> ~str {
                return format!("{:d} {:b} ({:c}) '{:s}' \"{:s}\"",
                                self.id, self.finished, self.priority,
                                self.todo, self.raw_todo)
        }

        pub fn create(text: ~str, id: int) -> Task {
                let mut task = Task{id: id, raw_todo: text.clone(), todo: text.clone(),
                                        finished: false, priority: '^',
                                        contexts: &[], projects: &[]};

                let mut todo = text.clone();

                if (todo.slice(0, 2) == "x ") {
                        task.finished = true;
                        todo = todo.slice(2, todo.len()).to_owned();
                }

                //if (todo[0])
                task.todo = todo;

                return task;
        }
}

#[test]
fn simple_todo_create_test() {
        let t = Task::create(~"some important task", 1);

        assert_eq!(t.id , 1);
        assert_eq!(t.priority , '^');
        assert_eq!(t.finished , false);
        assert_eq!(t.todo , ~"some important task");
        assert_eq!(t.raw_todo , ~"some important task");
}

#[test]
fn simple_todo_with_priority_test() {
        let t = Task::create(~"(A) some important task with priority", 1);

        assert_eq!(t.id , 1);
        assert_eq!(t.priority , '^');
        assert_eq!(t.finished , false);
        assert_eq!(t.todo , ~"some important task with priority");
        assert_eq!(t.raw_todo , ~"(A) some important task with priority");
}

#[test]
fn todo_to_str_test() {
        let t = Task::create(~"some important task", 1);

        assert_eq!(t.to_str(), ~"1 false (^) 'some important task' \"some important task\"")

        let x = Task::create(~"x some important task", 1);
        assert_eq!(x.to_str(), ~"1 true (^) 'some important task' \"x some important task\"")
}
<|endoftext|>