<commit_before>#[allow(unused_imports)]
use std::ascii::AsciiExt;

pub fn is_keyword(txt: &str) -> bool {
    match txt {
        "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate"
        | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in"
        | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "offsetof" | "override" | "priv"
        | "proc" | "pub" | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
        | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual"
        | "where" | "while" | "yield" => true,
        _ => false,
    }
}

pub fn snake_to_camel(input: &str) -> String {
    input
        .split('_')
        .flat_map(|s| {
            let mut first = true;
            s.chars().map(move |c| {
                if first {
                    first = false;
                    c.to_ascii_uppercase()
                } else {
                    c
                }
            })
        })
        .collect()
}

pub fn dotted_to_relname(input: &str) -> String {
    let mut it = input.split('.');
    match (it.next(), it.next()) {
        (Some(module), Some(name)) => format!("super::{}::{}", module, snake_to_camel(name)),
        (Some(name), None) => snake_to_camel(name),
        _ => unreachable!(),
    }
}
<commit_msg>Allow deprecated to stop warnings on compile<commit_after>#[allow(unused_imports)]
#[allow(deprecated)]
use std::ascii::AsciiExt;

pub fn is_keyword(txt: &str) -> bool {
    match txt {
        "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate"
        | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in"
        | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "offsetof" | "override" | "priv"
        | "proc" | "pub" | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
        | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual"
        | "where" | "while" | "yield" => true,
        _ => false,
    }
}

pub fn snake_to_camel(input: &str) -> String {
    input
        .split('_')
        .flat_map(|s| {
            let mut first = true;
            s.chars().map(move |c| {
                if first {
                    first = false;
                    c.to_ascii_uppercase()
                } else {
                    c
                }
            })
        })
        .collect()
}

pub fn dotted_to_relname(input: &str) -> String {
    let mut it = input.split('.');
    match (it.next(), it.next()) {
        (Some(module), Some(name)) => format!("super::{}::{}", module, snake_to_camel(name)),
        (Some(name), None) => snake_to_camel(name),
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>use std::iter::Fuse;
use alloc::collections::VecDeque;
use crate::size_hint;
use crate::PeekingNext;

/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
pub struct MultiPeek<I>
    where I: Iterator
{
    iter: Fuse<I>,
    buf: VecDeque<I::Item>,
    index: usize,
}

/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
    where I: IntoIterator
{
    MultiPeek {
        iter: iterable.into_iter().fuse(),
        buf: VecDeque::new(),
        index: 0,
    }
}

impl<I> MultiPeek<I>
    where I: Iterator
{
    /// Reset the peeking “cursor”
    pub fn reset_peek(&mut self) {
        self.index = 0;
    }
}

impl<I: Iterator> MultiPeek<I> {
    /// Works exactly like `.next()` with the only difference that it doesn't
    /// advance itself. `.peek()` can be called multiple times, to peek
    /// further ahead.
    /// When `.next()` is called, reset the peeking “cursor”.
    pub fn peek(&mut self) -> Option<&I::Item> {
        let ret = if self.index < self.buf.len() {
            Some(&self.buf[self.index])
        } else {
            match self.iter.next() {
                Some(x) => {
                    self.buf.push_back(x);
                    Some(&self.buf[self.index])
                }
                None => return None,
            }
        };

        self.index += 1;
        ret
    }
}

impl<I> PeekingNext for MultiPeek<I>
    where I: Iterator,
{
    fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
        where F: FnOnce(&Self::Item) -> bool
    {
        if self.buf.is_empty() {
            if let Some(r) = self.peek() {
                if !accept(r) { return None }
            }
        } else {
            if let Some(r) = self.buf.get(0) {
                if !accept(r) { return None }
            }
        }
        self.next()
    }
}

impl<I> Iterator for MultiPeek<I>
    where I: Iterator
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.index = 0;
        self.buf.pop_front().or_else(|| self.iter.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
    }
}

// Same size
impl<I> ExactSizeIterator for MultiPeek<I>
    where I: ExactSizeIterator
{}

<commit_msg>Canonicalize some free functions (5) multipeek: documentation<commit_after>use std::iter::Fuse;
use alloc::collections::VecDeque;
use crate::size_hint;
use crate::PeekingNext;
#[cfg(doc)]
use crate::Itertools;

/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
pub struct MultiPeek<I>
    where I: Iterator
{
    iter: Fuse<I>,
    buf: VecDeque<I::Item>,
    index: usize,
}

/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
///
/// [`IntoIterator`] enabled version of [`Itertools::multipeek`].
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
    where I: IntoIterator
{
    MultiPeek {
        iter: iterable.into_iter().fuse(),
        buf: VecDeque::new(),
        index: 0,
    }
}

impl<I> MultiPeek<I>
    where I: Iterator
{
    /// Reset the peeking “cursor”
    pub fn reset_peek(&mut self) {
        self.index = 0;
    }
}

impl<I: Iterator> MultiPeek<I> {
    /// Works exactly like `.next()` with the only difference that it doesn't
    /// advance itself. `.peek()` can be called multiple times, to peek
    /// further ahead.
    /// When `.next()` is called, reset the peeking “cursor”.
    pub fn peek(&mut self) -> Option<&I::Item> {
        let ret = if self.index < self.buf.len() {
            Some(&self.buf[self.index])
        } else {
            match self.iter.next() {
                Some(x) => {
                    self.buf.push_back(x);
                    Some(&self.buf[self.index])
                }
                None => return None,
            }
        };

        self.index += 1;
        ret
    }
}

impl<I> PeekingNext for MultiPeek<I>
    where I: Iterator,
{
    fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
        where F: FnOnce(&Self::Item) -> bool
    {
        if self.buf.is_empty() {
            if let Some(r) = self.peek() {
                if !accept(r) { return None }
            }
        } else {
            if let Some(r) = self.buf.get(0) {
                if !accept(r) { return None }
            }
        }
        self.next()
    }
}

impl<I> Iterator for MultiPeek<I>
    where I: Iterator
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.index = 0;
        self.buf.pop_front().or_else(|| self.iter.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
    }
}

// Same size
impl<I> ExactSizeIterator for MultiPeek<I>
    where I: ExactSizeIterator
{}

<|endoftext|>


<commit_before>//! Implementation of intrusive doubly linked list

use core::marker::PhantomData;

use link::Link;

pub trait Node: Sized {
    fn prev(&self) -> &Link<Self>;
    fn next(&self) -> &Link<Self>;

    fn prev_mut(&mut self) -> &mut Link<Self>;
    fn next_mut(&mut self) -> &mut Link<Self>;
}

pub trait Owner<T> where T: Node {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;

    fn take(self);

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self;
}

pub struct List<T, U> where T: Owner<U>, U: Node {
    head: Link<U>,
    tail: Link<U>,
    _phantom1: PhantomData<T>,
}

impl<T, U> List<T, U> where T: Owner<U>, U: Node {
    pub fn new() -> Self {
        List {
            head: Link::none(),
            tail: Link::none(),
            _phantom1: PhantomData,
        }
    }

    pub fn front(&self) -> Option<&U> {
        self.head.as_ref()
    }

    pub fn back(&self) -> Option<&U> {
        self.tail.as_ref()
    }

    pub fn front_mut(&mut self) -> Option<&mut U> {
        self.head.as_mut()
    }

    pub fn back_mut(&mut self) -> Option<&mut U> {
        self.tail.as_mut()
    }

    pub fn is_empty(&mut self) -> bool {
        self.head == Link::none()
    }

    pub fn push_front(&mut self, mut elem: T) {
        match self.head.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.tail = Link::some(elem.get_mut());
            }
            Some(h) => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::some(h);

                *h.prev_mut() = Link::some(elem.get_mut());
            },
        }

        self.head = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn push_back(&mut self, mut elem: T) {
        match self.tail.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.head = Link::some(elem.get_mut());
            }
            Some(t) => {
                *elem.get_mut().prev_mut() = Link::some(t);
                *elem.get_mut().next_mut() = Link::none();

                *t.next_mut() = Link::some(elem.get_mut());
            }
        }

        self.tail = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().as_mut().and_then(|h| {
            match h.next_mut().as_mut() {
                None => self.tail = Link::none(),
                Some(n) => {
                    *n.prev_mut() = Link::none();

                    self.head = Link::some(n);
                }
            }

            Some(unsafe { T::from_raw_ptr(h) })
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|t| {
            match t.prev_mut().as_mut() {
                None => self.head = Link::none(),
                Some(p) => {
                    *p.next_mut() = Link::none();

                    self.tail = Link::some(p);
                }
            }

            Some(unsafe { T::from_raw_ptr(t) })
        })
    }
}

#[cfg(test)]
impl<T> Owner<T> for ::std::boxed::Box<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        &**self
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        &mut **self
    }

    #[inline]
    fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}

#[cfg(test)]
mod test {
    use std::boxed::Box;

    use list::{List, Node};
    use link::Link;

    #[derive(Debug)]
    struct UsizeNode {
        pub data: usize,
        prev: Link<UsizeNode>,
        next: Link<UsizeNode>,
    }

    impl UsizeNode {
        pub fn new(data: usize) -> Self {
            UsizeNode {
                data: data,
                prev: Link::none(),
                next: Link::none(),
            }
        }
    }

    impl Node for UsizeNode {
        fn prev(&self) -> &Link<Self> {
            &self.prev
        }

        fn next(&self) -> &Link<Self> {
            &self.next
        }

        fn prev_mut(&mut self) -> &mut Link<Self> {
            &mut self.prev
        }

        fn next_mut(&mut self) -> &mut Link<Self> {
            &mut self.next
        }
    }

    impl PartialEq for UsizeNode {
        fn eq(&self, rhs: &Self) -> bool { self.data == rhs.data }
    }

    #[test]
    fn test_basic() {
        let mut list = List::<Box<UsizeNode>, UsizeNode>::new();

        assert_eq!(list.front(), None);
        assert_eq!(list.back(), None);

        assert!(list.is_empty());

        list.push_front(Box::new(UsizeNode::new(2)));

        assert!(!list.is_empty());
        assert_eq!(list.front(), list.back());

        list.push_front(Box::new(UsizeNode::new(1)));
        list.push_front(Box::new(UsizeNode::new(0)));

        assert_eq!(list.front().unwrap().data, 0);
        assert_eq!(list.back().unwrap().data, 2);

        list.push_back(Box::new(UsizeNode::new(3)));
        assert_eq!(list.back().unwrap().data, 3);

        list.push_back(Box::new(UsizeNode::new(4)));
        assert_eq!(list.back().unwrap().data, 4);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 0);
        assert_eq!(list.pop_front().unwrap().data, 1);
        assert_eq!(list.pop_front().unwrap().data, 2);
        assert_eq!(list.pop_back().unwrap().data, 4);
        assert_eq!(list.pop_back().unwrap().data, 3);
        assert_eq!(list.pop_back(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(5)));
        assert_eq!(list.pop_front().unwrap().data, 5);
        assert_eq!(list.pop_front(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(6)));
        list.push_back(Box::new(UsizeNode::new(7)));

        assert!(!list.is_empty());

        list.front_mut().unwrap().data = 6;
        list.back_mut().unwrap().data = 7;

        assert_eq!(list.front().unwrap().data, 6);
        assert_eq!(list.back().unwrap().data, 7);

        assert_eq!(list.pop_back().unwrap().data, 7);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 6);
        assert!(list.pop_front().is_none());
        assert!(list.pop_back().is_none());

        assert!(list.is_empty());
    }
}
<commit_msg>libintrusive: list::List now accepts ptr::Unique<commit_after>//! Implementation of intrusive doubly linked list

use core::ptr::Unique;
use core::marker::PhantomData;

use link::Link;

pub trait Node: Sized {
    fn prev(&self) -> &Link<Self>;
    fn next(&self) -> &Link<Self>;

    fn prev_mut(&mut self) -> &mut Link<Self>;
    fn next_mut(&mut self) -> &mut Link<Self>;
}

pub trait Owner<T> where T: Node {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;

    fn take(self);

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self;
}

pub struct List<T, U> where T: Owner<U>, U: Node {
    head: Link<U>,
    tail: Link<U>,
    _phantom1: PhantomData<T>,
}

impl<T, U> List<T, U> where T: Owner<U>, U: Node {
    pub fn new() -> Self {
        List {
            head: Link::none(),
            tail: Link::none(),
            _phantom1: PhantomData,
        }
    }

    pub fn front(&self) -> Option<&U> {
        self.head.as_ref()
    }

    pub fn back(&self) -> Option<&U> {
        self.tail.as_ref()
    }

    pub fn front_mut(&mut self) -> Option<&mut U> {
        self.head.as_mut()
    }

    pub fn back_mut(&mut self) -> Option<&mut U> {
        self.tail.as_mut()
    }

    pub fn is_empty(&mut self) -> bool {
        self.head == Link::none()
    }

    pub fn push_front(&mut self, mut elem: T) {
        match self.head.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.tail = Link::some(elem.get_mut());
            }
            Some(h) => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::some(h);

                *h.prev_mut() = Link::some(elem.get_mut());
            },
        }

        self.head = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn push_back(&mut self, mut elem: T) {
        match self.tail.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.head = Link::some(elem.get_mut());
            }
            Some(t) => {
                *elem.get_mut().prev_mut() = Link::some(t);
                *elem.get_mut().next_mut() = Link::none();

                *t.next_mut() = Link::some(elem.get_mut());
            }
        }

        self.tail = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().as_mut().and_then(|h| {
            match h.next_mut().as_mut() {
                None => self.tail = Link::none(),
                Some(n) => {
                    *n.prev_mut() = Link::none();

                    self.head = Link::some(n);
                }
            }

            Some(unsafe { T::from_raw_ptr(h) })
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|t| {
            match t.prev_mut().as_mut() {
                None => self.head = Link::none(),
                Some(p) => {
                    *p.next_mut() = Link::none();

                    self.tail = Link::some(p);
                }
            }

            Some(unsafe { T::from_raw_ptr(t) })
        })
    }
}

impl<T> Owner<T> for Unique<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        unsafe { self.get() }
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        unsafe { self.get_mut() }
    }

    #[inline]
    fn take(self) {}

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(test)]
impl<T> Owner<T> for ::std::boxed::Box<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        &**self
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        &mut **self
    }

    #[inline]
    fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}

#[cfg(test)]
mod test {
    use core::ptr::Unique;

    use std::boxed::Box;

    use list::{List, Node};
    use link::Link;

    #[derive(Debug)]
    struct UsizeNode {
        pub data: usize,
        prev: Link<UsizeNode>,
        next: Link<UsizeNode>,
    }

    impl UsizeNode {
        pub fn new(data: usize) -> Self {
            UsizeNode {
                data: data,
                prev: Link::none(),
                next: Link::none(),
            }
        }
    }

    impl Node for UsizeNode {
        fn prev(&self) -> &Link<Self> {
            &self.prev
        }

        fn next(&self) -> &Link<Self> {
            &self.next
        }

        fn prev_mut(&mut self) -> &mut Link<Self> {
            &mut self.prev
        }

        fn next_mut(&mut self) -> &mut Link<Self> {
            &mut self.next
        }
    }

    impl PartialEq for UsizeNode {
        fn eq(&self, rhs: &Self) -> bool { self.data == rhs.data }
    }

    #[test]
    fn test_unique() {
        let one = Box::new(UsizeNode::new(1));
        let two = Box::new(UsizeNode::new(2));
        let three = Box::new(UsizeNode::new(3));

        let one_ptr = Box::into_raw(one);
        let two_ptr = Box::into_raw(two);
        let three_ptr = Box::into_raw(three);

        let one_unique = unsafe { Unique::new(one_ptr) };
        let two_unique = unsafe { Unique::new(two_ptr) };
        let three_unique = unsafe { Unique::new(three_ptr) };

        let mut list = List::<Unique<UsizeNode>, UsizeNode>::new();

        list.push_front(three_unique);
        list.push_front(two_unique);
        list.push_front(one_unique);

        unsafe {
            assert_eq!(list.pop_back().unwrap().get_mut().data, 3);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 2);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 1);
            assert!(list.pop_back().is_none());
        }

        // Cleanup
        unsafe {
            Box::from_raw(one_ptr);
            Box::from_raw(two_ptr);
            Box::from_raw(three_ptr);
        }
    }

    #[test]
    fn test_basic() {
        let mut list = List::<Box<UsizeNode>, UsizeNode>::new();

        assert_eq!(list.front(), None);
        assert_eq!(list.back(), None);

        assert!(list.is_empty());

        list.push_front(Box::new(UsizeNode::new(2)));

        assert!(!list.is_empty());
        assert_eq!(list.front(), list.back());

        list.push_front(Box::new(UsizeNode::new(1)));
        list.push_front(Box::new(UsizeNode::new(0)));

        assert_eq!(list.front().unwrap().data, 0);
        assert_eq!(list.back().unwrap().data, 2);

        list.push_back(Box::new(UsizeNode::new(3)));
        assert_eq!(list.back().unwrap().data, 3);

        list.push_back(Box::new(UsizeNode::new(4)));
        assert_eq!(list.back().unwrap().data, 4);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 0);
        assert_eq!(list.pop_front().unwrap().data, 1);
        assert_eq!(list.pop_front().unwrap().data, 2);
        assert_eq!(list.pop_back().unwrap().data, 4);
        assert_eq!(list.pop_back().unwrap().data, 3);
        assert_eq!(list.pop_back(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(5)));
        assert_eq!(list.pop_front().unwrap().data, 5);
        assert_eq!(list.pop_front(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(6)));
        list.push_back(Box::new(UsizeNode::new(7)));

        assert!(!list.is_empty());

        list.front_mut().unwrap().data = 6;
        list.back_mut().unwrap().data = 7;

        assert_eq!(list.front().unwrap().data, 6);
        assert_eq!(list.back().unwrap().data, 7);

        assert_eq!(list.pop_back().unwrap().data, 7);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 6);
        assert!(list.pop_front().is_none());
        assert!(list.pop_back().is_none());

        assert!(list.is_empty());
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 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.

//! Global initialization and retreival of command line arguments.
//!
//! On some platforms these are stored during runtime startup,
//! and on some they are retrieved from the system on demand.

#![allow(dead_code)] // runtime init functions not used during testing

use ffi::OsString;
use marker::PhantomData;
use vec;

/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }

/// One-time global cleanup.
pub unsafe fn cleanup() { imp::cleanup() }

/// Returns the command line arguments
pub fn args() -> Args {
    imp::args()
}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.iter.len() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
}

mod imp {
    use os::unix::prelude::*;
    use mem;
    use ffi::OsString;
    use marker::PhantomData;
    use slice;
    use str;
    use super::Args;

    use sys_common::mutex::Mutex;

    static mut GLOBAL_ARGS_PTR: usize = 0;
    static LOCK: Mutex = Mutex::new();

    pub unsafe fn init(argc: isize, argv: *const *const u8) {
        let mut args: Vec<Vec<u8>> = Vec::new();
        for i in 0..argc {
            let len = *(argv.offset(i * 2)) as usize;
            let ptr = *(argv.offset(i * 2 + 1));
            args.push(slice::from_raw_parts(ptr, len).to_vec());
        }

        LOCK.lock();
        let ptr = get_global_ptr();
        assert!((*ptr).is_none());
        (*ptr) = Some(box args);
        LOCK.unlock();
    }

    pub unsafe fn cleanup() {
        LOCK.lock();
        *get_global_ptr() = None;
        LOCK.unlock();
    }

    pub fn args() -> Args {
        let bytes = clone().unwrap_or(Vec::new());
        let v: Vec<OsString> = bytes.into_iter().map(|v| {
            OsStringExt::from_vec(v)
        }).collect();
        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
    }

    fn clone() -> Option<Vec<Vec<u8>>> {
        unsafe {
            LOCK.lock();
            let ptr = get_global_ptr();
            let ret = (*ptr).as_ref().map(|s| (**s).clone());
            LOCK.unlock();
            return ret
        }
    }

    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
    }

}
<commit_msg>Auto merge of #38626 - redox-os:args_fix, r=alexcrichton<commit_after>// Copyright 2016 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.

//! Global initialization and retreival of command line arguments.
//!
//! On some platforms these are stored during runtime startup,
//! and on some they are retrieved from the system on demand.

#![allow(dead_code)] // runtime init functions not used during testing

use ffi::OsString;
use marker::PhantomData;
use vec;

/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }

/// One-time global cleanup.
pub unsafe fn cleanup() { imp::cleanup() }

/// Returns the command line arguments
pub fn args() -> Args {
    imp::args()
}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.iter.len() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
}

mod imp {
    use os::unix::prelude::*;
    use mem;
    use ffi::{CStr, OsString};
    use marker::PhantomData;
    use libc;
    use super::Args;

    use sys_common::mutex::Mutex;

    static mut GLOBAL_ARGS_PTR: usize = 0;
    static LOCK: Mutex = Mutex::new();

    pub unsafe fn init(argc: isize, argv: *const *const u8) {
        let args = (0..argc).map(|i| {
            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
        }).collect();

        LOCK.lock();
        let ptr = get_global_ptr();
        assert!((*ptr).is_none());
        (*ptr) = Some(box args);
        LOCK.unlock();
    }

    pub unsafe fn cleanup() {
        LOCK.lock();
        *get_global_ptr() = None;
        LOCK.unlock();
    }

    pub fn args() -> Args {
        let bytes = clone().unwrap_or(Vec::new());
        let v: Vec<OsString> = bytes.into_iter().map(|v| {
            OsStringExt::from_vec(v)
        }).collect();
        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
    }

    fn clone() -> Option<Vec<Vec<u8>>> {
        unsafe {
            LOCK.lock();
            let ptr = get_global_ptr();
            let ret = (*ptr).as_ref().map(|s| (**s).clone());
            LOCK.unlock();
            return ret
        }
    }

    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
    }

}
<|endoftext|>


<commit_before>// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80
// characters.  In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use
// `:set tw=0` to disable.
register_diagnostics! {

E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.

For example:

```compile_fail,E0178
trait Foo {}

struct Bar<'a> {
    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```

More details can be found in [RFC 438].

[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,

E0536: r##"
The `not` cfg-predicate was malformed.

Erroneous code example:

```compile_fail,E0536
#[cfg(not())] // error: expected 1 cfg-pattern
pub fn something() {}

pub fn main() {}
```

The `not` predicate expects one cfg-pattern. Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0537: r##"
An unknown predicate was used inside the `cfg` attribute.

Erroneous code example:

```compile_fail,E0537
#[cfg(unknown())] // error: invalid predicate `unknown`
pub fn something() {}

pub fn main() {}
```

The `cfg` attribute supports only three kinds of predicates:

 * any
 * all
 * not

Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0538: r##"
Attribute contains same meta item more than once.

Erroneous code example:

```compile_fail,E0538
#[deprecated(
    since="1.0.0",
    note="First deprecation note.",
    note="Second deprecation note." // error: multiple same meta item
)]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. Each key may only be
used once in each attribute.

To fix the problem, remove all but one of the meta items with the same key.

Example:

```
#[deprecated(
    since="1.0.0",
    note="First deprecation note."
)]
fn deprecated_function() {}
```
"##,

E0541: r##"
An unknown meta item was used.

Erroneous code example:

```compile_fail,E0541
#[deprecated(
    since="1.0.0",
    // error: unknown meta item
    reason="Example invalid meta item. Should be 'note'")
]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. The keys provided
must be one of the valid keys for the specified attribute.

To fix the problem, either remove the unknown meta item, or rename it if you
provided the wrong name.

In the erroneous code example above, the wrong name was provided, so changing
to a correct one it will fix the error. Example:

```
#[deprecated(
    since="1.0.0",
    note="This is a valid meta item for the deprecated attribute."
)]
fn deprecated_function() {}
```
"##,

E0552: r##"
A unrecognized representation attribute was used.

Erroneous code example:

```compile_fail,E0552
#[repr(D)] // error: unrecognized representation hint
struct MyStruct {
    my_field: usize
}
```

You can use a `repr` attribute to tell the compiler how you want a struct or
enum to be laid out in memory.

Make sure you're using one of the supported options:

```
#[repr(C)] // ok!
struct MyStruct {
    my_field: usize
}
```

For more information about specifying representations, see the ["Alternative
Representations" section] of the Rustonomicon.

["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html
"##,

E0554: r##"
Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.

Example of erroneous code (on a stable compiler):

```ignore (depends on release channel)
#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the
                              //        stable release channel
```

If you need the feature, make sure to use a nightly release of the compiler
(but be warned that the feature may be removed or altered in the future).
"##,

E0557: r##"
A feature attribute named a feature that has been removed.

Erroneous code example:

```compile_fail,E0557
#![feature(managed_boxes)] // error: feature has been removed
```

Delete the offending feature attribute.
"##,

E0565: r##"
A literal was used in a built-in attribute that doesn't support literals.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[inline("always")] // error: unsupported literal
pub fn something() {}
```

Literals in attributes are new and largely unsupported in built-in attributes.
Work to support literals where appropriate is ongoing. Try using an unquoted
name instead:

```
#[inline(always)]
pub fn something() {}
```
"##,

E0583: r##"
A file wasn't found for an out-of-line module.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
mod file_that_doesnt_exist; // error: file not found for module

fn main() {}
```

Please be sure that a file corresponding to the module exists. If you
want to use a module named `file_that_doesnt_exist`, you need to have a file
named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the
same directory.
"##,

E0585: r##"
A documentation comment that doesn't document anything was found.

Erroneous code example:

```compile_fail,E0585
fn main() {
    // The following doc comment will fail:
    /// This is a useless doc comment!
}
```

Documentation comments need to be followed by items, including functions,
types, modules, etc. Examples:

```
/// I'm documenting the following struct:
struct Foo;

/// I'm documenting the following function:
fn foo() {}
```
"##,

E0586: r##"
An inclusive range was used with no end.

Erroneous code example:

```compile_fail,E0586
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=]; // error: inclusive range was used with no end
}
```

An inclusive range needs an end in order to *include* it. If you just need a
start and no end, use a non-inclusive range (with `..`):

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..]; // ok!
}
```

Or put an end to your inclusive range:

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=3]; // ok!
}
```
"##,

E0589: r##"
The value of `N` that was specified for `repr(align(N))` was not a power
of two, or was greater than 2^29.

```compile_fail,E0589
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
enum Foo {
    Bar(u64),
}
```
"##,

E0658: r##"
An unstable feature was used.

Erroneous code example:

```compile_fail,E658
#[repr(u128)] // error: use of unstable library feature 'repr128'
enum Foo {
    Bar(u64),
}
```

If you're using a stable or a beta version of rustc, you won't be able to use
any unstable features. In order to do so, please switch to a nightly version of
rustc (by using rustup).

If you're using a nightly version of rustc, just add the corresponding feature
to be able to use it:

```
#![feature(repr128)]

#[repr(u128)] // ok!
enum Foo {
    Bar(u64),
}
```
"##,

E0633: r##"
The `unwind` attribute was malformed.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[unwind()] // error: expected one argument
pub extern fn something() {}

fn main() {}
```

The `#[unwind]` attribute should be used as follows:

- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function
  should abort the process if it attempts to unwind. This is the safer
  and preferred option.

- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function
  should be allowed to unwind. This can easily result in Undefined
  Behavior (UB), so be careful.

NB. The default behavior here is "allowed", but this is unspecified
and likely to change in the future.

"##,

E0704: r##"
This error indicates that a incorrect visibility restriction was specified.

Example of erroneous code:

```compile_fail,E0704
mod foo {
    pub(foo) struct Bar {
        x: i32
    }
}
```

To make struct `Bar` only visible in module `foo` the `in` keyword should be
used:
```
mod foo {
    pub(in crate::foo) struct Bar {
        x: i32
    }
}
# fn main() {}
```

For more information see the Rust Reference on [Visibility].

[Visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html
"##,

E0705: r##"
A `#![feature]` attribute was declared for a feature that is stable in
the current edition, but not in all editions.

Erroneous code example:

```ignore (limited to a warning during 2018 edition development)
#![feature(rust_2018_preview)]
#![feature(test_2018_feature)] // error: the feature
                               // `test_2018_feature` is
                               // included in the Rust 2018 edition
```

"##,

E0725: r##"
A feature attribute named a feature that was disallowed in the compiler
command line flags.

Erroneous code example:

```ignore (can't specify compiler flags from doctests)
#![feature(never_type)] // error: the feature `never_type` is not in
                        // the list of allowed features
```

Delete the offending feature attribute, or add it to the list of allowed
features in the `-Z allow_features` flag.
"##,

;

    E0539, // incorrect meta item
    E0540, // multiple rustc_deprecated attributes
    E0542, // missing 'since'
    E0543, // missing 'reason'
    E0544, // multiple stability levels
    E0545, // incorrect 'issue'
    E0546, // missing 'feature'
    E0547, // missing 'issue'
//  E0548, // replaced with a generic attribute input check
    // rustc_deprecated attribute must be paired with either stable or unstable
    // attribute
    E0549,
    E0550, // multiple deprecated attributes
    E0551, // incorrect meta item
    E0553, // multiple rustc_const_unstable attributes
//  E0555, // replaced with a generic attribute input check
    E0556, // malformed feature, expected just one word
    E0584, // file for module `..` found at both .. and ..
    E0629, // missing 'feature' (rustc_const_unstable)
    // rustc_const_unstable attribute must be paired with stable/unstable
    // attribute
    E0630,
    E0693, // incorrect `repr(align)` attribute format
//  E0694, // an unknown tool name found in scoped attributes
    E0703, // invalid ABI
    E0717, // rustc_promotable without stability attribute
}
<commit_msg>Add long error explanation for E0550<commit_after>// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80
// characters.  In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use
// `:set tw=0` to disable.
register_diagnostics! {

E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.

For example:

```compile_fail,E0178
trait Foo {}

struct Bar<'a> {
    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```

More details can be found in [RFC 438].

[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,

E0536: r##"
The `not` cfg-predicate was malformed.

Erroneous code example:

```compile_fail,E0536
#[cfg(not())] // error: expected 1 cfg-pattern
pub fn something() {}

pub fn main() {}
```

The `not` predicate expects one cfg-pattern. Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0537: r##"
An unknown predicate was used inside the `cfg` attribute.

Erroneous code example:

```compile_fail,E0537
#[cfg(unknown())] // error: invalid predicate `unknown`
pub fn something() {}

pub fn main() {}
```

The `cfg` attribute supports only three kinds of predicates:

 * any
 * all
 * not

Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0538: r##"
Attribute contains same meta item more than once.

Erroneous code example:

```compile_fail,E0538
#[deprecated(
    since="1.0.0",
    note="First deprecation note.",
    note="Second deprecation note." // error: multiple same meta item
)]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. Each key may only be
used once in each attribute.

To fix the problem, remove all but one of the meta items with the same key.

Example:

```
#[deprecated(
    since="1.0.0",
    note="First deprecation note."
)]
fn deprecated_function() {}
```
"##,

E0541: r##"
An unknown meta item was used.

Erroneous code example:

```compile_fail,E0541
#[deprecated(
    since="1.0.0",
    // error: unknown meta item
    reason="Example invalid meta item. Should be 'note'")
]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. The keys provided
must be one of the valid keys for the specified attribute.

To fix the problem, either remove the unknown meta item, or rename it if you
provided the wrong name.

In the erroneous code example above, the wrong name was provided, so changing
to a correct one it will fix the error. Example:

```
#[deprecated(
    since="1.0.0",
    note="This is a valid meta item for the deprecated attribute."
)]
fn deprecated_function() {}
```
"##,

E0550: r##"
More than one `deprecated` attribute has been put on an item.

Erroneous code example:

```compile_fail,E0550
#[deprecated(note = "because why not?")]
#[deprecated(note = "right?")] // error!
fn the_banished() {}
```

The `deprecated` attribute can only be present **once** on an item.

```
#[deprecated(note = "because why not, right?")]
fn the_banished() {} // ok!
```
"##,

E0552: r##"
A unrecognized representation attribute was used.

Erroneous code example:

```compile_fail,E0552
#[repr(D)] // error: unrecognized representation hint
struct MyStruct {
    my_field: usize
}
```

You can use a `repr` attribute to tell the compiler how you want a struct or
enum to be laid out in memory.

Make sure you're using one of the supported options:

```
#[repr(C)] // ok!
struct MyStruct {
    my_field: usize
}
```

For more information about specifying representations, see the ["Alternative
Representations" section] of the Rustonomicon.

["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html
"##,

E0554: r##"
Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.

Example of erroneous code (on a stable compiler):

```ignore (depends on release channel)
#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the
                              //        stable release channel
```

If you need the feature, make sure to use a nightly release of the compiler
(but be warned that the feature may be removed or altered in the future).
"##,

E0557: r##"
A feature attribute named a feature that has been removed.

Erroneous code example:

```compile_fail,E0557
#![feature(managed_boxes)] // error: feature has been removed
```

Delete the offending feature attribute.
"##,

E0565: r##"
A literal was used in a built-in attribute that doesn't support literals.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[inline("always")] // error: unsupported literal
pub fn something() {}
```

Literals in attributes are new and largely unsupported in built-in attributes.
Work to support literals where appropriate is ongoing. Try using an unquoted
name instead:

```
#[inline(always)]
pub fn something() {}
```
"##,

E0583: r##"
A file wasn't found for an out-of-line module.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
mod file_that_doesnt_exist; // error: file not found for module

fn main() {}
```

Please be sure that a file corresponding to the module exists. If you
want to use a module named `file_that_doesnt_exist`, you need to have a file
named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the
same directory.
"##,

E0585: r##"
A documentation comment that doesn't document anything was found.

Erroneous code example:

```compile_fail,E0585
fn main() {
    // The following doc comment will fail:
    /// This is a useless doc comment!
}
```

Documentation comments need to be followed by items, including functions,
types, modules, etc. Examples:

```
/// I'm documenting the following struct:
struct Foo;

/// I'm documenting the following function:
fn foo() {}
```
"##,

E0586: r##"
An inclusive range was used with no end.

Erroneous code example:

```compile_fail,E0586
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=]; // error: inclusive range was used with no end
}
```

An inclusive range needs an end in order to *include* it. If you just need a
start and no end, use a non-inclusive range (with `..`):

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..]; // ok!
}
```

Or put an end to your inclusive range:

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=3]; // ok!
}
```
"##,

E0589: r##"
The value of `N` that was specified for `repr(align(N))` was not a power
of two, or was greater than 2^29.

```compile_fail,E0589
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
enum Foo {
    Bar(u64),
}
```
"##,

E0658: r##"
An unstable feature was used.

Erroneous code example:

```compile_fail,E658
#[repr(u128)] // error: use of unstable library feature 'repr128'
enum Foo {
    Bar(u64),
}
```

If you're using a stable or a beta version of rustc, you won't be able to use
any unstable features. In order to do so, please switch to a nightly version of
rustc (by using rustup).

If you're using a nightly version of rustc, just add the corresponding feature
to be able to use it:

```
#![feature(repr128)]

#[repr(u128)] // ok!
enum Foo {
    Bar(u64),
}
```
"##,

E0633: r##"
The `unwind` attribute was malformed.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[unwind()] // error: expected one argument
pub extern fn something() {}

fn main() {}
```

The `#[unwind]` attribute should be used as follows:

- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function
  should abort the process if it attempts to unwind. This is the safer
  and preferred option.

- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function
  should be allowed to unwind. This can easily result in Undefined
  Behavior (UB), so be careful.

NB. The default behavior here is "allowed", but this is unspecified
and likely to change in the future.

"##,

E0704: r##"
This error indicates that a incorrect visibility restriction was specified.

Example of erroneous code:

```compile_fail,E0704
mod foo {
    pub(foo) struct Bar {
        x: i32
    }
}
```

To make struct `Bar` only visible in module `foo` the `in` keyword should be
used:
```
mod foo {
    pub(in crate::foo) struct Bar {
        x: i32
    }
}
# fn main() {}
```

For more information see the Rust Reference on [Visibility].

[Visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html
"##,

E0705: r##"
A `#![feature]` attribute was declared for a feature that is stable in
the current edition, but not in all editions.

Erroneous code example:

```ignore (limited to a warning during 2018 edition development)
#![feature(rust_2018_preview)]
#![feature(test_2018_feature)] // error: the feature
                               // `test_2018_feature` is
                               // included in the Rust 2018 edition
```

"##,

E0725: r##"
A feature attribute named a feature that was disallowed in the compiler
command line flags.

Erroneous code example:

```ignore (can't specify compiler flags from doctests)
#![feature(never_type)] // error: the feature `never_type` is not in
                        // the list of allowed features
```

Delete the offending feature attribute, or add it to the list of allowed
features in the `-Z allow_features` flag.
"##,

;

    E0539, // incorrect meta item
    E0540, // multiple rustc_deprecated attributes
    E0542, // missing 'since'
    E0543, // missing 'reason'
    E0544, // multiple stability levels
    E0545, // incorrect 'issue'
    E0546, // missing 'feature'
    E0547, // missing 'issue'
//  E0548, // replaced with a generic attribute input check
    // rustc_deprecated attribute must be paired with either stable or unstable
    // attribute
    E0549,
    E0551, // incorrect meta item
    E0553, // multiple rustc_const_unstable attributes
//  E0555, // replaced with a generic attribute input check
    E0556, // malformed feature, expected just one word
    E0584, // file for module `..` found at both .. and ..
    E0629, // missing 'feature' (rustc_const_unstable)
    // rustc_const_unstable attribute must be paired with stable/unstable
    // attribute
    E0630,
    E0693, // incorrect `repr(align)` attribute format
//  E0694, // an unknown tool name found in scoped attributes
    E0703, // invalid ABI
    E0717, // rustc_promotable without stability attribute
}
<|endoftext|>


<commit_before>use seed::prelude::*;
use crate::Msg;

extern crate num_bigint as bigint;
extern crate num_traits;

use crate::utils::nth;
use regex::Regex;

mod numerics_to_text {
    use num_traits::{Num,ToPrimitive,Zero};
    use num_bigint::{BigUint,ToBigUint};

    pub fn convert(str_num: String) -> String{
        let units:Vec<&str> = vec![
            "",
            " one",
            " two",
            " three",
            " four",
            " five",
            " six",
            " seven",
            " eight",
            " nine",
            " ten",
            " eleven",
            " twelve",
            " thirteen",
            " fourteen",
            " fifteen",
            " sixteen",
            " seventeen",
            " eighteen",
            " nineteen"
        ];
        let tens:Vec<&str> = vec![
            "",
            "",
            " twenty",
            " thirty",
            " forty",
            " fifty",
            " sixty",
            " seventy",
            " eighty",
            " ninety"
        ];
        let triplets:Vec<&str> = vec![
            "",
            " thousand",
            " million",
            " billion",
            " trillion",
            " quadrillion",
            " quintillion",
            " sextillion",
            " septillion",
            " octillion",
            " nonillion",
            " decillion",
            " undecillion",
            " duodecillion",
            " tredecillion",
            " quattuordecillion",
            " quindecillion",
            " sexdecillion",
            " septendecillion",
            " octodecillion",
            " novemdecillion",
            " vigintillion",
            " unvigintillion",
            " duovigintillion",
            " tresvigintillion",
            " quattuorvigintillion",
            " quinquavigintillion",
            " sesvigintillion",
            " septemvigintillion",
            " octovigintillion",
            " novemvigintillion",
            " trigintillion",
            " untrigintillion",
            " duotrigintillion",
            " trestrigintillion",
            " quattuortrigintillion",
            " quinquatrigintillion",
            " sestrigintillion",
            " septentrigintillion",
            " octotrigintillion",
            " noventrigintillion",
            " quadragintillion",
            " ERROR ",
        ];

        let num:BigUint = num_bigint::BigUint::from_str_radix(&str_num, 10).unwrap();
        let string:String = convert_tri(num, Zero::zero(), units, tens, triplets);
        //remove first character which is a space
        string[1..].to_string()
    }

    fn convert_tri(num:BigUint, tri:usize, units:Vec<&str>, tens:Vec<&str>, triplets:Vec<&str>) -> String {
        // chunk the number, ...rxyy
        let ten:BigUint = 10.to_biguint().unwrap();
        let hundred:BigUint = 100.to_biguint().unwrap();
        let thousand:BigUint = 1000.to_biguint().unwrap();
        let r = &num / &thousand; // this in theory is rounding down to an int
        let x:usize = ((&num / &hundred) % &ten).to_usize().unwrap();
        let y:usize = (&num % &hundred).to_usize().unwrap();
        // init the output string
        let mut string:String = "".to_owned();
        // do hundreds
        if x > 0 {
            string.push_str(units[x]);
            string.push_str(" hundred");
        }
        // do units and tens
        if y < 20 {
            string.push_str(units[y]);
        } else {
            string.push_str(tens[(y / 10)]);
            string.push_str(units[(y % 10)]);
        }
        // add triplet modifier only if there
        // is some output to be modified...
        if string != "" {
            match triplets[tri] {
                _s => string.push_str(&triplets[tri].to_string()),
            }
        }
        // continue recursing?
        if r > Zero::zero() {
            let mut string2:String = convert_tri(r, tri + 1, units, tens, triplets);
            string2.push_str(&string);
            string2
        } else {
            string
        }
    }

}

fn html_form() -> seed::dom_types::Node<Msg> {
    div![
        h1!["Number Cruncher"],
        "Welcome to the number cruncher.
        Type in a number in the box below and we will crunch it for you.",
        br![],
        br![],
        "You will be taken to a page that tells you the following information about your number:",
        ul![
            li!["Is it odd or even?"],
            li!["Is it a palindrome?"],
            li!["Is it a prime number? (Checks numbers upto 11 digits in length)"],
            li!["Is it a ",a!["mersenne prime", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Mersenne_prime"}],"? (Checks numbers upto 2993 digits in length)"],
            li!["Is it a ",a!["fermat prime", attrs!{At::Class => "link", At::Href => "https://www.fermatsearch.org/"}],"? (Checks numbers upto 155 digits in length"],
            li!["Is it a ",a!["perfect number", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Perfect_number"}],"? (Checks numbers upto 12003 digits in length)"],
            li!["Is it a triangle number? (Checks numbers upto 40 digits in length)"],
            li!["Is it a square number?"],
            li!["Is it a cube number? (Checks numbers upto 17 digits in length)"],
            li!["Is it a factorial number?"],
            br![],
            br![],
            li!["All factors of the number will be listed (for numbers upto 9 digits)"],
            li!["The page will also show a list of base conversions. e.g. binary, octal and hexadecimal (Numbers upto 500 digits in length)"],
            li!["The number will be converted to roman numerals (Upto 6 digits in length)"],
            li!["The number will be converted to egyptian numerals (Upto 7 digits in length)"],
            li!["The number will be converted to chinese numerals (Upto 6 digits in length)"],
            li!["The number will be converted to babylonian numerals (Upto 13 digits in length)"],
        ],
        br![],
        br![],
	    "Please type your number here:",
        form![attrs!{At::Name => "crunchy", At::Action => "/cruncher/", At::Method => "get", At::Target => "_top"},
            div![
                textarea![attrs!{At::Name => "number", At::Cols => "85", At::Rows => "10", At::OnKeyDown => "if (event.keyCode == 13){document.location='/cruncher/'+crunchy.number.value+'/'}"}],
                br![],
                input![attrs!{At::Type => "button", At::Value => "Crunch", At::OnClick => "document.location='/cruncher/'+crunchy.number.value+'/'"}],
            ],
        ],
    ]
}

fn html_crunched_number(slug:String) -> seed::dom_types::Node<Msg> {
    let table_style = style!{"border" => "1px #000 solid"};
    div![style!{"width" => "75%"; "padding" => "3px"},
        br![],
        br![],
        b!["The number you submitted to be crunched was:"],
        h1![slug.to_string()," - ",numerics_to_text::convert(slug.to_string())],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It is an odd number.",
                        br![],
                        "It is the ",nth(4)," prime number.",
                        br![],
                        "It is the 2nd ",a!["mersenne prime", attrs!{At::Class => "link", At::Href => "http://en.wikipedia.org/wiki/Mersenne_prime"}],".",
                        br![],
                        "It is not a ",a!["fermat prime", attrs!{At::Class => "link", At::Href => "https://www.fermatsearch.org/"}],".",
                        br![],
                        "It is not a ",a!["perfect number", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Perfect_number"}],".",
                        br![],
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It is not a triangle number.",
                        br![],
                        "It is not a square number.",
                        br![],
                        "It is not a cube number.",
                        br![],
                        br![],
                        "It is not a factorial number.",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It it has no factors except itself and 1.",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 2 (Binary):",
                    ],
                    td![
                        "111",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 3 (Ternary):",
                    ],
                    td![
                        "21",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 4 (Quaternary):",
                    ],
                    td![
                        "13",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 5 (Quinary):",
                    ],
                    td![
                        "12",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 8 (Octal):",
                    ],
                    td![
                        "7",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 10 (Denary):",
                    ],
                    td![
                        "7",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 16 (Hexadecimal):",
                    ],
                    td![
                        "7",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![attrs!{At::Width => "200"},
                        "Roman Numerals:",
                    ],
                    td![attrs!{At::Width => "40"},
                        "VII",
                    ],
                ],
                tr![
                    td![
                        "Egyptian Numerals:",
                    ],
                    td![
                        "𓐀",
                    ]
                ],
                tr![
                    td![
                        "Chinese Numerals:",
                    ],
                    td![style!{"vertical-align" => "middle"; "background-color" => "#FFF"},
                        "柒",
                    ]
                ],
                tr![
                    td![
                        "Babylonian Numerals:",
                    ],
                    td![style!{"vertical-align" => "middle"; "background-color" => "#FFF"},
                        img![attrs!{At::Src => "https://static.bigprimes.net/imgs/babnumbers/bab_7.gif", At::Alt => "7"}],
                    ]
                ],
            ],
        ],
    ]
}

pub fn render(slug:String) -> seed::dom_types::Node<Msg> {
    let rgx = Regex::new(r"^([1-9]+[0-9]*)$").unwrap();

    match rgx.is_match(&slug) {
        true => html_crunched_number(slug),
        _ => html_form()
    }
}

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

    #[test]
    fn numerics_to_text_test() {
        assert_eq!(numerics_to_text::convert("170".to_string()), "one hundred seventy");
        assert_eq!(numerics_to_text::convert("90001".to_string()), "ninety thousand one");
    }
}<commit_msg>Added an extreme unit test for numerics_to_text()<commit_after>use seed::prelude::*;
use crate::Msg;

extern crate num_bigint as bigint;
extern crate num_traits;

use crate::utils::nth;
use regex::Regex;

mod numerics_to_text {
    use num_traits::{Num,ToPrimitive,Zero};
    use num_bigint::{BigUint,ToBigUint};

    pub fn convert(str_num: String) -> String{
        let units:Vec<&str> = vec![
            "",
            " one",
            " two",
            " three",
            " four",
            " five",
            " six",
            " seven",
            " eight",
            " nine",
            " ten",
            " eleven",
            " twelve",
            " thirteen",
            " fourteen",
            " fifteen",
            " sixteen",
            " seventeen",
            " eighteen",
            " nineteen"
        ];
        let tens:Vec<&str> = vec![
            "",
            "",
            " twenty",
            " thirty",
            " forty",
            " fifty",
            " sixty",
            " seventy",
            " eighty",
            " ninety"
        ];
        let triplets:Vec<&str> = vec![
            "",
            " thousand",
            " million",
            " billion",
            " trillion",
            " quadrillion",
            " quintillion",
            " sextillion",
            " septillion",
            " octillion",
            " nonillion",
            " decillion",
            " undecillion",
            " duodecillion",
            " tredecillion",
            " quattuordecillion",
            " quindecillion",
            " sexdecillion",
            " septendecillion",
            " octodecillion",
            " novemdecillion",
            " vigintillion",
            " unvigintillion",
            " duovigintillion",
            " tresvigintillion",
            " quattuorvigintillion",
            " quinquavigintillion",
            " sesvigintillion",
            " septemvigintillion",
            " octovigintillion",
            " novemvigintillion",
            " trigintillion",
            " untrigintillion",
            " duotrigintillion",
            " trestrigintillion",
            " quattuortrigintillion",
            " quinquatrigintillion",
            " sestrigintillion",
            " septentrigintillion",
            " octotrigintillion",
            " noventrigintillion",
            " quadragintillion",
            " ERROR ",
        ];

        let num:BigUint = num_bigint::BigUint::from_str_radix(&str_num, 10).unwrap();
        let string:String = convert_tri(num, Zero::zero(), units, tens, triplets);
        //remove first character which is a space
        string[1..].to_string()
    }

    fn convert_tri(num:BigUint, tri:usize, units:Vec<&str>, tens:Vec<&str>, triplets:Vec<&str>) -> String {
        // chunk the number, ...rxyy
        let ten:BigUint = 10.to_biguint().unwrap();
        let hundred:BigUint = 100.to_biguint().unwrap();
        let thousand:BigUint = 1000.to_biguint().unwrap();
        let r = &num / &thousand; // this in theory is rounding down to an int
        let x:usize = ((&num / &hundred) % &ten).to_usize().unwrap();
        let y:usize = (&num % &hundred).to_usize().unwrap();
        // init the output string
        let mut string:String = "".to_owned();
        // do hundreds
        if x > 0 {
            string.push_str(units[x]);
            string.push_str(" hundred");
        }
        // do units and tens
        if y < 20 {
            string.push_str(units[y]);
        } else {
            string.push_str(tens[(y / 10)]);
            string.push_str(units[(y % 10)]);
        }
        // add triplet modifier only if there
        // is some output to be modified...
        if string != "" {
            match triplets[tri] {
                _s => string.push_str(&triplets[tri].to_string()),
            }
        }
        // continue recursing?
        if r > Zero::zero() {
            let mut string2:String = convert_tri(r, tri + 1, units, tens, triplets);
            string2.push_str(&string);
            string2
        } else {
            string
        }
    }

}

fn html_form() -> seed::dom_types::Node<Msg> {
    div![
        h1!["Number Cruncher"],
        "Welcome to the number cruncher.
        Type in a number in the box below and we will crunch it for you.",
        br![],
        br![],
        "You will be taken to a page that tells you the following information about your number:",
        ul![
            li!["Is it odd or even?"],
            li!["Is it a palindrome?"],
            li!["Is it a prime number? (Checks numbers upto 11 digits in length)"],
            li!["Is it a ",a!["mersenne prime", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Mersenne_prime"}],"? (Checks numbers upto 2993 digits in length)"],
            li!["Is it a ",a!["fermat prime", attrs!{At::Class => "link", At::Href => "https://www.fermatsearch.org/"}],"? (Checks numbers upto 155 digits in length"],
            li!["Is it a ",a!["perfect number", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Perfect_number"}],"? (Checks numbers upto 12003 digits in length)"],
            li!["Is it a triangle number? (Checks numbers upto 40 digits in length)"],
            li!["Is it a square number?"],
            li!["Is it a cube number? (Checks numbers upto 17 digits in length)"],
            li!["Is it a factorial number?"],
            br![],
            br![],
            li!["All factors of the number will be listed (for numbers upto 9 digits)"],
            li!["The page will also show a list of base conversions. e.g. binary, octal and hexadecimal (Numbers upto 500 digits in length)"],
            li!["The number will be converted to roman numerals (Upto 6 digits in length)"],
            li!["The number will be converted to egyptian numerals (Upto 7 digits in length)"],
            li!["The number will be converted to chinese numerals (Upto 6 digits in length)"],
            li!["The number will be converted to babylonian numerals (Upto 13 digits in length)"],
        ],
        br![],
        br![],
	    "Please type your number here:",
        form![attrs!{At::Name => "crunchy", At::Action => "/cruncher/", At::Method => "get", At::Target => "_top"},
            div![
                textarea![attrs!{At::Name => "number", At::Cols => "85", At::Rows => "10", At::OnKeyDown => "if (event.keyCode == 13){document.location='/cruncher/'+crunchy.number.value+'/'}"}],
                br![],
                input![attrs!{At::Type => "button", At::Value => "Crunch", At::OnClick => "document.location='/cruncher/'+crunchy.number.value+'/'"}],
            ],
        ],
    ]
}

fn html_crunched_number(slug:String) -> seed::dom_types::Node<Msg> {
    let table_style = style!{"border" => "1px #000 solid"};
    div![style!{"width" => "75%"; "padding" => "3px"},
        br![],
        br![],
        b!["The number you submitted to be crunched was:"],
        h1![slug.to_string()," - ",numerics_to_text::convert(slug.to_string())],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It is an odd number.",
                        br![],
                        "It is the ",nth(4)," prime number.",
                        br![],
                        "It is the 2nd ",a!["mersenne prime", attrs!{At::Class => "link", At::Href => "http://en.wikipedia.org/wiki/Mersenne_prime"}],".",
                        br![],
                        "It is not a ",a!["fermat prime", attrs!{At::Class => "link", At::Href => "https://www.fermatsearch.org/"}],".",
                        br![],
                        "It is not a ",a!["perfect number", attrs!{At::Class => "link", At::Href => "https://en.wikipedia.org/wiki/Perfect_number"}],".",
                        br![],
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It is not a triangle number.",
                        br![],
                        "It is not a square number.",
                        br![],
                        "It is not a cube number.",
                        br![],
                        br![],
                        "It is not a factorial number.",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![
                        "It it has no factors except itself and 1.",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 2 (Binary):",
                    ],
                    td![
                        "111",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 3 (Ternary):",
                    ],
                    td![
                        "21",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 4 (Quaternary):",
                    ],
                    td![
                        "13",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 5 (Quinary):",
                    ],
                    td![
                        "12",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 8 (Octal):",
                    ],
                    td![
                        "7",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 10 (Denary):",
                    ],
                    td![
                        "7",
                    ],
                ],
                tr![
                    td![attrs!{At::Width => "200"},
                        "Base 16 (Hexadecimal):",
                    ],
                    td![
                        "7",
                    ],
                ],
            ],
        ],
        br![],
        br![],
        table![attrs!{At::Class => "text", At::Width => "100%"}, &table_style,
            tbody![
                tr![
                    td![attrs!{At::Width => "200"},
                        "Roman Numerals:",
                    ],
                    td![attrs!{At::Width => "40"},
                        "VII",
                    ],
                ],
                tr![
                    td![
                        "Egyptian Numerals:",
                    ],
                    td![
                        "𓐀",
                    ]
                ],
                tr![
                    td![
                        "Chinese Numerals:",
                    ],
                    td![style!{"vertical-align" => "middle"; "background-color" => "#FFF"},
                        "柒",
                    ]
                ],
                tr![
                    td![
                        "Babylonian Numerals:",
                    ],
                    td![style!{"vertical-align" => "middle"; "background-color" => "#FFF"},
                        img![attrs!{At::Src => "https://static.bigprimes.net/imgs/babnumbers/bab_7.gif", At::Alt => "7"}],
                    ]
                ],
            ],
        ],
    ]
}

pub fn render(slug:String) -> seed::dom_types::Node<Msg> {
    let rgx = Regex::new(r"^([1-9]+[0-9]*)$").unwrap();

    match rgx.is_match(&slug) {
        true => html_crunched_number(slug),
        _ => html_form()
    }
}

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

    #[test]
    fn numerics_to_text_test() {
        assert_eq!(numerics_to_text::convert("170".to_string()), "one hundred seventy");
        assert_eq!(numerics_to_text::convert("90001".to_string()), "ninety thousand one");
        assert_eq!(numerics_to_text::convert("1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001000".to_string()), "one noventrigintillion one octotrigintillion one septentrigintillion one sestrigintillion one quinquatrigintillion one quattuortrigintillion one trestrigintillion one duotrigintillion one untrigintillion one trigintillion one novemvigintillion one octovigintillion one septemvigintillion one sesvigintillion one quinquavigintillion one quattuorvigintillion one tresvigintillion one duovigintillion one unvigintillion one vigintillion one novemdecillion one octodecillion one septendecillion one sexdecillion one quindecillion one quattuordecillion one tredecillion one duodecillion one undecillion one decillion one nonillion one octillion one septillion one sextillion one quintillion one quadrillion one trillion one billion one million one thousand");
    }
}<|endoftext|>