<commit_before>use event::{Event, Rule, State};
use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

fn isnt_newline(c: u8) -> bool {
    !is_newline(c)
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    fn start_rule(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            return None
        }

        let c = self.bytes[self.offset];
        if c == b'}' {
            self.offset += 1;
            return Some(self.end())
        }
        if c == b'$' {
            return Some(self.next_variable())
        }

        let d = self.bytes[self.offset + 1];
        if c == b'/' && d == b'*' {
            return Some(self.next_comment())
        }

        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = match self.stack.pop() {
            Some(r) => r,
            None => {
                println!("Unexpected empty stack!");
                return Event::End(Rule::SassRule)
            },
        };
        self.state = State::StartRule;
        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let mut i = self.offset;
        let limit = self.sass.len();

        while i < limit {
            let c = self.bytes[i];
            if is_ascii_whitespace(c) {
                i += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
            } else if c == b'/' && i + 1 < limit && self.bytes[i + 1] == b'/' {
                i += self.scan_while(&self.sass[i..self.sass.len()], isnt_newline);
            } else {
                self.offset = i;
                return
            }
        }
        self.offset = limit;
    }

    fn next_comment(&mut self) -> Event<'a> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2]))
            } else {
                i += 1;
            }
        }
        unreachable!()
    }

    fn next_variable(&mut self) -> Event<'a> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Variable(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )
            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            return self.next_comment()
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InSelectors;
                self.stack.push(Rule::SassRule);
                return Event::Start(Rule::SassRule)
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_selector(&mut self) -> Event<'a> {
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}
<commit_msg>Put state back in properties if we're still in a rule<commit_after>use event::{Event, Rule, State};
use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

fn isnt_newline(c: u8) -> bool {
    !is_newline(c)
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    fn start_rule(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            return None
        }

        let c = self.bytes[self.offset];
        if c == b'}' {
            self.offset += 1;
            return Some(self.end())
        }
        if c == b'$' {
            return Some(self.next_variable())
        }

        let d = self.bytes[self.offset + 1];
        if c == b'/' && d == b'*' {
            return Some(self.next_comment())
        }

        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = match self.stack.pop() {
            Some(r) => r,
            None => {
                println!("Unexpected empty stack!");
                return Event::End(Rule::SassRule)
            },
        };

        if self.stack.len() == 0 {
            self.state = State::StartRule;
        } else {
            self.state = State::InProperties;
        }

        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let mut i = self.offset;
        let limit = self.sass.len();

        while i < limit {
            let c = self.bytes[i];
            if is_ascii_whitespace(c) {
                i += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
            } else if c == b'/' && i + 1 < limit && self.bytes[i + 1] == b'/' {
                i += self.scan_while(&self.sass[i..self.sass.len()], isnt_newline);
            } else {
                self.offset = i;
                return
            }
        }
        self.offset = limit;
    }

    fn next_comment(&mut self) -> Event<'a> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2]))
            } else {
                i += 1;
            }
        }
        unreachable!()
    }

    fn next_variable(&mut self) -> Event<'a> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Variable(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )
            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            return self.next_comment()
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InSelectors;
                self.stack.push(Rule::SassRule);
                return Event::Start(Rule::SassRule)
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_selector(&mut self) -> Event<'a> {
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! Request boundary validator

use std::mem;

pub fn extract_requests(buf: &[u8]) -> (Vec<String>, usize) {
    let utf8 = match String::from_utf8(buf.to_vec()) {
        Ok(val) => val,
        Err(_) => { return (Vec::new(), 0) }
    };

    let mut str_buf = String::new();
    let mut depth = 0;
    let mut res = Vec::new();
    let mut last_req = 0;
    let mut in_str = false;
    let mut is_escaped = false;

    for (idx, char) in utf8.char_indices() {
        str_buf.push(char);

        if (char == '{' || char == '[') && !in_str {
            depth += 1;
        }
        else if (char == '}' || char == ']') && !in_str {
            depth -= 1;
        }
        else if char == '"' && !is_escaped {
            in_str = !in_str;
        }
        else if char == '\\' && is_escaped && !in_str {
            is_escaped = !is_escaped;
        }

        if depth == 0 && str_buf.len() > 0 {
            res.push(mem::replace(&mut str_buf, String::new()));
            last_req = idx;
        }
    }

    (res, last_req)
}

#[test]
fn can_extract_request() {
    let buf = b"{ \"val\" : 1 } ffuuu";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"val\" : 1 }");
}

#[test]
fn can_extract_requests() {
    let buf = b"{ \"val\" : 1 }{ \"val2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"val\" : 1 }");
    assert_eq!(res.0[1], "{ \"val2\" : 2 }");
}

#[test]
fn can_extract_requests_with_slash() {
    let buf = b"{ \"va\\l\" : 1 }{ \"va\\l2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"va\\l\" : 1 }");
    assert_eq!(res.0[1], "{ \"va\\l2\" : 2 }");
}

#[test]
fn can_extract_requests_with_brackets() {
    let buf = b"[{ \"val_s1\" : 10 }{ \"val_s2\" : 20 }]";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "[{ \"val_s1\" : 10 }{ \"val_s2\" : 20 }]");
}

#[test]
fn can_extract_requests_with_braces() {
    let buf = b"{ \"va{l\" : 1 }{ \"va}l2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"va{l\" : 1 }");
    assert_eq!(res.0[1], "{ \"va}l2\" : 2 }");
}

#[test]
fn can_extract_vitro1() {
    let buf = b"[{\"jsonrpc\":\"2.0\",\"id\":\"3a3472c0-c7be-4070-a05c-8042c0a94892\",\"method\":\"eth_accounts\",\"params\":[]}][{\"jsonrpc\":\"2.0\",\"id\":\"a7329aff-888e-4aa7-a925-651c9545f356\",\"method\":\"net_peerCount\",\"params\":[]}]";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "[{\"jsonrpc\":\"2.0\",\"id\":\"3a3472c0-c7be-4070-a05c-8042c0a94892\",\"method\":\"eth_accounts\",\"params\":[]}]");
    assert_eq!(res.0[1], "[{\"jsonrpc\":\"2.0\",\"id\":\"a7329aff-888e-4aa7-a925-651c9545f356\",\"method\":\"net_peerCount\",\"params\":[]}]");
}<commit_msg>skipping empty requests<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! Request boundary validator

use std::mem;

pub fn extract_requests(buf: &[u8]) -> (Vec<String>, usize) {
    let utf8 = match String::from_utf8(buf.to_vec()) {
        Ok(val) => val,
        Err(_) => { return (Vec::new(), 0) }
    };

    let mut str_buf = String::new();
    let mut depth = 0;
    let mut res = Vec::new();
    let mut last_req = 0;
    let mut in_str = false;
    let mut is_escaped = false;
    let mut ever_started = false;

    for (idx, char) in utf8.char_indices() {
        str_buf.push(char);

        if (char == '{' || char == '[') && !in_str {
            if depth == 0 {
                ever_started = true;
            }
            depth += 1;
        }
        else if (char == '}' || char == ']') && !in_str {
            depth -= 1;
        }
        else if char == '"' && !is_escaped {
            in_str = !in_str;
        }
        else if char == '\\' && is_escaped && !in_str {
            is_escaped = !is_escaped;
        }

        if depth == 0 && str_buf.len() > 0 {
            if ever_started {
                res.push(mem::replace(&mut str_buf, String::new()));
            }
            ever_started = false;
            last_req = idx;
        }
    }

    (res, last_req)
}

#[test]
fn can_extract_request() {
    let buf = b"{ \"val\" : 1 } ffuuu";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"val\" : 1 }");
}

#[test]
fn can_extract_requests() {
    let buf = b"{ \"val\" : 1 }{ \"val2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"val\" : 1 }");
    assert_eq!(res.0[1], "{ \"val2\" : 2 }");
}

#[test]
fn can_extract_requests_with_slash() {
    let buf = b"{ \"va\\l\" : 1 }{ \"va\\l2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"va\\l\" : 1 }");
    assert_eq!(res.0[1], "{ \"va\\l2\" : 2 }");
}

#[test]
fn can_extract_requests_with_brackets() {
    let buf = b"[{ \"val_s1\" : 10 }{ \"val_s2\" : 20 }]";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "[{ \"val_s1\" : 10 }{ \"val_s2\" : 20 }]");
}

#[test]
fn can_extract_requests_with_braces() {
    let buf = b"{ \"va{l\" : 1 }{ \"va}l2\" : 2 }";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "{ \"va{l\" : 1 }");
    assert_eq!(res.0[1], "{ \"va}l2\" : 2 }");
}

#[test]
fn can_extract_vitro1() {
    let buf = b"[{\"jsonrpc\":\"2.0\",\"id\":\"3a3472c0-c7be-4070-a05c-8042c0a94892\",\"method\":\"eth_accounts\",\"params\":[]}][{\"jsonrpc\":\"2.0\",\"id\":\"a7329aff-888e-4aa7-a925-651c9545f356\",\"method\":\"net_peerCount\",\"params\":[]}]";
    let res = extract_requests(buf);
    assert_eq!(res.0[0], "[{\"jsonrpc\":\"2.0\",\"id\":\"3a3472c0-c7be-4070-a05c-8042c0a94892\",\"method\":\"eth_accounts\",\"params\":[]}]");
    assert_eq!(res.0[1], "[{\"jsonrpc\":\"2.0\",\"id\":\"a7329aff-888e-4aa7-a925-651c9545f356\",\"method\":\"net_peerCount\",\"params\":[]}]");
}<|endoftext|>


<commit_before>use byteorder::Error as ByteOrderError;
use image::ImageError;
use name::WadName;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter};
use std::fmt::Result as FmtResult;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::result::Result as StdResult;
use toml::DecodeError as TomlDecodeError;
use toml::ParserError as TomlParserError;

pub type Result<T> = StdResult<T, Error>;

#[derive(Debug)]
pub struct Error {
    file: Option<PathBuf>,
    kind: ErrorKind,
}

impl StdError for Error {
    fn description(&self) -> &str {
        self.kind.description()
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        match self.file {
            Some(ref path) => write!(fmt, "in '{}': {}", path.to_string_lossy(), self.kind),
            None => write!(fmt, "{}", self.kind),
        }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    Io(IoError),
    ByteOrder(ByteOrderError),
    BadWadHeader,
    BadWadName(Vec<u8>),
    MissingRequiredLump(String),
    // MissingRequiredPatch(WadName, WadName),
    BadMetadataSchema(TomlDecodeError),
    BadMetadataSyntax(Vec<TomlParserError>),
    BadImage(WadName, ImageError),
}

impl ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref inner) => inner.description(),
            ErrorKind::ByteOrder(ref inner) => inner.description(),
            ErrorKind::BadWadHeader(..) => "invalid header",
            ErrorKind::BadWadName(..) => "invalid wad name",
            ErrorKind::MissingRequiredLump(..) => "missing required lump",
            // ErrorKind::MissingRequiredPatch(..) => "missing required patch",
            ErrorKind::BadMetadataSchema(..) => "invalid data in metadata",
            ErrorKind::BadMetadataSyntax(..) => "TOML syntax error in metadata",
            ErrorKind::BadImage(..) => "Bad image",
        }
    }
}

impl Display for ErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        let desc = self.description();
        match *self {
            ErrorKind::Io(ref inner) => write!(fmt, "{}", inner),
            ErrorKind::ByteOrder(ref inner) => write!(fmt, "{}", inner),
            ErrorKind::BadWadHeader => write!(fmt, "{}", desc),
            ErrorKind::BadWadName(ref name) => write!(fmt, "{} ({:?})", desc, name),
            ErrorKind::MissingRequiredLump(ref name) => {
                write!(fmt, "{} ({})", desc, name)
            }
            // ErrorKind::MissingRequiredPatch(ref patch, ref texture) => {
            //    write!(fmt, "{} ({}, required by {})", desc, patch, texture)
            // },
            ErrorKind::BadMetadataSchema(ref err) => {
                write!(fmt, "{}: {}", desc, err)
            }
            ErrorKind::BadMetadataSyntax(ref errors) => {
                write!(fmt, "{}: {:?}", desc, errors)
            }
            ErrorKind::BadImage(ref name, ref inner) => {
                write!(fmt, "{}: in {}: {}", desc, name, inner)
            }
        }
    }
}

impl From<IoError> for Error {
    fn from(cause: IoError) -> Error {
        ErrorKind::Io(cause).into()
    }
}

impl From<ByteOrderError> for Error {
    fn from(cause: ByteOrderError) -> Error {
        ErrorKind::ByteOrder(cause).into()
    }
}

impl From<TomlDecodeError> for Error {
    fn from(cause: TomlDecodeError) -> Error {
        ErrorKind::BadMetadataSchema(cause).into()
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        Error {
            kind: kind,
            file: None,
        }
    }
}

pub trait InFile {
    type Output;
    fn in_file(self, file: &Path) -> Self::Output;
}

impl InFile for Error {
    type Output = Error;
    fn in_file(self, file: &Path) -> Error {
        Error {
            file: Some(file.to_owned()),
            kind: self.kind,
        }
    }
}

impl InFile for ErrorKind {
    type Output = Error;
    fn in_file(self, file: &Path) -> Error {
        Error {
            file: Some(file.to_owned()),
            kind: self,
        }
    }
}

impl<S, E: Into<Error>> InFile for StdResult<S, E> {
    type Output = Result<S>;
    fn in_file(self, file: &Path) -> Result<S> {
        self.map_err(|e| e.into().in_file(file))
    }
}
<commit_msg>fix unit variant pattern match warning<commit_after>use byteorder::Error as ByteOrderError;
use image::ImageError;
use name::WadName;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter};
use std::fmt::Result as FmtResult;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::result::Result as StdResult;
use toml::DecodeError as TomlDecodeError;
use toml::ParserError as TomlParserError;

pub type Result<T> = StdResult<T, Error>;

#[derive(Debug)]
pub struct Error {
    file: Option<PathBuf>,
    kind: ErrorKind,
}

impl StdError for Error {
    fn description(&self) -> &str {
        self.kind.description()
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        match self.file {
            Some(ref path) => write!(fmt, "in '{}': {}", path.to_string_lossy(), self.kind),
            None => write!(fmt, "{}", self.kind),
        }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    Io(IoError),
    ByteOrder(ByteOrderError),
    BadWadHeader,
    BadWadName(Vec<u8>),
    MissingRequiredLump(String),
    // MissingRequiredPatch(WadName, WadName),
    BadMetadataSchema(TomlDecodeError),
    BadMetadataSyntax(Vec<TomlParserError>),
    BadImage(WadName, ImageError),
}

impl ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref inner) => inner.description(),
            ErrorKind::ByteOrder(ref inner) => inner.description(),
            ErrorKind::BadWadHeader => "invalid header",
            ErrorKind::BadWadName(..) => "invalid wad name",
            ErrorKind::MissingRequiredLump(..) => "missing required lump",
            // ErrorKind::MissingRequiredPatch(..) => "missing required patch",
            ErrorKind::BadMetadataSchema(..) => "invalid data in metadata",
            ErrorKind::BadMetadataSyntax(..) => "TOML syntax error in metadata",
            ErrorKind::BadImage(..) => "Bad image",
        }
    }
}

impl Display for ErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        let desc = self.description();
        match *self {
            ErrorKind::Io(ref inner) => write!(fmt, "{}", inner),
            ErrorKind::ByteOrder(ref inner) => write!(fmt, "{}", inner),
            ErrorKind::BadWadHeader => write!(fmt, "{}", desc),
            ErrorKind::BadWadName(ref name) => write!(fmt, "{} ({:?})", desc, name),
            ErrorKind::MissingRequiredLump(ref name) => write!(fmt, "{} ({})", desc, name),
            // ErrorKind::MissingRequiredPatch(ref patch, ref texture) => {
            //    write!(fmt, "{} ({}, required by {})", desc, patch, texture)
            // },
            ErrorKind::BadMetadataSchema(ref err) => write!(fmt, "{}: {}", desc, err),
            ErrorKind::BadMetadataSyntax(ref errors) => write!(fmt, "{}: {:?}", desc, errors),
            ErrorKind::BadImage(ref name, ref inner) => {
                write!(fmt, "{}: in {}: {}", desc, name, inner)
            }
        }
    }
}

impl From<IoError> for Error {
    fn from(cause: IoError) -> Error {
        ErrorKind::Io(cause).into()
    }
}

impl From<ByteOrderError> for Error {
    fn from(cause: ByteOrderError) -> Error {
        ErrorKind::ByteOrder(cause).into()
    }
}

impl From<TomlDecodeError> for Error {
    fn from(cause: TomlDecodeError) -> Error {
        ErrorKind::BadMetadataSchema(cause).into()
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        Error {
            kind: kind,
            file: None,
        }
    }
}

pub trait InFile {
    type Output;
    fn in_file(self, file: &Path) -> Self::Output;
}

impl InFile for Error {
    type Output = Error;
    fn in_file(self, file: &Path) -> Error {
        Error {
            file: Some(file.to_owned()),
            kind: self.kind,
        }
    }
}

impl InFile for ErrorKind {
    type Output = Error;
    fn in_file(self, file: &Path) -> Error {
        Error {
            file: Some(file.to_owned()),
            kind: self,
        }
    }
}

impl<S, E: Into<Error>> InFile for StdResult<S, E> {
    type Output = Result<S>;
    fn in_file(self, file: &Path) -> Result<S> {
        self.map_err(|e| e.into().in_file(file))
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Array, Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a multipart form.
    #[inline]
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(bytes.as_ref()),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let body_array = Array::new();
                body_array.push(&body_uint8_array);
                let js_value: &JsValue = body_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}
<commit_msg>Fix body to `JsValue` conversion (#1354)<commit_after>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Array, Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a multipart form.
    #[inline]
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(bytes.as_ref()),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let body_array = Array::from(&body_uint8_array);
                let js_value: &JsValue = body_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}

#[cfg(test)]
mod tests {
    use js_sys::{Array, Uint8Array};
    use wasm_bindgen::{prelude::*, JsValue};
    use wasm_bindgen_test::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen]
    extern "C" {
        // Use `js_namespace` here to bind `console.log(..)` instead of just
        // `log(..)`
        #[wasm_bindgen(js_namespace = console)]
        fn log(s: String);
    }

    #[wasm_bindgen_test]
    async fn test_body() {
        use crate::Body;

        let body = Body::from("TEST");
        assert_eq!([84, 69, 83, 84], body.as_bytes().unwrap());
    }

    #[wasm_bindgen_test]
    async fn test_body_js() {
        use crate::Body;

        let body = Body::from("TEST");

        let arr = [84u8, 69, 83, 84];
        let u8_arr: Uint8Array = arr.as_ref().into();
        let expected = JsValue::from(Array::from(&u8_arr));

        // ty JS -.-
        assert_eq!(
            format!("{:#?}", expected),
            format!(
                "{:#?}",
                body.to_js_value()
                    .expect("could not convert body to JsValue")
            )
        );
    }
}
<|endoftext|>


<commit_before>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

/*===============================================================================================*/
/*------UTIL STRUCT------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// The Math utility struct
///
/// It contains various utility functions such as: Clamp, Lerp, Min, Max, etc.
#[derive (Copy, Clone)]
pub struct Util;

/*===============================================================================================*/
/*------UTIL PUBLIC STATIC METHODS---------------------------------------------------------------*/
/*===============================================================================================*/

impl Util {

    /// Clamps a value between two numbers.
    ///
    /// # Arguments
    /// * `value` - The value to clamp
    /// * `min` - The minimum the value is allowed to be
    /// * `max` - The maximum the value is allowed to be
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let val = 23.0;
    /// let min = 5.0;
    /// let max = 19.0;
    ///
    /// println! ("Clamp = {}", Util::clamp (val, min, max));
    /// ```
    /// ```c
    /// Output : Clamp = 19.0
    pub fn clamp (value: f32, min: f32, max: f32) -> f32 {

        if value < min {
            return min;
        }

        else if value > max {
            return max;
        }

        value
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Converts a number from degrees to radians.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let deg = 95.0;
    /// println! ("Value as radians = {}", Util::deg2rad (deg));
    /// ```
    /// ```c
    /// Output : Value as radians = 1.658035
    pub fn deg2rad (value: f32) -> f32 {

        value * 0.017453
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Linearly interpolates between two numbers.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let start = 9.0;
    /// let end = 22.0;
    /// let percent = 0.5;
    ///
    /// println! ("{}", Util::lerp (start, end, percent));
    /// ```
    /// ```c
    /// Output : 15.5
    pub fn lerp (start: f32, end: f32, percentage: f32) -> f32 {

        start + (end - start) * Util::clamp (percentage, 0.0, 1.0)
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Linearly interpolates between two numbers without clamping.
    pub fn lerp_unclamped (start: f32, end: f32, percentage: f32) -> f32 {

        start + (end - start) * percentage
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns the largest of two numbers
    ///
    /// # Arguments
    /// * `lhs` - The first value to compare, or left hand side value
    /// * `rhs` - The second value to compare, or right hand side value
    pub fn max (lhs: f32, rhs: f32) -> f32 {

        if lhs > rhs {
            return lhs
        }

        rhs
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns the smallest of two numbers
    ///
    /// # Arguments
    /// * `lhs` - The first value to compare, or left hand side value
    /// * `rhs` - The second value to compare, or right hand side value
    pub fn min (lhs: f32, rhs: f32) -> f32 {

        if lhs < rhs {
            return lhs;
        }

        rhs
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Converts a number from radians to degrees
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let rad = 2.5;
    /// println! ("Value as degrees = {}", Util::rad2deg (rad));
    /// ```
    /// ```c
    /// Output : Value as degrees = 143.2394475
    pub fn rad2deg (value: f32) -> f32 {

        value * 57.295779
    }
}
<commit_msg>Added "cot" method.<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

/*===============================================================================================*/
/*------UTIL STRUCT------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// The Math utility struct
///
/// It contains various utility functions such as: Clamp, Lerp, Min, Max, etc.
#[derive (Copy, Clone)]
pub struct Util;

/*===============================================================================================*/
/*------UTIL PUBLIC STATIC METHODS---------------------------------------------------------------*/
/*===============================================================================================*/

impl Util {

    /// Clamps a value between two numbers.
    ///
    /// # Arguments
    /// * `value` - The value to clamp
    /// * `min` - The minimum the value is allowed to be
    /// * `max` - The maximum the value is allowed to be
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let val = 23.0;
    /// let min = 5.0;
    /// let max = 19.0;
    ///
    /// println! ("Clamp = {}", Util::clamp (val, min, max));
    /// ```
    /// ```c
    /// Output : Clamp = 19.0
    pub fn clamp (value: f32, min: f32, max: f32) -> f32 {

        if value < min {
            return min;
        }

        else if value > max {
            return max;
        }

        value
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Calculates the cotangent of a value.
    pub fn cot (value: f32) -> f32 {
        1.0 / value.tan ()
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Converts a number from degrees to radians.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let deg = 95.0;
    /// println! ("Value as radians = {}", Util::deg2rad (deg));
    /// ```
    /// ```c
    /// Output : Value as radians = 1.658035
    pub fn deg2rad (value: f32) -> f32 {

        value * 0.017453
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Linearly interpolates between two numbers.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let start = 9.0;
    /// let end = 22.0;
    /// let percent = 0.5;
    ///
    /// println! ("{}", Util::lerp (start, end, percent));
    /// ```
    /// ```c
    /// Output : 15.5
    pub fn lerp (start: f32, end: f32, percentage: f32) -> f32 {

        start + (end - start) * Util::clamp (percentage, 0.0, 1.0)
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Linearly interpolates between two numbers without clamping.
    pub fn lerp_unclamped (start: f32, end: f32, percentage: f32) -> f32 {

        start + (end - start) * percentage
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns the largest of two numbers
    ///
    /// # Arguments
    /// * `lhs` - The first value to compare, or left hand side value
    /// * `rhs` - The second value to compare, or right hand side value
    pub fn max (lhs: f32, rhs: f32) -> f32 {

        if lhs > rhs {
            return lhs
        }

        rhs
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns the smallest of two numbers
    ///
    /// # Arguments
    /// * `lhs` - The first value to compare, or left hand side value
    /// * `rhs` - The second value to compare, or right hand side value
    pub fn min (lhs: f32, rhs: f32) -> f32 {

        if lhs < rhs {
            return lhs;
        }

        rhs
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Converts a number from radians to degrees
    ///
    /// # Examples
    /// ```
    /// # use ion_core::util::math::Util;
    /// #
    /// let rad = 2.5;
    /// println! ("Value as degrees = {}", Util::rad2deg (rad));
    /// ```
    /// ```c
    /// Output : Value as degrees = 143.2394475
    pub fn rad2deg (value: f32) -> f32 {

        value * 57.295779
    }
}
<|endoftext|>


<commit_before>use core::ptr::*;
use core::cell::RefCell;

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = p.wrapping_offset(1);
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = mp.wrapping_offset(1);
    assert!(!mq.is_null());

    // Pointers to unsized types -- slices
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    let ncs: *const [u8] = null::<[u8; 3]>();
    assert!(ncs.is_null());

    let nms: *mut [u8] = null_mut::<[u8; 3]>();
    assert!(nms.is_null());

    // Pointers to unsized types -- trait objects
    let ci: *const dyn ToString = &3;
    assert!(!ci.is_null());

    let mi: *mut dyn ToString = &mut 3;
    assert!(!mi.is_null());

    let nci: *const dyn ToString = null::<isize>();
    assert!(nci.is_null());

    let nmi: *mut dyn ToString = null_mut::<isize>();
    assert!(nmi.is_null());
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = null::<[u8; 3]>();
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_ref(), None);

        // Pointers to unsized types -- trait objects
        let ci: *const dyn ToString = &3;
        assert!(ci.as_ref().is_some());

        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_ref().is_some());

        let nci: *const dyn ToString = null::<isize>();
        assert!(nci.as_ref().is_none());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_ref().is_none());
    }
}

#[test]
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut().unwrap() as *mut _, s as *mut _);

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_mut(), None);

        // Pointers to unsized types -- trait objects
        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_mut().is_some());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_mut().is_none());
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        loop {
            *m_ptr += *m_ptr;
            if m_ptr == m_start {
                break;
            }
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_nonnull() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}

#[test]
#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_zst() {
    // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
    // all, because no amount of elements will align the pointer.
    let mut p = 1;
    while p < 1024 {
        assert_eq!((p as *const ()).align_offset(p), 0);
        if p != 1 {
            assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
        }
        p = (p + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_stride1() {
    // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
    // number of bytes.
    let mut align = 1;
    while align < 1024 {
        for ptr in 1..2*align {
            let expected = ptr % align;
            let offset = if expected == 0 { 0 } else { align - expected };
            assert_eq!((ptr as *const u8).align_offset(align), offset,
            "ptr = {}, align = {}, size = 1", ptr, align);
        }
        align = (align + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri is too slow
fn align_offset_weird_strides() {
    #[repr(packed)]
    struct A3(u16, u8);
    struct A4(u32);
    #[repr(packed)]
    struct A5(u32, u8);
    #[repr(packed)]
    struct A6(u32, u16);
    #[repr(packed)]
    struct A7(u32, u16, u8);
    #[repr(packed)]
    struct A8(u32, u32);
    #[repr(packed)]
    struct A9(u32, u32, u8);
    #[repr(packed)]
    struct A10(u32, u32, u16);

    unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
        let numptr = ptr as usize;
        let mut expected = usize::max_value();
        // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
        for el in 0..align {
            if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
                expected = el;
                break;
            }
        }
        let got = ptr.align_offset(align);
        if got != expected {
            eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
                      ::std::mem::size_of::<T>(), align, expected, got);
            return true;
        }
        return false;
    }

    // For pointers of stride != 1, we verify the algorithm against the naivest possible
    // implementation
    let mut align = 1;
    let mut x = false;
    while align < 1024 {
        for ptr in 1usize..4*align {
            unsafe {
                x |= test_weird_stride::<A3>(ptr as *const A3, align);
                x |= test_weird_stride::<A4>(ptr as *const A4, align);
                x |= test_weird_stride::<A5>(ptr as *const A5, align);
                x |= test_weird_stride::<A6>(ptr as *const A6, align);
                x |= test_weird_stride::<A7>(ptr as *const A7, align);
                x |= test_weird_stride::<A8>(ptr as *const A8, align);
                x |= test_weird_stride::<A9>(ptr as *const A9, align);
                x |= test_weird_stride::<A10>(ptr as *const A10, align);
            }
        }
        align = (align + 1).next_power_of_two();
    }
    assert!(!x);
}
<commit_msg>Test content, not value<commit_after>use core::ptr::*;
use core::cell::RefCell;

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = p.wrapping_offset(1);
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = mp.wrapping_offset(1);
    assert!(!mq.is_null());

    // Pointers to unsized types -- slices
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    let ncs: *const [u8] = null::<[u8; 3]>();
    assert!(ncs.is_null());

    let nms: *mut [u8] = null_mut::<[u8; 3]>();
    assert!(nms.is_null());

    // Pointers to unsized types -- trait objects
    let ci: *const dyn ToString = &3;
    assert!(!ci.is_null());

    let mi: *mut dyn ToString = &mut 3;
    assert!(!mi.is_null());

    let nci: *const dyn ToString = null::<isize>();
    assert!(nci.is_null());

    let nmi: *mut dyn ToString = null_mut::<isize>();
    assert!(nmi.is_null());
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = null::<[u8; 3]>();
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_ref(), None);

        // Pointers to unsized types -- trait objects
        let ci: *const dyn ToString = &3;
        assert!(ci.as_ref().is_some());

        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_ref().is_some());

        let nci: *const dyn ToString = null::<isize>();
        assert!(nci.as_ref().is_none());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_ref().is_none());
    }
}

#[test]
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut(), Some(&mut [1, 2, 3]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_mut(), None);

        // Pointers to unsized types -- trait objects
        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_mut().is_some());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_mut().is_none());
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        loop {
            *m_ptr += *m_ptr;
            if m_ptr == m_start {
                break;
            }
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_nonnull() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}

#[test]
#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_zst() {
    // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
    // all, because no amount of elements will align the pointer.
    let mut p = 1;
    while p < 1024 {
        assert_eq!((p as *const ()).align_offset(p), 0);
        if p != 1 {
            assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
        }
        p = (p + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_stride1() {
    // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
    // number of bytes.
    let mut align = 1;
    while align < 1024 {
        for ptr in 1..2*align {
            let expected = ptr % align;
            let offset = if expected == 0 { 0 } else { align - expected };
            assert_eq!((ptr as *const u8).align_offset(align), offset,
            "ptr = {}, align = {}, size = 1", ptr, align);
        }
        align = (align + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri is too slow
fn align_offset_weird_strides() {
    #[repr(packed)]
    struct A3(u16, u8);
    struct A4(u32);
    #[repr(packed)]
    struct A5(u32, u8);
    #[repr(packed)]
    struct A6(u32, u16);
    #[repr(packed)]
    struct A7(u32, u16, u8);
    #[repr(packed)]
    struct A8(u32, u32);
    #[repr(packed)]
    struct A9(u32, u32, u8);
    #[repr(packed)]
    struct A10(u32, u32, u16);

    unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
        let numptr = ptr as usize;
        let mut expected = usize::max_value();
        // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
        for el in 0..align {
            if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
                expected = el;
                break;
            }
        }
        let got = ptr.align_offset(align);
        if got != expected {
            eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
                      ::std::mem::size_of::<T>(), align, expected, got);
            return true;
        }
        return false;
    }

    // For pointers of stride != 1, we verify the algorithm against the naivest possible
    // implementation
    let mut align = 1;
    let mut x = false;
    while align < 1024 {
        for ptr in 1usize..4*align {
            unsafe {
                x |= test_weird_stride::<A3>(ptr as *const A3, align);
                x |= test_weird_stride::<A4>(ptr as *const A4, align);
                x |= test_weird_stride::<A5>(ptr as *const A5, align);
                x |= test_weird_stride::<A6>(ptr as *const A6, align);
                x |= test_weird_stride::<A7>(ptr as *const A7, align);
                x |= test_weird_stride::<A8>(ptr as *const A8, align);
                x |= test_weird_stride::<A9>(ptr as *const A9, align);
                x |= test_weird_stride::<A10>(ptr as *const A10, align);
            }
        }
        align = (align + 1).next_power_of_two();
    }
    assert!(!x);
}
<|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.

use core::ptr::*;
use core::slice;
use core::cell::RefCell;

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = unsafe { p.offset(1) };
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = unsafe { mp.offset(1) };
    assert!(!mq.is_null());

    // Pointers to unsized types
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    unsafe {
        let ncs: *const [u8] = slice::from_raw_parts(null(), 0);
        assert!(ncs.is_null());

        let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0);
        assert!(nms.is_null());
    }
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = slice::from_raw_parts(null(), 0);
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0);
        assert_eq!(nms.as_ref(), None);
    }
}

#[test]
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut(), Some(s));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = slice::from_raw_parts_mut(null_mut(), 0);
        assert_eq!(nms.as_mut(), None);
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        while m_ptr >= m_start {
            *m_ptr += *m_ptr;
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_unique() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}
<commit_msg>Avoid the UB of a null reference to a slice<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.

use core::mem;
use core::ptr::*;
use core::cell::RefCell;

/// Create a null pointer to a mutable slice.  This is implemented like
/// `slice::from_raw_parts_mut`, which we can't use directly because
/// having a null `&mut [T]` even temporarily is UB.
fn null_slice<T>() -> *mut [T] {
    unsafe {
        #[repr(C)]
        struct Repr<T> {
            pub data: *mut T,
            pub len: usize,
        }

        mem::transmute(Repr { data: null_mut::<T>(), len: 0 })
    }
}

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = unsafe { p.offset(1) };
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = unsafe { mp.offset(1) };
    assert!(!mq.is_null());

    // Pointers to unsized types
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    let ncs: *const [u8] = null_slice();
    assert!(ncs.is_null());

    let nms: *mut [u8] = null_slice();
    assert!(nms.is_null());
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = null_slice();
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = null_slice();
        assert_eq!(nms.as_ref(), None);
    }
}

#[test]
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut(), Some(s));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = null_slice();
        assert_eq!(nms.as_mut(), None);
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        while m_ptr >= m_start {
            *m_ptr += *m_ptr;
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_unique() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}
<|endoftext|>