<commit_before>extern crate rand;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::cmp::{Ord, Ordering};
use std::fmt;
extern crate crossterm;
use crate::Render;
use crossterm::{cursor, terminal};

// comands in config-file start with
pub const CONF_LINE_IDENTIFIER__CONTROL: char = ':';

// the default can be changed by one of the following switches
const DEFAULT_REWARDING_SCHEME: RewardingScheme = RewardingScheme::UnhideWhenGuessedChar;

// Keyword to switch rewarding scheme
// :traditional-rewarding
const UNHIDE_WHEN_LOST_LIVE_IDENTIFIER: &str = "traditional-rewarding";

// Keyword to switch rewarding scheme
// :success-rewarding
const UNHIDE_WHEN_GUESSED_CHAR_IDENTIFIER: &str = "success-rewarding";

// images in config file start with
pub const CONF_LINE_IDENTIFIER__IMAGE: char = '|';

const BIG_IMAGE: usize = 100; // sort algorithm <-> random algorithm

// first char of image lines must be '|'
const DEFAULT_IMAGES: &[&str] = &[
    "
|    ,,,,,
|   (o   o)
|    /. .\\
|   (_____)
|     : :
|    ##O##'
|  ,,,: :,,,
| _)\\ : : /(____
|{  \\     /  ___}
| \\/)     ((/
|  (_______)
|    :   :
|    :   :
|   / \\ / \\
|   \"\"\" \"\"\"
",
    "
|    |\\_|X|_/|
|   /         \\
| =(  O     O  )=
|  -\\    o    /-
|   / .-----. \\
| /_ | o   o |_ \\
|(U  |       |  U)
|   _|_     _|_
|  (   )---(   )
",
    "
|        _.---._    /\\\\
|     ./'       \"--`\\//
|   ./              o \\
|  /./\\  )______   \\__ \\
| ./  / /\\ \\   | \\ \\  \\ \\
|    / /  \\ \\  | |\\ \\  \\7
|     \"     \"    \"  \"        VK
",
    "
|       ,.
|      (_|,.
|     ,' /, )_______   _
|  __j o``-'        `.'-)'
| (\")                 \\'
|  `-j                |
|    `-._(           /
|       |_\\  |--^.  /
|      /_]'|_| /_)_/
|         /_]'  /_]'
# Author: hjw
",
    "
|        _
|       [ ]
|      (   )
|       |>|
|    __/===\\__
|   //| o=o |\\\\
| <]  | o=o |  [>
|     \\=====/
|    / / | \\ \\
|   <_________>
",
    "
|                          (_)(_)
|                          /     \\
|                         /       |
|                        /   \\  * |
|          ________     /    /\\__/
|  _      /        \\   /    /
| / \\    /  ____    \\_/    /
|//\\ \\  /  /    \\         /
|V  \\ \\/  /      \\       /
|    \\___/        \\_____/
",
    "
|         .-.
|        (. .)__,')
|        / V      )
|  ()    \\  (   \\/
|<)-`\\()  `._`._ \\
|  <).>=====<<==`'====
|   C-'`(>
# Author: hjw
",
    "
| >(. )
|  |  (     /)
|  |   \\___/ )
|  (   ----- )  >@)_//   >@)_//  >@)_//  >@)_//
|   \\_______/    (__)     (__)    (__)    (__)
|~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
",
    "
|           __
|           /(`o
|     ,-,  //  \\\\
|    (,,,) ||   V
|   (,,,,)\\//
|   (,,,/w)-'
|   \\,,/w)
|   `V/uu
|     / |
|     | |
|     o o
|     \\ |
|\\,/  ,\\|,.  \\,/
",
    "
|o
| \\_/\\o
|( Oo)                    \\|/
|(_=-)  .===O-  ~~Z~A~P~~ -O-
|/   \\_/U'                /|\\
|||  |_/
|\\\\  |
|{K ||
| | PP
| | ||
| (__\\\\
# Author: ac
",
    "
|      ______
|     /     /\\
|    /     /  \\
|   /_____/----\\_    (
|  \"     \"          ).
| _ ___          o (:') o
|(@))_))        o ~/~~\\~ o
|                o  o  o
",
    "
|                             _______     |\\
|                            |License|    | \\
|  _____                     | ~~*~~ |    |  \\
| |     |  (((        .--.   |_______|    |
| |DrJRO| ~OvO~ __   (////)               |
| |     | ( _ )|==|   \\__/                |
| |o    |  \\_/ |_(|  /    \\   _______     |
| |     | //|\\\\   \\\\//|  |\\\\  |__o__|     |
| |   __|//\\_/\\\\ __\\/ |__|//  |__o__|     |
| |  |==\"\"//=\\\\\"\"====|||||)   |__o__|     |
|_|__||_|_||_||_____||||||____|__o__|_____|
|    ||  (_) (_)    ||||||                \\
|    []             [(_)(_)
",
];

#[derive(PartialOrd, Eq, PartialEq, Debug, Copy, Clone)] //omitting Ord
pub struct ImChar {
    pub point: (u8, u8),
    pub code: char,
}

impl fmt::Display for ImChar {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.code)
    }
}

// Ord enables us to v.sort()
impl Ord for ImChar {
    fn cmp(&self, other: &Self) -> Ordering {
        fn weight(ic: &ImChar) -> isize {
            let &ImChar { point: (x, y), .. } = ic;
            // points near the lower left corner are light
            x as isize - y as isize
        }
        weight(&self).cmp(&weight(&other))
    }
}

#[derive(Debug, PartialEq)]
pub enum RewardingScheme {
    UnhideWhenLostLife,
    UnhideWhenGuessedChar,
}

#[derive(Debug)]
pub struct Image {
    pub ichars: Vec<ImChar>,
    pub offset: (usize, usize),
    pub dimension: (u8, u8),
    pub visible_points: usize,
    pub rewarding_scheme: RewardingScheme,
}

impl Render for Image {
    fn render(&self) {
        let cursor = cursor();
        let terminal = terminal();
        for ic in self.ichars.iter().take(self.visible_points) {
            let &ImChar {
                point: (x, y),
                code,
            } = ic;
            cursor
                .goto(
                    (self.offset.1 + (x as usize) + 1) as u16,
                    (self.offset.0 + (y as usize) + 1) as u16,
                )
                .expect("Can not set curson position.");
            terminal
                .write(&code.to_string())
                .expect("Can not write on terminal.");
        }
        // after printing the image s, bring the cursor below
        cursor
            .goto(0, (self.dimension.1 as usize + 1 + self.offset.1) as u16)
            .expect("Can not move cursor.");
    }
}

impl Image {
    pub fn new(string: &str, offset: (usize, usize)) -> Self {
        let mut v: Vec<ImChar> = Vec::new();

        let mut rewarding_scheme: RewardingScheme = DEFAULT_REWARDING_SCHEME;
        for (y, line) in string
            // split in lines
            .lines()
            // interpret identifier line
            .filter_map(|l| {
                if l.starts_with(CONF_LINE_IDENTIFIER__CONTROL) {
                    if l[1..].trim().contains(UNHIDE_WHEN_LOST_LIVE_IDENTIFIER) {
                        rewarding_scheme = RewardingScheme::UnhideWhenLostLife;
                    }
                    if l[1..].trim().contains(UNHIDE_WHEN_GUESSED_CHAR_IDENTIFIER) {
                        rewarding_scheme = RewardingScheme::UnhideWhenGuessedChar;
                    }
                    None
                } else {
                    Some(l)
                }
            })
            // consider only lines starting with '|'
            .filter(|&l| l.starts_with(CONF_LINE_IDENTIFIER__IMAGE))
            .enumerate()
        //.inspect(|&(n,l)| println!("line {:?}: {:?} ", n,l))
        {
            let mut ii: Vec<_> = line
                .char_indices()
                // skip first char '|'
                .skip(1)
                // consider only chars != ' '
                .filter(|&(_, c)| c != ' ')
                // save in ImageChar object
                .map(|(x, c)| ImChar {
                    point: (x as u8, y as u8),
                    code: c,
                })
                .collect();
            v.append(&mut ii);
        }

        // find dimensions
        let mut x_max = 0;
        let mut y_max = 0;
        for i in &v {
            let &ImChar { point: (x, y), .. } = i;
            if x > x_max {
                x_max = x
            };
            if y > y_max {
                y_max = y
            };
        }

        // order points
        let v_len = v.len();
        if v_len <= BIG_IMAGE {
            v.sort(); // Sort algorithm, see "impl Ord for ImageChar"
        } else {
            let mut rng = thread_rng();
            (&mut v).shuffle(&mut rng); // points appear randomly.
        }

        if v.is_empty() {
            let mut rng = thread_rng();
            Self::new((&DEFAULT_IMAGES).choose(&mut rng).unwrap(), offset)
        } else {
            Self {
                ichars: v,
                offset,
                dimension: (x_max, y_max),
                visible_points: v_len,
                rewarding_scheme,
            }
        }
    }

    pub fn disclose(&mut self, lives_frac: (usize, usize), guessed_chars_frac: (usize, usize)) {
        let l = self.ichars.len();

        let as_points = |(n, d)| (3 * l * (d - n) as usize / d as usize + l) / 4;

        self.visible_points = match self.rewarding_scheme {
            RewardingScheme::UnhideWhenGuessedChar => as_points(guessed_chars_frac),
            RewardingScheme::UnhideWhenLostLife => as_points(lives_frac),
        };
    }
}
<commit_msg>use print! consistently throughout the application<commit_after>extern crate rand;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::cmp::{Ord, Ordering};
use std::fmt;
extern crate crossterm;
use crate::Render;
use crossterm::cursor;

// comands in config-file start with
pub const CONF_LINE_IDENTIFIER__CONTROL: char = ':';

// the default can be changed by one of the following switches
const DEFAULT_REWARDING_SCHEME: RewardingScheme = RewardingScheme::UnhideWhenGuessedChar;

// Keyword to switch rewarding scheme
// :traditional-rewarding
const UNHIDE_WHEN_LOST_LIVE_IDENTIFIER: &str = "traditional-rewarding";

// Keyword to switch rewarding scheme
// :success-rewarding
const UNHIDE_WHEN_GUESSED_CHAR_IDENTIFIER: &str = "success-rewarding";

// images in config file start with
pub const CONF_LINE_IDENTIFIER__IMAGE: char = '|';

const BIG_IMAGE: usize = 100; // sort algorithm <-> random algorithm

// first char of image lines must be '|'
const DEFAULT_IMAGES: &[&str] = &[
    "
|    ,,,,,
|   (o   o)
|    /. .\\
|   (_____)
|     : :
|    ##O##'
|  ,,,: :,,,
| _)\\ : : /(____
|{  \\     /  ___}
| \\/)     ((/
|  (_______)
|    :   :
|    :   :
|   / \\ / \\
|   \"\"\" \"\"\"
",
    "
|    |\\_|X|_/|
|   /         \\
| =(  O     O  )=
|  -\\    o    /-
|   / .-----. \\
| /_ | o   o |_ \\
|(U  |       |  U)
|   _|_     _|_
|  (   )---(   )
",
    "
|        _.---._    /\\\\
|     ./'       \"--`\\//
|   ./              o \\
|  /./\\  )______   \\__ \\
| ./  / /\\ \\   | \\ \\  \\ \\
|    / /  \\ \\  | |\\ \\  \\7
|     \"     \"    \"  \"        VK
",
    "
|       ,.
|      (_|,.
|     ,' /, )_______   _
|  __j o``-'        `.'-)'
| (\")                 \\'
|  `-j                |
|    `-._(           /
|       |_\\  |--^.  /
|      /_]'|_| /_)_/
|         /_]'  /_]'
# Author: hjw
",
    "
|        _
|       [ ]
|      (   )
|       |>|
|    __/===\\__
|   //| o=o |\\\\
| <]  | o=o |  [>
|     \\=====/
|    / / | \\ \\
|   <_________>
",
    "
|                          (_)(_)
|                          /     \\
|                         /       |
|                        /   \\  * |
|          ________     /    /\\__/
|  _      /        \\   /    /
| / \\    /  ____    \\_/    /
|//\\ \\  /  /    \\         /
|V  \\ \\/  /      \\       /
|    \\___/        \\_____/
",
    "
|         .-.
|        (. .)__,')
|        / V      )
|  ()    \\  (   \\/
|<)-`\\()  `._`._ \\
|  <).>=====<<==`'====
|   C-'`(>
# Author: hjw
",
    "
| >(. )
|  |  (     /)
|  |   \\___/ )
|  (   ----- )  >@)_//   >@)_//  >@)_//  >@)_//
|   \\_______/    (__)     (__)    (__)    (__)
|~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
",
    "
|           __
|           /(`o
|     ,-,  //  \\\\
|    (,,,) ||   V
|   (,,,,)\\//
|   (,,,/w)-'
|   \\,,/w)
|   `V/uu
|     / |
|     | |
|     o o
|     \\ |
|\\,/  ,\\|,.  \\,/
",
    "
|o
| \\_/\\o
|( Oo)                    \\|/
|(_=-)  .===O-  ~~Z~A~P~~ -O-
|/   \\_/U'                /|\\
|||  |_/
|\\\\  |
|{K ||
| | PP
| | ||
| (__\\\\
# Author: ac
",
    "
|      ______
|     /     /\\
|    /     /  \\
|   /_____/----\\_    (
|  \"     \"          ).
| _ ___          o (:') o
|(@))_))        o ~/~~\\~ o
|                o  o  o
",
    "
|                             _______     |\\
|                            |License|    | \\
|  _____                     | ~~*~~ |    |  \\
| |     |  (((        .--.   |_______|    |
| |DrJRO| ~OvO~ __   (////)               |
| |     | ( _ )|==|   \\__/                |
| |o    |  \\_/ |_(|  /    \\   _______     |
| |     | //|\\\\   \\\\//|  |\\\\  |__o__|     |
| |   __|//\\_/\\\\ __\\/ |__|//  |__o__|     |
| |  |==\"\"//=\\\\\"\"====|||||)   |__o__|     |
|_|__||_|_||_||_____||||||____|__o__|_____|
|    ||  (_) (_)    ||||||                \\
|    []             [(_)(_)
",
];

#[derive(PartialOrd, Eq, PartialEq, Debug, Copy, Clone)] //omitting Ord
pub struct ImChar {
    pub point: (u8, u8),
    pub code: char,
}

impl fmt::Display for ImChar {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.code)
    }
}

// Ord enables us to v.sort()
impl Ord for ImChar {
    fn cmp(&self, other: &Self) -> Ordering {
        fn weight(ic: &ImChar) -> isize {
            let &ImChar { point: (x, y), .. } = ic;
            // points near the lower left corner are light
            x as isize - y as isize
        }
        weight(&self).cmp(&weight(&other))
    }
}

#[derive(Debug, PartialEq)]
pub enum RewardingScheme {
    UnhideWhenLostLife,
    UnhideWhenGuessedChar,
}

#[derive(Debug)]
pub struct Image {
    pub ichars: Vec<ImChar>,
    pub offset: (usize, usize),
    pub dimension: (u8, u8),
    pub visible_points: usize,
    pub rewarding_scheme: RewardingScheme,
}

impl Render for Image {
    fn render(&self) {
        use std::io::prelude::*;
        use std::io;

        let cursor = cursor();
        for ic in self.ichars.iter().take(self.visible_points) {
            let &ImChar {
                point: (x, y),
                code,
            } = ic;
            cursor
                .goto(
                    (self.offset.1 + (x as usize) + 1) as u16,
                    (self.offset.0 + (y as usize) + 1) as u16,
                )
                .expect("Can not set cursor position.");

            print!("{}", &code );

            // The following flush() is necessary on Windows terminals that do not understand ANSI
            // escape code such as Window 7, 8 and older 10. BTW, in 2016, Microsoft released the
            // Windows 10 Version 1511 update which unexpectedly implemented support for ANSI
            // escape sequences.
            // [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code#Windows)

            io::stdout().flush().ok().expect("Could not flush stdout");
        }
        // after printing the image s, bring the cursor below
        cursor
            .goto(0, (self.dimension.1 as usize + 1 + self.offset.1) as u16)
            .expect("Can not move cursor.");
    }
}

impl Image {
    pub fn new(string: &str, offset: (usize, usize)) -> Self {
        let mut v: Vec<ImChar> = Vec::new();

        let mut rewarding_scheme: RewardingScheme = DEFAULT_REWARDING_SCHEME;
        for (y, line) in string
            // split in lines
            .lines()
            // interpret identifier line
            .filter_map(|l| {
                if l.starts_with(CONF_LINE_IDENTIFIER__CONTROL) {
                    if l[1..].trim().contains(UNHIDE_WHEN_LOST_LIVE_IDENTIFIER) {
                        rewarding_scheme = RewardingScheme::UnhideWhenLostLife;
                    }
                    if l[1..].trim().contains(UNHIDE_WHEN_GUESSED_CHAR_IDENTIFIER) {
                        rewarding_scheme = RewardingScheme::UnhideWhenGuessedChar;
                    }
                    None
                } else {
                    Some(l)
                }
            })
            // consider only lines starting with '|'
            .filter(|&l| l.starts_with(CONF_LINE_IDENTIFIER__IMAGE))
            .enumerate()
        //.inspect(|&(n,l)| println!("line {:?}: {:?} ", n,l))
        {
            let mut ii: Vec<_> = line
                .char_indices()
                // skip first char '|'
                .skip(1)
                // consider only chars != ' '
                .filter(|&(_, c)| c != ' ')
                // save in ImageChar object
                .map(|(x, c)| ImChar {
                    point: (x as u8, y as u8),
                    code: c,
                })
                .collect();
            v.append(&mut ii);
        }

        // find dimensions
        let mut x_max = 0;
        let mut y_max = 0;
        for i in &v {
            let &ImChar { point: (x, y), .. } = i;
            if x > x_max {
                x_max = x
            };
            if y > y_max {
                y_max = y
            };
        }

        // order points
        let v_len = v.len();
        if v_len <= BIG_IMAGE {
            v.sort(); // Sort algorithm, see "impl Ord for ImageChar"
        } else {
            let mut rng = thread_rng();
            (&mut v).shuffle(&mut rng); // points appear randomly.
        }

        if v.is_empty() {
            let mut rng = thread_rng();
            Self::new((&DEFAULT_IMAGES).choose(&mut rng).unwrap(), offset)
        } else {
            Self {
                ichars: v,
                offset,
                dimension: (x_max, y_max),
                visible_points: v_len,
                rewarding_scheme,
            }
        }
    }

    pub fn disclose(&mut self, lives_frac: (usize, usize), guessed_chars_frac: (usize, usize)) {
        let l = self.ichars.len();

        let as_points = |(n, d)| (3 * l * (d - n) as usize / d as usize + l) / 4;

        self.visible_points = match self.rewarding_scheme {
            RewardingScheme::UnhideWhenGuessedChar => as_points(guessed_chars_frac),
            RewardingScheme::UnhideWhenLostLife => as_points(lives_frac),
        };
    }
}
<|endoftext|>


<commit_before>use super::{ArrayLength, GenericArray};
use core::{mem, ptr};
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use nodrop::NoDrop;

impl<T: Default, N> Default for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn default() -> Self {
        unsafe {
            let mut res: NoDrop<GenericArray<T, N>> = NoDrop::new(mem::uninitialized());
            for r in res.iter_mut() {
                ptr::write(r, T::default())
            }
            res.into_inner()
        }
    }
}

impl<T: Clone, N> Clone for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> GenericArray<T, N> {
        unsafe {
            let mut res: NoDrop<GenericArray<T, N>> = NoDrop::new(mem::uninitialized());
            for i in 0..N::to_usize() {
                ptr::write(&mut res[i], self[i].clone())
            }
            res.into_inner()
        }
    }
}
impl<T: Copy, N> Copy for GenericArray<T, N>
where
    N: ArrayLength<T>,
    N::ArrayType: Copy,
{
}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn eq(&self, other: &Self) -> bool {
        **self == **other
    }
}
impl<T: Eq, N> Eq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
}

impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&self, &other)
    }
}

impl<T: Ord, N> Ord for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
        Ord::cmp(&self, &other)
    }
}

impl<T: Debug, N> Debug for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(fmt)
    }
}

impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn borrow(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn borrow_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn as_ref(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn as_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T: Hash, N> Hash for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        Hash::hash(&self[..], state)
    }
}
<commit_msg>Use new builder methods for Default and Clone implementations.<commit_after>use super::{ArrayLength, GenericArray};
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};

impl<T: Default, N> Default for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline]
    fn default() -> Self {
        Self::generate(|_| T::default())
    }
}

impl<T: Clone, N> Clone for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> GenericArray<T, N> {
        self.map_ref(|x| x.clone())
    }
}
impl<T: Copy, N> Copy for GenericArray<T, N>
where
    N: ArrayLength<T>,
    N::ArrayType: Copy,
{
}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn eq(&self, other: &Self) -> bool {
        **self == **other
    }
}
impl<T: Eq, N> Eq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
}

impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&self, &other)
    }
}

impl<T: Ord, N> Ord for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
        Ord::cmp(&self, &other)
    }
}

impl<T: Debug, N> Debug for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(fmt)
    }
}

impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn borrow(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn borrow_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn as_ref(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn as_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T: Hash, N> Hash for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        Hash::hash(&self[..], state)
    }
}
<|endoftext|>


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

//! A number of passes which remove various redundancies in the CFG.
//!
//! The `SimplifyCfg` pass gets rid of unnecessary blocks in the CFG, whereas the `SimplifyLocals`
//! gets rid of all the unnecessary local variable declarations.
//!
//! The `SimplifyLocals` pass is kinda expensive and therefore not very suitable to be run often.
//! Most of the passes should not care or be impacted in meaningful ways due to extra locals
//! either, so running the pass once, right before translation, should suffice.
//!
//! On the other side of the spectrum, the `SimplifyCfg` pass is considerably cheap to run, thus
//! one should run it after every pass which may modify CFG in significant ways. This pass must
//! also be run before any analysis passes because it removes dead blocks, and some of these can be
//! ill-typed.
//!
//! The cause of this typing issue is typeck allowing most blocks whose end is not reachable have
//! an arbitrary return type, rather than having the usual () return type (as a note, typeck's
//! notion of reachability is in fact slightly weaker than MIR CFG reachability - see #31617). A
//! standard example of the situation is:
//!
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return.

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext};
use std::borrow::Cow;
use transform::{MirPass, MirSource};

pub struct SimplifyCfg { label: String }

impl SimplifyCfg {
    pub fn new(label: &str) -> Self {
        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
    }
}

pub fn simplify_cfg(mir: &mut Mir) {
    CfgSimplifier::new(mir).simplify();
    remove_dead_blocks(mir);

    // FIXME: Should probably be moved into some kind of pass manager
    mir.basic_blocks_mut().raw.shrink_to_fit();
}

impl MirPass for SimplifyCfg {
    fn name<'a>(&'a self) -> Cow<'a, str> {
        Cow::Borrowed(&self.label)
    }

    fn run_pass<'a, 'tcx>(&self,
                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          _src: MirSource,
                          mir: &mut Mir<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
        simplify_cfg(mir);
    }
}

pub struct CfgSimplifier<'a, 'tcx: 'a> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>
}

impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
    pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(mir) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors().iter() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = mir.basic_blocks_mut();

        CfgSimplifier {
            basic_blocks,
            pred_count,
        }
    }

    pub fn simplify(mut self) {
        self.strip_nops();

        loop {
            let mut changed = false;

            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
                if self.pred_count[bb] == 0 {
                    continue
                }

                debug!("simplifying {:?}", bb);

                let mut terminator = self.basic_blocks[bb].terminator.take()
                    .expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut new_stmts = vec![];
                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
                    changed |= inner_changed;
                }

                self.basic_blocks[bb].statements.extend(new_stmts);
                self.basic_blocks[bb].terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed { break }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator: ref mut terminator @ Some(Terminator {
                    kind: TerminatorKind::Goto { .. }, ..
                }), ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!()
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;

        if self.pred_count[*start] == 1 {
            // This is the last reference to *start, so the pred-count to
            // to target is moved into the current block.
            self.pred_count[*start] = 0;
        } else {
            self.pred_count[target] += 1;
            self.pred_count[*start] -= 1;
        }

        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(&mut self,
                       new_stmts: &mut Vec<Statement<'tcx>>,
                       terminator: &mut Terminator<'tcx>)
                       -> bool
    {
        let target = match terminator.kind {
            TerminatorKind::Goto { target }
                if self.pred_count[target] == 1
                => target,
            _ => return false
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false
            }
        };
        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::SwitchInt { .. } => {},
            _ => return false
        };

        let first_succ = {
            let successors = terminator.successors();
            if let Some(&first_succ) = terminator.successors().get(0) {
                if successors.iter().all(|s| *s == first_succ) {
                    self.pred_count[first_succ] -= (successors.len()-1) as u32;
                    first_succ
                } else {
                    return false
                }
            } else {
                return false
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }

    fn strip_nops(&mut self) {
        for blk in self.basic_blocks.iter_mut() {
            blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
                false
            } else {
                true
            })
        }
    }
}

pub fn remove_dead_blocks(mir: &mut Mir) {
    let mut seen = BitVector::new(mir.basic_blocks().len());
    for (bb, _) in traversal::preorder(mir) {
        seen.insert(bb.index());
    }

    let basic_blocks = mir.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since alive_index is
            // non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}

pub struct SimplifyLocals;

impl MirPass for SimplifyLocals {
    fn run_pass<'a, 'tcx>(&self,
                          _: TyCtxt<'a, 'tcx, 'tcx>,
                          _: MirSource,
                          mir: &mut Mir<'tcx>) {
        let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
        marker.visit_mir(mir);
        // Return pointer and arguments are always live
        marker.locals.insert(0);
        for idx in mir.args_iter() {
            marker.locals.insert(idx.index());
        }
        let map = make_local_map(&mut mir.local_decls, marker.locals);
        // Update references to all vars and tmps now
        LocalUpdater { map: map }.visit_mir(mir);
        mir.local_decls.shrink_to_fit();
    }
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<'tcx, I: Idx, V>(vec: &mut IndexVec<I, V>, mask: BitVector) -> Vec<usize> {
    let mut map: Vec<usize> = ::std::iter::repeat(!0).take(vec.len()).collect();
    let mut used = 0;
    for alive_index in mask.iter() {
        map[alive_index] = used;
        if alive_index != used {
            vec.swap(alive_index, used);
        }
        used += 1;
    }
    vec.truncate(used);
    map
}

struct DeclMarker {
    pub locals: BitVector,
}

impl<'tcx> Visitor<'tcx> for DeclMarker {
    fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
        // ignore these altogether, they get removed along with their otherwise unused decls.
        if ctx != PlaceContext::StorageLive && ctx != PlaceContext::StorageDead {
            self.locals.insert(local.index());
        }
    }
}

struct LocalUpdater {
    map: Vec<usize>,
}

impl<'tcx> MutVisitor<'tcx> for LocalUpdater {
    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
        // Remove unnecessary StorageLive and StorageDead annotations.
        data.statements.retain(|stmt| {
            match stmt.kind {
                StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
                    self.map[l.index()] != !0
                }
                _ => true
            }
        });
        self.super_basic_block_data(block, data);
    }
    fn visit_local(&mut self, l: &mut Local, _: PlaceContext<'tcx>, _: Location) {
        *l = Local::new(self.map[l.index()]);
    }
}
<commit_msg>rustc_mir: do not remove dead user variables if debuginfo needs them.<commit_after>// Copyright 2015 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.

//! A number of passes which remove various redundancies in the CFG.
//!
//! The `SimplifyCfg` pass gets rid of unnecessary blocks in the CFG, whereas the `SimplifyLocals`
//! gets rid of all the unnecessary local variable declarations.
//!
//! The `SimplifyLocals` pass is kinda expensive and therefore not very suitable to be run often.
//! Most of the passes should not care or be impacted in meaningful ways due to extra locals
//! either, so running the pass once, right before translation, should suffice.
//!
//! On the other side of the spectrum, the `SimplifyCfg` pass is considerably cheap to run, thus
//! one should run it after every pass which may modify CFG in significant ways. This pass must
//! also be run before any analysis passes because it removes dead blocks, and some of these can be
//! ill-typed.
//!
//! The cause of this typing issue is typeck allowing most blocks whose end is not reachable have
//! an arbitrary return type, rather than having the usual () return type (as a note, typeck's
//! notion of reachability is in fact slightly weaker than MIR CFG reachability - see #31617). A
//! standard example of the situation is:
//!
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return.

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext};
use rustc::session::config::FullDebugInfo;
use std::borrow::Cow;
use transform::{MirPass, MirSource};

pub struct SimplifyCfg { label: String }

impl SimplifyCfg {
    pub fn new(label: &str) -> Self {
        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
    }
}

pub fn simplify_cfg(mir: &mut Mir) {
    CfgSimplifier::new(mir).simplify();
    remove_dead_blocks(mir);

    // FIXME: Should probably be moved into some kind of pass manager
    mir.basic_blocks_mut().raw.shrink_to_fit();
}

impl MirPass for SimplifyCfg {
    fn name<'a>(&'a self) -> Cow<'a, str> {
        Cow::Borrowed(&self.label)
    }

    fn run_pass<'a, 'tcx>(&self,
                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          _src: MirSource,
                          mir: &mut Mir<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
        simplify_cfg(mir);
    }
}

pub struct CfgSimplifier<'a, 'tcx: 'a> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>
}

impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
    pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(mir) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors().iter() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = mir.basic_blocks_mut();

        CfgSimplifier {
            basic_blocks,
            pred_count,
        }
    }

    pub fn simplify(mut self) {
        self.strip_nops();

        loop {
            let mut changed = false;

            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
                if self.pred_count[bb] == 0 {
                    continue
                }

                debug!("simplifying {:?}", bb);

                let mut terminator = self.basic_blocks[bb].terminator.take()
                    .expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut new_stmts = vec![];
                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
                    changed |= inner_changed;
                }

                self.basic_blocks[bb].statements.extend(new_stmts);
                self.basic_blocks[bb].terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed { break }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator: ref mut terminator @ Some(Terminator {
                    kind: TerminatorKind::Goto { .. }, ..
                }), ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!()
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;

        if self.pred_count[*start] == 1 {
            // This is the last reference to *start, so the pred-count to
            // to target is moved into the current block.
            self.pred_count[*start] = 0;
        } else {
            self.pred_count[target] += 1;
            self.pred_count[*start] -= 1;
        }

        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(&mut self,
                       new_stmts: &mut Vec<Statement<'tcx>>,
                       terminator: &mut Terminator<'tcx>)
                       -> bool
    {
        let target = match terminator.kind {
            TerminatorKind::Goto { target }
                if self.pred_count[target] == 1
                => target,
            _ => return false
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false
            }
        };
        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::SwitchInt { .. } => {},
            _ => return false
        };

        let first_succ = {
            let successors = terminator.successors();
            if let Some(&first_succ) = terminator.successors().get(0) {
                if successors.iter().all(|s| *s == first_succ) {
                    self.pred_count[first_succ] -= (successors.len()-1) as u32;
                    first_succ
                } else {
                    return false
                }
            } else {
                return false
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }

    fn strip_nops(&mut self) {
        for blk in self.basic_blocks.iter_mut() {
            blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
                false
            } else {
                true
            })
        }
    }
}

pub fn remove_dead_blocks(mir: &mut Mir) {
    let mut seen = BitVector::new(mir.basic_blocks().len());
    for (bb, _) in traversal::preorder(mir) {
        seen.insert(bb.index());
    }

    let basic_blocks = mir.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since alive_index is
            // non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}

pub struct SimplifyLocals;

impl MirPass for SimplifyLocals {
    fn run_pass<'a, 'tcx>(&self,
                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          _: MirSource,
                          mir: &mut Mir<'tcx>) {
        let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
        marker.visit_mir(mir);
        // Return pointer and arguments are always live
        marker.locals.insert(RETURN_PLACE.index());
        for arg in mir.args_iter() {
            marker.locals.insert(arg.index());
        }

        // We may need to keep dead user variables live for debuginfo.
        if tcx.sess.opts.debuginfo == FullDebugInfo {
            for local in mir.vars_iter() {
                marker.locals.insert(local.index());
            }
        }

        let map = make_local_map(&mut mir.local_decls, marker.locals);
        // Update references to all vars and tmps now
        LocalUpdater { map: map }.visit_mir(mir);
        mir.local_decls.shrink_to_fit();
    }
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<'tcx, I: Idx, V>(vec: &mut IndexVec<I, V>, mask: BitVector) -> Vec<usize> {
    let mut map: Vec<usize> = ::std::iter::repeat(!0).take(vec.len()).collect();
    let mut used = 0;
    for alive_index in mask.iter() {
        map[alive_index] = used;
        if alive_index != used {
            vec.swap(alive_index, used);
        }
        used += 1;
    }
    vec.truncate(used);
    map
}

struct DeclMarker {
    pub locals: BitVector,
}

impl<'tcx> Visitor<'tcx> for DeclMarker {
    fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
        // ignore these altogether, they get removed along with their otherwise unused decls.
        if ctx != PlaceContext::StorageLive && ctx != PlaceContext::StorageDead {
            self.locals.insert(local.index());
        }
    }
}

struct LocalUpdater {
    map: Vec<usize>,
}

impl<'tcx> MutVisitor<'tcx> for LocalUpdater {
    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
        // Remove unnecessary StorageLive and StorageDead annotations.
        data.statements.retain(|stmt| {
            match stmt.kind {
                StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
                    self.map[l.index()] != !0
                }
                _ => true
            }
        });
        self.super_basic_block_data(block, data);
    }
    fn visit_local(&mut self, l: &mut Local, _: PlaceContext<'tcx>, _: Location) {
        *l = Local::new(self.map[l.index()]);
    }
}
<|endoftext|>


<commit_before>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "81e754c359c471f91263813c46c67955071716a7";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Deprecated anonymous parameter syntax in traits
    "test/ui/issues/issue-13105.rs",
    "test/ui/issues/issue-13775.rs",
    "test/ui/issues/issue-34074.rs",
    "test/ui/proc-macro/trait-fn-args-2015.rs",

    // not actually test cases
    "test/rustdoc-ui/test-compile-fail2.rs",
    "test/rustdoc-ui/test-compile-fail3.rs",
    "test/ui/include-single-expr-helper.rs",
    "test/ui/include-single-expr-helper-1.rs",
    "test/ui/issues/auxiliary/issue-21146-inc.rs",
    "test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "test/ui/lint/expansion-time-include.rs",
    "test/ui/macros/auxiliary/macro-comma-support.rs",
    "test/ui/macros/auxiliary/macro-include-items-expr.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/src/") {
        path
    } else if let Some(path) = path_string.strip_prefix("tests/rust/library/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    // TODO assert that parsing fails on the parse-fail cases
    if path.starts_with("test/parse-fail")
        || path.starts_with("test/compile-fail")
        || path.starts_with("test/rustfix")
    {
        return false;
    }

    if path.starts_with("test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust/src");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/src/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Update tested compiler repo to nightly 2020-08-18<commit_after>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "792c645ca7d11a8d254df307d019c5bf01445c37";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // TODO: type parameters after const parameters: struct S<const N: usize, T>
    // https://github.com/dtolnay/syn/issues/886
    "test/ui/const-generics/defaults/complex-unord-param.rs",
    "test/ui/const-generics/defaults/needs-feature.rs",
    "test/ui/const-generics/defaults/simple-defaults.rs",
    "test/ui/const-generics/type-after-const-ok.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "test/ui/issues/issue-13105.rs",
    "test/ui/issues/issue-13775.rs",
    "test/ui/issues/issue-34074.rs",
    "test/ui/proc-macro/trait-fn-args-2015.rs",

    // Not actually test cases
    "test/rustdoc-ui/test-compile-fail2.rs",
    "test/rustdoc-ui/test-compile-fail3.rs",
    "test/ui/include-single-expr-helper.rs",
    "test/ui/include-single-expr-helper-1.rs",
    "test/ui/issues/auxiliary/issue-21146-inc.rs",
    "test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "test/ui/lint/expansion-time-include.rs",
    "test/ui/macros/auxiliary/macro-comma-support.rs",
    "test/ui/macros/auxiliary/macro-include-items-expr.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/src/") {
        path
    } else if let Some(path) = path_string.strip_prefix("tests/rust/library/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    // TODO assert that parsing fails on the parse-fail cases
    if path.starts_with("test/parse-fail")
        || path.starts_with("test/compile-fail")
        || path.starts_with("test/rustfix")
    {
        return false;
    }

    if path.starts_with("test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust/src");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/src/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Remove unused file<commit_after><|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ops::Deref;
use std::slice::Iter;

use chrono::{DateTime, UTC};
use serde_json;

use api::{CratesIO, VersionData};
use errors::*;

#[derive(Debug)]
pub struct Version {
    pub num: String, // XXX should be semver::Version
    pub downloads: i32,
    pub created_at: DateTime<UTC>,
    pub updated_at: DateTime<UTC>,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

impl Version {
    fn from_versiondata(data: &VersionData) -> Self {
        Version {
            num: data.num.clone(),
            downloads: data.downloads,
            created_at: data.created_at,
            updated_at: data.updated_at,
            features: data.features.clone(),
            yanked: data.yanked,
        }
    }
}

#[derive(Debug)]
pub struct Versions {
    versions: Vec<Version>,
}

impl Versions {
    fn by_id(id: i32, versions: &[VersionData]) -> Option<&VersionData> {
        for v in versions {
            if id == v.id {
                return Some(v);
            }
        }
        None
    }

    fn from_crate_data(data: &CratesIO) -> Self {
        let mut versions = Vec::new();
        if let Some(vers) = data.krate.versions.as_ref() {
            for id in vers {
                if let Some(versiondata) = Versions::by_id(*id, &data.versions) {
                    versions.push(Version::from_versiondata(versiondata))
                }
            }
        }
        Versions { versions: versions }
    }

    pub fn iter(&self) -> Iter<Version> {
        self.versions.iter()
    }
}

impl Deref for Versions {
    type Target = [Version];
    fn deref(&self) -> &[Version] {
        &self.versions
    }
}

// impl Iterator for Versions {
//     type Item = Version;
//     fn
// }
#[derive(Debug)]
pub struct Crate {
    pub id: String,
    pub name: String,
    pub updated_at: DateTime<UTC>,
    pub created_at: DateTime<UTC>,
    pub downloads: i32,
    pub max_version: String, // XXX Should be semver::Version
    pub description: Option<String>,
    pub homepage: Option<String>,
    pub documentation: Option<String>,
    pub readme: Option<String>,
    pub license: Option<String>,
    pub repository: Option<String>,
    pub max_upload_size: Option<i32>,
    pub versions: Versions,
}

impl Crate {
    pub fn json_data(name: &str) -> Result<String> {
        CratesIO::raw_data(name)
    }

    pub fn json_pretty(name: &str) -> Result<String> {
        let json = CratesIO::raw_data(name)?;
        let json = serde_json::from_str::<serde_json::Value>(&json)?;
        serde_json::to_string_pretty(&json).chain_err(|| "Failed to prettify")
    }

    pub fn by_name(name: &str) -> Result<Self> {
        let data = CratesIO::by_name(name)?;
        let versions = Versions::from_crate_data(&data);
        Ok(Crate {
               id: data.krate.id,
               name: data.krate.name,
               updated_at: data.krate.updated_at,
               created_at: data.krate.created_at,
               downloads: data.krate.downloads,
               max_version: data.krate.max_version,
               description: data.krate.description,
               homepage: data.krate.homepage,
               documentation: data.krate.documentation,
               readme: None,
               license: data.krate.license,
               repository: data.krate.repository,
               max_upload_size: None,
               versions: versions,
           })
    }
}
<commit_msg>Drop commented out code<commit_after>use std::collections::HashMap;
use std::ops::Deref;
use std::slice::Iter;

use chrono::{DateTime, UTC};
use serde_json;

use api::{CratesIO, VersionData};
use errors::*;

#[derive(Debug)]
pub struct Version {
    pub num: String, // XXX should be semver::Version
    pub downloads: i32,
    pub created_at: DateTime<UTC>,
    pub updated_at: DateTime<UTC>,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

impl Version {
    fn from_versiondata(data: &VersionData) -> Self {
        Version {
            num: data.num.clone(),
            downloads: data.downloads,
            created_at: data.created_at,
            updated_at: data.updated_at,
            features: data.features.clone(),
            yanked: data.yanked,
        }
    }
}

#[derive(Debug)]
pub struct Versions {
    versions: Vec<Version>,
}

impl Versions {
    fn by_id(id: i32, versions: &[VersionData]) -> Option<&VersionData> {
        for v in versions {
            if id == v.id {
                return Some(v);
            }
        }
        None
    }

    fn from_crate_data(data: &CratesIO) -> Self {
        let mut versions = Vec::new();
        if let Some(vers) = data.krate.versions.as_ref() {
            for id in vers {
                if let Some(versiondata) = Versions::by_id(*id, &data.versions) {
                    versions.push(Version::from_versiondata(versiondata))
                }
            }
        }
        Versions { versions: versions }
    }

    pub fn iter(&self) -> Iter<Version> {
        self.versions.iter()
    }
}

impl Deref for Versions {
    type Target = [Version];
    fn deref(&self) -> &[Version] {
        &self.versions
    }
}

#[derive(Debug)]
pub struct Crate {
    pub id: String,
    pub name: String,
    pub updated_at: DateTime<UTC>,
    pub created_at: DateTime<UTC>,
    pub downloads: i32,
    pub max_version: String, // XXX Should be semver::Version
    pub description: Option<String>,
    pub homepage: Option<String>,
    pub documentation: Option<String>,
    pub readme: Option<String>,
    pub license: Option<String>,
    pub repository: Option<String>,
    pub max_upload_size: Option<i32>,
    pub versions: Versions,
}

impl Crate {
    pub fn json_data(name: &str) -> Result<String> {
        CratesIO::raw_data(name)
    }

    pub fn json_pretty(name: &str) -> Result<String> {
        let json = CratesIO::raw_data(name)?;
        let json = serde_json::from_str::<serde_json::Value>(&json)?;
        serde_json::to_string_pretty(&json).chain_err(|| "Failed to prettify")
    }

    pub fn by_name(name: &str) -> Result<Self> {
        let data = CratesIO::by_name(name)?;
        let versions = Versions::from_crate_data(&data);
        Ok(Crate {
               id: data.krate.id,
               name: data.krate.name,
               updated_at: data.krate.updated_at,
               created_at: data.krate.created_at,
               downloads: data.krate.downloads,
               max_version: data.krate.max_version,
               description: data.krate.description,
               homepage: data.krate.homepage,
               documentation: data.krate.documentation,
               readme: None,
               license: data.krate.license,
               repository: data.krate.repository,
               max_upload_size: None,
               versions: versions,
           })
    }
}
<|endoftext|>


<commit_before>use std;
use std::fmt::{Display, Formatter};
use {Result, Error};

#[derive(Debug, Copy, Clone)]
pub enum Logic {
  High,
  Low
}

impl Into<usize> for Logic {
    fn into(self) -> usize {
        match self {
            Logic::High => 1,
            Logic::Low  => 0
        }
    }
}

impl Display for Logic {
    fn fmt(&self, f: &mut Formatter) -> std::result::Result<(), std::fmt::Error> {
        let v: usize = (*self).into();
        write!(f, "{}", v)
    }
}

#[derive(Debug, Copy, Clone)]
pub enum Logic3 {
  High,
  Low,
  Z
}

pub trait DigitalLogic {
  fn logic_level(&self) -> Logic;
}

impl DigitalLogic for i32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for u32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for isize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for usize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}
impl DigitalLogic for Logic {
  fn logic_level(&self) -> Logic {
    *self
  }
}

pub trait DigitalRead {
  fn digital_read(&mut self) -> Result<Logic>;

  fn get(&mut self) -> Result<Logic> {
    self.digital_read()
  }

  fn is_high(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(true),
          Logic::Low => Ok(false)
      }
  }

  fn is_low(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(false),
          Logic::Low => Ok(true)
      }
  }
}

pub trait DigitalWrite {
  fn digital_write<L: DigitalLogic>(&mut self, level: L) -> Result<()>;

  fn set<L: DigitalLogic>(&mut self, level: L) -> Result<()> {
    self.digital_write(level)
  }

  fn high(&mut self) -> Result<()> {
    self.digital_write(Logic::High)
  }

  fn low(&mut self) -> Result<()> {
    self.digital_write(Logic::Low)
  }
}

pub trait AnalogRead {
  fn analog_read(&self) -> usize;
}

pub trait AnalogWrite {
  fn analog_write(&self, value: usize);
}
<commit_msg>Add Logic::inverse()<commit_after>use std;
use std::fmt::{Display, Formatter};
use {Result, Error};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Logic {
  High,
  Low
}

impl Logic {
    pub fn inverse(self) -> Logic {
        match self {
            Logic::High => Logic::Low,
            Logic::Low  => Logic::High
        }
    }
}

impl Into<usize> for Logic {
    fn into(self) -> usize {
        match self {
            Logic::High => 1,
            Logic::Low  => 0
        }
    }
}

impl Display for Logic {
    fn fmt(&self, f: &mut Formatter) -> std::result::Result<(), std::fmt::Error> {
        let v: usize = (*self).into();
        write!(f, "{}", v)
    }
}

#[derive(Debug, Copy, Clone)]
pub enum Logic3 {
  High,
  Low,
  Z
}

pub trait DigitalLogic {
  fn logic_level(&self) -> Logic;
}

impl DigitalLogic for i32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for u32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for isize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for usize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}
impl DigitalLogic for Logic {
  fn logic_level(&self) -> Logic {
    *self
  }
}

pub trait DigitalRead {
  fn digital_read(&mut self) -> Result<Logic>;

  fn get(&mut self) -> Result<Logic> {
    self.digital_read()
  }

  fn is_high(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(true),
          Logic::Low => Ok(false)
      }
  }

  fn is_low(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(false),
          Logic::Low => Ok(true)
      }
  }
}

pub trait DigitalWrite {
  fn digital_write<L: DigitalLogic>(&mut self, level: L) -> Result<()>;

  fn set<L: DigitalLogic>(&mut self, level: L) -> Result<()> {
    self.digital_write(level)
  }

  fn high(&mut self) -> Result<()> {
    self.digital_write(Logic::High)
  }

  fn low(&mut self) -> Result<()> {
    self.digital_write(Logic::Low)
  }
}

pub trait AnalogRead {
  fn analog_read(&self) -> usize;
}

pub trait AnalogWrite {
  fn analog_write(&self, value: usize);
}

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

    #[test]
    fn logic_inverse() {
        let low = Logic::Low;
        let high = Logic::High;
        assert_eq!(low.inverse(), high);
        assert_eq!(low, high.inverse());
    }
}
<|endoftext|>


<commit_before>#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
    ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
        #[inline]
        fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
            where $v: $crate::de::Visitor<$l>
        {
            $(
                let _ = $arg;
            )*
            self.deserialize(visitor)
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
    (bool<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_bool<$l, $v>()}
    };
    (u8<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u8<$l, $v>()}
    };
    (u16<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u16<$l, $v>()}
    };
    (u32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u32<$l, $v>()}
    };
    (u64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u64<$l, $v>()}
    };
    (i8<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i8<$l, $v>()}
    };
    (i16<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i16<$l, $v>()}
    };
    (i32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i32<$l, $v>()}
    };
    (i64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i64<$l, $v>()}
    };
    (f32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_f32<$l, $v>()}
    };
    (f64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_f64<$l, $v>()}
    };
    (char<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_char<$l, $v>()}
    };
    (str<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_str<$l, $v>()}
    };
    (string<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_string<$l, $v>()}
    };
    (unit<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_unit<$l, $v>()}
    };
    (option<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_option<$l, $v>()}
    };
    (seq<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_seq<$l, $v>()}
    };
    (seq_fixed_size<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_seq_fixed_size<$l, $v>(len: usize)}
    };
    (bytes<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_bytes<$l, $v>()}
    };
    (byte_buf<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_byte_buf<$l, $v>()}
    };
    (map<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_map<$l, $v>()}
    };
    (unit_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
    };
    (newtype_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
    };
    (tuple_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
    };
    (struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
    };
    (struct_field<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_struct_field<$l, $v>()}
    };
    (tuple<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)}
    };
    (enum<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
    };
    (ignored_any<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_ignored_any<$l, $v>()}
    };
}

// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
// documentation.
//
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// #     type Error = value::Error;
/// #
/// #     fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// #         where V: Visitor<'de>
/// #     {
/// #         unimplemented!()
/// #     }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
///     where V: Visitor<'de>
/// {
///     self.deserialize(visitor)
/// }
/// #
/// #     forward_to_deserialize! {
/// #         u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// #         seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// #         tuple_struct struct struct_field tuple enum ignored_any
/// #     }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// #   type Error = value::Error;
/// #
///     fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
///         where V: Visitor<'de>
///     {
///         /* ... */
/// #       let _ = visitor;
/// #       unimplemented!()
///     }
///
///     forward_to_deserialize! {
///         bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
///         seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
///         tuple_struct struct struct_field tuple enum ignored_any
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
/// The macro assumes the convention that your `Deserializer` lifetime parameter
/// is called `'de` and that the `Visitor` type parameters on each method are
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// # impl<'q> Deserializer<'q> for MyDeserializer {
/// #   type Error = value::Error;
/// #    fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// #        where V: Visitor<'q> { unimplemented!() }
/// forward_to_deserialize! {
///     <W: Visitor<'q>>
///     bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
///     seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
///     tuple_struct struct struct_field tuple enum ignored_any
/// }
/// # }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! forward_to_deserialize {
    (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
        $(forward_to_deserialize_helper!{$func<$lifetime, $visitor>})*
    };
    ($($func:ident)*) => {
        $(forward_to_deserialize_helper!{$func<'de, V>})*
    };
}
<commit_msg>Use a deserializer in which V would conflict<commit_after>#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
    ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
        #[inline]
        fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
            where $v: $crate::de::Visitor<$l>
        {
            $(
                let _ = $arg;
            )*
            self.deserialize(visitor)
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
    (bool<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_bool<$l, $v>()}
    };
    (u8<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u8<$l, $v>()}
    };
    (u16<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u16<$l, $v>()}
    };
    (u32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u32<$l, $v>()}
    };
    (u64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_u64<$l, $v>()}
    };
    (i8<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i8<$l, $v>()}
    };
    (i16<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i16<$l, $v>()}
    };
    (i32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i32<$l, $v>()}
    };
    (i64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_i64<$l, $v>()}
    };
    (f32<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_f32<$l, $v>()}
    };
    (f64<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_f64<$l, $v>()}
    };
    (char<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_char<$l, $v>()}
    };
    (str<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_str<$l, $v>()}
    };
    (string<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_string<$l, $v>()}
    };
    (unit<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_unit<$l, $v>()}
    };
    (option<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_option<$l, $v>()}
    };
    (seq<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_seq<$l, $v>()}
    };
    (seq_fixed_size<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_seq_fixed_size<$l, $v>(len: usize)}
    };
    (bytes<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_bytes<$l, $v>()}
    };
    (byte_buf<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_byte_buf<$l, $v>()}
    };
    (map<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_map<$l, $v>()}
    };
    (unit_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
    };
    (newtype_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
    };
    (tuple_struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
    };
    (struct<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
    };
    (struct_field<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_struct_field<$l, $v>()}
    };
    (tuple<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)}
    };
    (enum<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
    };
    (ignored_any<$l:tt, $v:ident>) => {
        forward_to_deserialize_method!{deserialize_ignored_any<$l, $v>()}
    };
}

// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
// documentation.
//
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// #     type Error = value::Error;
/// #
/// #     fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// #         where V: Visitor<'de>
/// #     {
/// #         unimplemented!()
/// #     }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
///     where V: Visitor<'de>
/// {
///     self.deserialize(visitor)
/// }
/// #
/// #     forward_to_deserialize! {
/// #         u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// #         seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// #         tuple_struct struct struct_field tuple enum ignored_any
/// #     }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// #   type Error = value::Error;
/// #
///     fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
///         where V: Visitor<'de>
///     {
///         /* ... */
/// #       let _ = visitor;
/// #       unimplemented!()
///     }
///
///     forward_to_deserialize! {
///         bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
///         seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
///         tuple_struct struct struct_field tuple enum ignored_any
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
/// The macro assumes the convention that your `Deserializer` lifetime parameter
/// is called `'de` and that the `Visitor` type parameters on each method are
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use std::marker::PhantomData;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer<V>(PhantomData<V>);
/// #
/// # impl<'q, V> Deserializer<'q> for MyDeserializer<V> {
/// #     type Error = value::Error;
/// #
/// #     fn deserialize<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// #         where W: Visitor<'q>
/// #     {
/// #         unimplemented!()
/// #     }
/// #
/// forward_to_deserialize! {
///     <W: Visitor<'q>>
///     bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
///     seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
///     tuple_struct struct struct_field tuple enum ignored_any
/// }
/// # }
/// #
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! forward_to_deserialize {
    (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
        $(forward_to_deserialize_helper!{$func<$lifetime, $visitor>})*
    };
    ($($func:ident)*) => {
        $(forward_to_deserialize_helper!{$func<'de, V>})*
    };
}
<|endoftext|>


<commit_before>use vertex::{VertexPosition, AnyVertex};
use super::glium::backend::Facade;
use super::glium::{Frame, DrawParameters};
use cgmath::*;
use triangle::*;
use std::f32;
use renderable::{RenderableVertexNormal, Renderable};
use rand::distributions::Range;
use rand::distributions::IndependentSample;
use rand;

pub struct Ocean<T: AnyVertex, N: AnyVertex> {
    triangles: Vec<Triangle<T, N>>,
    pub verticies: Vec<T>,
    pub normals: Vec<N>,
    pub renderable: RenderableVertexNormal<T, N>,
    scale: [[f32; 4]; 4],
    u_color: [f32; 3],
}

impl<T: AnyVertex, N: AnyVertex> Ocean<T, N> {
    pub fn new(display: &Facade, subdivisions: i32, size: f32) -> Self {
        let t: f32 = (1. + (5.0f32).sqrt()) / 2.;

        let mut p0: Vector3<f32> = Vector3::new(-1., t, 0.);
        let mut p1: Vector3<f32> = Vector3::new(1., t, 0.);
        let mut p2: Vector3<f32> = Vector3::new(-1., -t, 0.);
        let mut p3: Vector3<f32> = Vector3::new(1., -t, 0.);

        let mut p4: Vector3<f32> = Vector3::new(0., -1., t);
        let mut p5: Vector3<f32> = Vector3::new(0., 1., t);
        let mut p6: Vector3<f32> = Vector3::new(0., -1., -t);
        let mut p7: Vector3<f32> = Vector3::new(0., 1., -t);

        let mut p8: Vector3<f32> = Vector3::new(t, 0., -1.);
        let mut p9: Vector3<f32> = Vector3::new(t, 0., 1.);
        let mut p10: Vector3<f32> = Vector3::new(-t, 0., -1.);
        let mut p11: Vector3<f32> = Vector3::new(-t, 0., 1.);

        p0 = p0.normalize();
        p1 = p1.normalize();
        p2 = p2.normalize();
        p3 = p3.normalize();
        p4 = p4.normalize();
        p5 = p5.normalize();
        p6 = p6.normalize();
        p7 = p7.normalize();
        p8 = p8.normalize();
        p9 = p9.normalize();
        p10 = p10.normalize();
        p11 = p11.normalize();

        let mut tris: Vec<Triangle<T, N>> = Vec::new();

        tris.push(Triangle::new([p0, p11, p5], 0.));
        tris.push(Triangle::new([p0, p5, p1], 0.));
        tris.push(Triangle::new([p0, p1, p7], 0.));
        tris.push(Triangle::new([p0, p7, p10], 0.));
        tris.push(Triangle::new([p0, p10, p11], 0.));

        tris.push(Triangle::new([p1, p5, p9], 0.));
        tris.push(Triangle::new([p5, p11, p4], 0.));
        tris.push(Triangle::new([p11, p10, p2], 0.));
        tris.push(Triangle::new([p10, p7, p6], 0.));
        tris.push(Triangle::new([p7, p1, p8], 0.));

        tris.push(Triangle::new([p3, p9, p4], 0.));
        tris.push(Triangle::new([p3, p4, p2], 0.));
        tris.push(Triangle::new([p3, p2, p6], 0.));
        tris.push(Triangle::new([p3, p6, p8], 0.));
        tris.push(Triangle::new([p3, p8, p9], 0.));

        tris.push(Triangle::new([p4, p9, p5], 0.));
        tris.push(Triangle::new([p2, p4, p11], 0.));
        tris.push(Triangle::new([p6, p2, p10], 0.));
        tris.push(Triangle::new([p8, p6, p7], 0.));
        tris.push(Triangle::new([p9, p8, p1], 0.));

        for _ in 0..subdivisions {
            for tri in tris.iter_mut() {
                (*tri).subdivide();
            }
        }

        let mut verts: Vec<T> = Vec::new();
        for tri in tris.iter_mut() {
            verts.append(&mut tri.get_verticies());
        }

        let mut nrm: Vec<N> = Vec::new();
        for t in tris.iter_mut() {
            nrm.append(&mut t.get_normal());
        }
        let vertex_shader = include_str!("../assets/shaders/ocean.glslv");
        let fragment_shader = include_str!("../assets/shaders/ocean.glslf");
        let rnd =
            RenderableVertexNormal::new(display, &verts, &nrm, &vertex_shader, &fragment_shader);

        let scal = [[size, 0.0, 0.0, 0.0],
                    [0.0, size, 0.0, 0.0],
                    [0.0, 0.0, size, 0.0],
                    [0.0, 0.0, 0.0, 1.0]];

        let mut rng = rand::thread_rng();
        let col = Range::new(0.0f32, 1.0f32);

        Ocean {
            triangles: tris,
            verticies: verts,
            normals: nrm,
            renderable: rnd,
            scale: scal,
            u_color: [col.ind_sample(&mut rng), col.ind_sample(&mut rng), col.ind_sample(&mut rng)],
        }
    }

    pub fn draw(&mut self,
                target: &mut Frame,
                params: &DrawParameters,
                m_view: [[f32; 4]; 4],
                m_proj: [[f32; 4]; 4],
                light: [f32; 3],
                time: f32) {
        let uni = uniform!{view : m_view, projection: m_proj, u_light: light, f_time : time, scale: self.scale, u_color : self.u_color};
        self.renderable.render(target, params, &uni);
    }
}
<commit_msg>Use vec!<commit_after>use vertex::{VertexPosition, AnyVertex};
use super::glium::backend::Facade;
use super::glium::{Frame, DrawParameters};
use cgmath::*;
use triangle::*;
use renderable::{RenderableVertexNormal, Renderable};
use rand::distributions::Range;
use rand::distributions::IndependentSample;
use rand;

pub struct Ocean<T: AnyVertex, N: AnyVertex> {
    triangles: Vec<Triangle<T, N>>,
    pub verticies: Vec<T>,
    pub normals: Vec<N>,
    pub renderable: RenderableVertexNormal<T, N>,
    scale: [[f32; 4]; 4],
    u_color: [f32; 3],
}

impl<T, N: AnyVertex> Ocean<T, N>
    where T: AnyVertex,
          N: AnyVertex
{
    pub fn new(display: &Facade, subdivisions: i32, size: f32) -> Self {
        let t: f32 = (1. + (5.0f32).sqrt()) / 2.;

        let mut p0: Vector3<f32> = Vector3::new(-1., t, 0.);
        let mut p1: Vector3<f32> = Vector3::new(1., t, 0.);
        let mut p2: Vector3<f32> = Vector3::new(-1., -t, 0.);
        let mut p3: Vector3<f32> = Vector3::new(1., -t, 0.);

        let mut p4: Vector3<f32> = Vector3::new(0., -1., t);
        let mut p5: Vector3<f32> = Vector3::new(0., 1., t);
        let mut p6: Vector3<f32> = Vector3::new(0., -1., -t);
        let mut p7: Vector3<f32> = Vector3::new(0., 1., -t);

        let mut p8: Vector3<f32> = Vector3::new(t, 0., -1.);
        let mut p9: Vector3<f32> = Vector3::new(t, 0., 1.);
        let mut p10: Vector3<f32> = Vector3::new(-t, 0., -1.);
        let mut p11: Vector3<f32> = Vector3::new(-t, 0., 1.);

        p0 = p0.normalize();
        p1 = p1.normalize();
        p2 = p2.normalize();
        p3 = p3.normalize();
        p4 = p4.normalize();
        p5 = p5.normalize();
        p6 = p6.normalize();
        p7 = p7.normalize();
        p8 = p8.normalize();
        p9 = p9.normalize();
        p10 = p10.normalize();
        p11 = p11.normalize();

        let mut tris = vec![Triangle::new([p0, p11, p5], 0.),
                            Triangle::new([p0, p5, p1], 0.),
                            Triangle::new([p0, p1, p7], 0.),
                            Triangle::new([p0, p7, p10], 0.),
                            Triangle::new([p0, p10, p11], 0.),

                            Triangle::new([p1, p5, p9], 0.),
                            Triangle::new([p5, p11, p4], 0.),
                            Triangle::new([p11, p10, p2], 0.),
                            Triangle::new([p10, p7, p6], 0.),
                            Triangle::new([p7, p1, p8], 0.),

                            Triangle::new([p3, p9, p4], 0.),
                            Triangle::new([p3, p4, p2], 0.),
                            Triangle::new([p3, p2, p6], 0.),
                            Triangle::new([p3, p6, p8], 0.),
                            Triangle::new([p3, p8, p9], 0.),

                            Triangle::new([p4, p9, p5], 0.),
                            Triangle::new([p2, p4, p11], 0.),
                            Triangle::new([p6, p2, p10], 0.),
                            Triangle::new([p8, p6, p7], 0.),
                            Triangle::new([p9, p8, p1], 0.)];

        for _ in 0..subdivisions {
            for tri in tris.iter_mut() {
                (*tri).subdivide();
            }
        }

        let mut verts: Vec<T> = Vec::new();
        for tri in tris.iter_mut() {
            verts.append(&mut tri.get_verticies());
        }

        let mut nrm: Vec<N> = Vec::new();
        for t in tris.iter_mut() {
            nrm.append(&mut t.get_normal());
        }
        let vertex_shader = include_str!("../assets/shaders/ocean.glslv");
        let fragment_shader = include_str!("../assets/shaders/ocean.glslf");
        let rnd =
            RenderableVertexNormal::new(display, &verts, &nrm, &vertex_shader, &fragment_shader);

        let scal = [[size, 0.0, 0.0, 0.0],
                    [0.0, size, 0.0, 0.0],
                    [0.0, 0.0, size, 0.0],
                    [0.0, 0.0, 0.0, 1.0]];

        let mut rng = rand::thread_rng();
        let col = Range::new(0.0f32, 1.0f32);

        Ocean {
            triangles: tris,
            verticies: verts,
            normals: nrm,
            renderable: rnd,
            scale: scal,
            u_color: [col.ind_sample(&mut rng), col.ind_sample(&mut rng), col.ind_sample(&mut rng)],
        }
    }

    pub fn draw(&mut self,
                target: &mut Frame,
                params: &DrawParameters,
                m_view: [[f32; 4]; 4],
                m_proj: [[f32; 4]; 4],
                light: [f32; 3],
                time: f32) {
        let uni = uniform!{view : m_view, projection: m_proj, u_light: light, f_time : time, scale: self.scale, u_color : self.u_color};
        self.renderable.render(target, params, &uni);
    }
}
<|endoftext|>


<commit_before>
use libc::{c_char};

#[repr(C)]
    struct mrb_state;
#[repr(C)]
    struct mrb_value;
#[repr(C)]
    struct RClass;

#[link(name="m")]
#[link(name="mruby")]
extern "C" {

    fn mrb_open() -> *mut mrb_state;
    fn mrb_load_string(state:*mut mrb_state,s:*const c_char) -> mrb_value;
    fn mrb_close(state:*mut mrb_state);
    fn mrb_class_get(state:*mut mrb_state,name:*const c_char) -> *mut RClass;
    fn mrb_define_class(state:*mut mrb_state,name:*const c_char,class:*mut RClass) -> *mut RClass;
}

enum MvalType {
    TypeFalse ,
    TypeFree,
    TypeTrue,
    TypeFixnum,
    TypeSymbol,
    TypeUndef,
    TypeFloat,
    TypeCptr,
    TypeObject,
    TypeClass,
    TypeModule,
    TypeIClass,
    TypeSClass,
    TypeProc,
    TypeArray,
    TypeHash,
    TypeString,
    TypeRange,
    TypeException,
    TypeFile,
    TypeEnv,
    TypeData,
    TypeFiber,
    TypeMaxDefine
}

pub struct Mrb{
    state:*mut mrb_state
}

pub struct Value {
    val :*mut mrb_value
}

pub struct Class<'a>{
    mrb : &'a Mrb,
    class :*mut RClass
}

pub fn open() -> Mrb {
    let s = unsafe { mrb_open() } ;
    Mrb{state:s}
}

impl Mrb {
    pub fn load_str(&self,s:&str) {
        let cs = s.to_c_str();
        unsafe {
            mrb_load_string(self.state,cs.as_ptr());
        }
    }

    pub fn close(&self) {
        unsafe {
            mrb_close(self.state);
        }
    }

    pub fn define_class(&self,name:&str,clz:&Class) -> Class {
        let cs = name.to_c_str();
        let c = unsafe { mrb_define_class(self.state,cs.as_ptr(),clz.class) } ;
        Class{mrb:self,class:c}
    }

    pub fn obj_class(&self) -> Class {
        let s = "Object";
        let c = unsafe { mrb_class_get(self.state,s.to_c_str().as_ptr()) } ;
        Class{mrb:self,class:c}
    }
}

#[test]
fn test_open_class() {
    let m = open();
    let exec = "[1,2,3].each do |i| puts i+1 end";
    m.load_str(exec);

    let o = &m.obj_class();
    let c = m.define_class("Hello",o);
    m.close();
}
<commit_msg>wrap with Rc<commit_after>
use libc::{c_char};
use std::rc::Rc;

#[repr(C)]
    struct mrb_state;
#[repr(C)]
    struct mrb_value;
#[repr(C)]
    struct RClass;

#[link(name="m")]
#[link(name="mruby")]
extern "C" {

    fn mrb_open() -> *mut mrb_state;
    fn mrb_load_string(state:*mut mrb_state,s:*const c_char) -> mrb_value;
    fn mrb_close(state:*mut mrb_state);
    fn mrb_class_get(state:*mut mrb_state,name:*const c_char) -> *mut RClass;
    fn mrb_define_class(state:*mut mrb_state,name:*const c_char,class:*mut RClass) -> *mut RClass;
}

enum MvalType {
    TypeFalse ,
    TypeFree,
    TypeTrue,
    TypeFixnum,
    TypeSymbol,
    TypeUndef,
    TypeFloat,
    TypeCptr,
    TypeObject,
    TypeClass,
    TypeModule,
    TypeIClass,
    TypeSClass,
    TypeProc,
    TypeArray,
    TypeHash,
    TypeString,
    TypeRange,
    TypeException,
    TypeFile,
    TypeEnv,
    TypeData,
    TypeFiber,
    TypeMaxDefine
}

pub struct Mrb{
    state:Rc<*mut mrb_state>
}
/*
pub struct Value {
    val :*mut mrb_value
}
*/
pub struct Class {
    state:Rc<*mut mrb_state>,
    class:*mut RClass
}

pub fn open() -> Mrb {
    let s = unsafe { mrb_open() } ;
    Mrb{state:Rc::new(s)}
}

impl Mrb {
    pub fn load_str(&self,s:&str) {
        let cs = s.to_c_str();
        unsafe {
            mrb_load_string(*self.state.deref(),cs.as_ptr());
        }
    }

    pub fn define_class(&self,name:&str,clz:&Class) -> Class {
        let cs = name.to_c_str();
        let c = unsafe {
            mrb_define_class(*self.state.deref(),cs.as_ptr(),clz.class)
        };
        Class{state:self.state.clone(),class:c}
    }

    pub fn obj_class(&self) -> Class {
        let s = "Object";
        let c = unsafe {
            mrb_class_get(*self.state.deref(),s.to_c_str().as_ptr())
        };
        Class{state:self.state.clone(),class:c}
    }
}
/*
impl Drop for Mrb {
    fn drop(&mut self) {
        drop(self.state);
        println!("drop mrb");
    }
}
*/

#[test]
fn test_open_class() {
    let m = open();
    let exec = "[1,2,3].each do |i| puts i+1 end";
    m.load_str(exec);

    let exec2 = "[1,2,3].each do |i| puts i+1 end";
    m.load_str(exec2);

    let o = &m.obj_class();
    let c = m.define_class("Hello",o);
}
<|endoftext|>