<commit_before>use std::collections::hash_map::Entry::{Occupied, Vacant};

use failure::{err_msg, Error};
use ggez::{graphics, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};
use warmy::{LogicalKey, Store};

use crate::game::{Game, SceneState};
use crate::input::{Axis, Button, InputEvent};
use crate::objects::TextureAtlas;
use crate::palette::PaletteSwaps;
use crate::piv::{extract_palette, Colour};
use crate::scenes::FSceneSwitch;

use super::menu::Menu;

enum State {
    Selecting,
    Naming,
}

pub struct SelectKnight {
    menu: Menu,
    oscillate: ColourOscillate,
    swap_colour: Colour,

    state: State,

    current: usize,
    selected: Vec<u32>,
    available: Vec<u32>,
}

struct ColourOscillate {
    from: Colour,
    to: Colour,
    current: Colour,
    target: Colour,
}

impl ColourOscillate {
    pub fn new(from: Colour, to: Colour) -> Self {
        ColourOscillate {
            from: from.clone(),
            to: to.clone(),
            current: from.clone(),
            target: to.clone(),
        }
    }
}

impl Iterator for ColourOscillate {
    type Item = Colour;

    fn next(&mut self) -> Option<Self::Item> {
        if self.target.r > self.current.r {
            self.current.r += 16
        } else if self.target.r < self.current.r {
            self.current.r -= 16
        };

        if self.target.g > self.current.g {
            self.current.g += 16
        } else if self.target.g < self.current.g {
            self.current.g -= 16
        };

        if self.target.b > self.current.b {
            self.current.b += 16
        } else if self.target.b < self.current.b {
            self.current.b -= 16
        };

        if self.current == self.target {
            if self.target == self.from {
                self.target = self.to
            } else {
                self.target = self.from
            }
        }
        Some(self.current.clone())
    }
}

impl SelectKnight {
    pub fn new(ctx: &mut Context, store: &mut Store<Context>) -> Result<Self, Error> {
        let menu = Menu::new(ctx, store, "/select_knight.yaml")?;

        let swaps_res = store.get::<_, PaletteSwaps>(&LogicalKey::new("/palettes.yaml"), ctx)?;
        let swaps = swaps_res.borrow();
        let raw_palette = swaps
            .0
            .get("select_knight")
            .ok_or_else(|| err_msg("failed to load select_knight.yaml"))?;
        let mut swap_colour = extract_palette(raw_palette)
            .first()
            .ok_or_else(|| err_msg("select_knight palette does not have a colour defined"))?
            .clone();
        swap_colour.a = 255;

        let original_colour = menu.palette[15].clone();

        let oscillate = ColourOscillate::new(original_colour, swap_colour);

        Ok(Self {
            menu,
            oscillate,
            swap_colour: original_colour.clone(),
            state: State::Selecting,
            current: 0,
            available: vec![0, 1, 2, 3],
            selected: Vec::new(),
        })
    }

    fn draw_cursor(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        let atlas = game
            .store
            .get::<_, TextureAtlas>(&LogicalKey::new(&self.menu.screen.cursor.sheet), ctx)
            // TODO: raise error
            .expect("Couldn't find sel.cel yaml metadata");

        let ggez_image = match game.images.entry(format!(
            "{}-{}-{}-{}",
            self.menu.screen.cursor.sheet,
            self.swap_colour.r,
            self.swap_colour.g,
            self.swap_colour.b
        )) {
            Occupied(i) => i.into_mut(),
            Vacant(i) => {
                let mut palette = self.menu.palette.clone();
                palette[15] = self.swap_colour;

                let atlas_dimension = atlas.borrow().image.width as u32;
                i.insert(graphics::Image::from_rgba8(
                    ctx,
                    atlas_dimension as u16,
                    atlas_dimension as u16,
                    &atlas.borrow().image.to_rgba8(&palette),
                )?)
            }
        };

        let rect = atlas.borrow().rects[self.menu.screen.cursor.image];
        let texture_size = atlas.borrow().image.width as f32;
        let draw_params = graphics::DrawParam {
            src: graphics::Rect {
                x: rect.x as f32 / texture_size,
                y: rect.y as f32 / texture_size,
                w: rect.w as f32 / texture_size,
                h: rect.h as f32 / texture_size,
            },
            dest: graphics::Point2::new(
                self.menu.screen.cursor.x as f32 * 3.0,
                self.menu.screen.cursor.y as f32 * 3.0,
            ),
            scale: graphics::Point2::new(3.0, 3.0),
            ..Default::default()
        };
        graphics::draw_ex(ctx, ggez_image, draw_params)?;

        Ok(())
    }

    fn select_current_knight(&mut self) {
        self.selected.push(self.available.remove(self.current));
        self.menu.screen.images.remove(self.current);

        self.current = 0;
    }
}

impl Scene<Game, InputEvent> for SelectKnight {
    fn update(&mut self, game: &mut Game, _ctx: &mut Context) -> FSceneSwitch {
        if let Some(colour) = self.oscillate.next() {
            self.swap_colour = colour;
        }
        self.menu.screen.cursor.x = self
            .menu
            .screen
            .images
            .iter()
            .map(|i| i.x)
            .nth(self.current)
            .unwrap_or_else(|| self.menu.screen.cursor.x);

        if self.selected.len() == game.num_players as usize {
            SceneSwitch::Pop
        } else {
            SceneSwitch::None
        }
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        graphics::set_background_color(ctx, graphics::Color::from((0, 0, 0, 255)));
        graphics::clear(ctx);
        self.menu.draw(game, ctx);
        self.draw_cursor(game, ctx);
        Ok(())
    }

    fn name(&self) -> &str {
        "Select a Knight"
    }

    fn input(&mut self, gameworld: &mut Game, _event: InputEvent, started: bool) {
        match self.state {
            State::Selecting => {
                let x = gameworld.input.get_axis_raw(Axis::Horz1) as i32;
                let len = self.available.len() as i32;
                if x > 0 {
                    self.current = ((self.current as i32 + x) % len) as usize;
                } else {
                    self.current = ((self.current as i32 + x + len) % len) as usize;
                }

                if gameworld.input.get_button_down(Button::Fire1) {
                    self.select_current_knight();
                }
            }
            State::Naming => (),
        }
    }
}
<commit_msg>ggez-v0.5: update select_knight.rs<commit_after>use std::collections::hash_map::Entry::{Occupied, Vacant};

use failure::{err_msg, Error};
use ggez::nalgebra::{Point2, Vector2};
use ggez::{graphics, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};
use warmy::{LogicalKey, Store};

use crate::game::{Game, SceneState};
use crate::input::{Axis, Button, InputEvent};
use crate::objects::TextureAtlas;
use crate::palette::PaletteSwaps;
use crate::piv::{extract_palette, Colour};
use crate::scenes::FSceneSwitch;

use super::menu::Menu;

enum State {
    Selecting,
    Naming,
}

pub struct SelectKnight {
    menu: Menu,
    oscillate: ColourOscillate,
    swap_colour: Colour,

    state: State,

    current: usize,
    selected: Vec<u32>,
    available: Vec<u32>,
}

struct ColourOscillate {
    from: Colour,
    to: Colour,
    current: Colour,
    target: Colour,
}

impl ColourOscillate {
    pub fn new(from: Colour, to: Colour) -> Self {
        ColourOscillate {
            from: from.clone(),
            to: to.clone(),
            current: from.clone(),
            target: to.clone(),
        }
    }
}

impl Iterator for ColourOscillate {
    type Item = Colour;

    fn next(&mut self) -> Option<Self::Item> {
        if self.target.r > self.current.r {
            self.current.r += 16
        } else if self.target.r < self.current.r {
            self.current.r -= 16
        };

        if self.target.g > self.current.g {
            self.current.g += 16
        } else if self.target.g < self.current.g {
            self.current.g -= 16
        };

        if self.target.b > self.current.b {
            self.current.b += 16
        } else if self.target.b < self.current.b {
            self.current.b -= 16
        };

        if self.current == self.target {
            if self.target == self.from {
                self.target = self.to
            } else {
                self.target = self.from
            }
        }
        Some(self.current.clone())
    }
}

impl SelectKnight {
    pub fn new(ctx: &mut Context, store: &mut Store<Context>) -> Result<Self, Error> {
        let menu = Menu::new(ctx, store, "/select_knight.yaml")?;

        let swaps_res = store.get::<_, PaletteSwaps>(&LogicalKey::new("/palettes.yaml"), ctx)?;
        let swaps = swaps_res.borrow();
        let raw_palette = swaps
            .0
            .get("select_knight")
            .ok_or_else(|| err_msg("failed to load select_knight.yaml"))?;
        let mut swap_colour = extract_palette(raw_palette)
            .first()
            .ok_or_else(|| err_msg("select_knight palette does not have a colour defined"))?
            .clone();
        swap_colour.a = 255;

        let original_colour = menu.palette[15].clone();

        let oscillate = ColourOscillate::new(original_colour, swap_colour);

        Ok(Self {
            menu,
            oscillate,
            swap_colour: original_colour.clone(),
            state: State::Selecting,
            current: 0,
            available: vec![0, 1, 2, 3],
            selected: Vec::new(),
        })
    }

    fn draw_cursor(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        let atlas = game
            .store
            .get::<_, TextureAtlas>(&LogicalKey::new(&self.menu.screen.cursor.sheet), ctx)
            // TODO: raise error
            .expect("Couldn't find sel.cel yaml metadata");

        let ggez_image = match game.images.entry(format!(
            "{}-{}-{}-{}",
            self.menu.screen.cursor.sheet,
            self.swap_colour.r,
            self.swap_colour.g,
            self.swap_colour.b
        )) {
            Occupied(i) => i.into_mut(),
            Vacant(i) => {
                let mut palette = self.menu.palette.clone();
                palette[15] = self.swap_colour;

                let atlas_dimension = atlas.borrow().image.width as u32;
                i.insert(graphics::Image::from_rgba8(
                    ctx,
                    atlas_dimension as u16,
                    atlas_dimension as u16,
                    &atlas.borrow().image.to_rgba8(&palette),
                )?)
            }
        };

        let rect = atlas.borrow().rects[self.menu.screen.cursor.image];
        let texture_size = atlas.borrow().image.width as f32;
        let draw_params = graphics::DrawParam::default()
            .src(graphics::Rect {
                x: rect.x as f32 / texture_size,
                y: rect.y as f32 / texture_size,
                w: rect.w as f32 / texture_size,
                h: rect.h as f32 / texture_size,
            })
            .dest(Point2::new(
                self.menu.screen.cursor.x as f32 * 3.0,
                self.menu.screen.cursor.y as f32 * 3.0,
            ))
            .scale(Vector2::new(3.0, 3.0));
        graphics::draw(ctx, ggez_image, draw_params)?;

        Ok(())
    }

    fn select_current_knight(&mut self) {
        self.selected.push(self.available.remove(self.current));
        self.menu.screen.images.remove(self.current);

        self.current = 0;
    }
}

impl Scene<Game, InputEvent> for SelectKnight {
    fn update(&mut self, game: &mut Game, _ctx: &mut Context) -> FSceneSwitch {
        if let Some(colour) = self.oscillate.next() {
            self.swap_colour = colour;
        }
        self.menu.screen.cursor.x = self
            .menu
            .screen
            .images
            .iter()
            .map(|i| i.x)
            .nth(self.current)
            .unwrap_or_else(|| self.menu.screen.cursor.x);

        if self.selected.len() == game.num_players as usize {
            SceneSwitch::Pop
        } else {
            SceneSwitch::None
        }
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx, graphics::Color::from((0, 0, 0, 255)));
        self.menu.draw(game, ctx);
        self.draw_cursor(game, ctx);
        Ok(())
    }

    fn name(&self) -> &str {
        "Select a Knight"
    }

    fn input(&mut self, gameworld: &mut Game, _event: InputEvent, started: bool) {
        match self.state {
            State::Selecting => {
                let x = gameworld.input.get_axis_raw(Axis::Horz1) as i32;
                let len = self.available.len() as i32;
                if x > 0 {
                    self.current = ((self.current as i32 + x) % len) as usize;
                } else {
                    self.current = ((self.current as i32 + x + len) % len) as usize;
                }

                if gameworld.input.get_button_down(Button::Fire1) {
                    self.select_current_knight();
                }
            }
            State::Naming => (),
        }
    }
}
<|endoftext|>


<commit_before>//! Character conversions.

use crate::convert::TryFrom;
use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;

use super::MAX;

/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid [`char`]:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_u32(i: u32) -> Option<char> {
    char::try_from(i).ok()
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
#[inline]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
    // SAFETY: the caller must guarantee that `i` is a valid char value.
    if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}

#[stable(feature = "char_convert", since = "1.13.0")]
impl From<char> for u32 {
    /// Converts a [`char`] into a [`u32`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = 'c';
    /// let u = u32::from(c);
    /// assert!(4 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        c as u32
    }
}

/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
///
/// Unicode is designed such that this effectively decodes bytes
/// with the character encoding that IANA calls ISO-8859-1.
/// This encoding is compatible with ASCII.
///
/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
/// which leaves some "blanks", byte values that are not assigned to any character.
/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
///
/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
/// to punctuation and various Latin characters.
///
/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
/// C0 and C1 control codes.
#[stable(feature = "char_convert", since = "1.13.0")]
impl From<u8> for char {
    /// Converts a [`u8`] into a [`char`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let u = 32 as u8;
    /// let c = char::from(u);
    /// assert!(4 == mem::size_of_val(&c))
    /// ```
    #[inline]
    fn from(i: u8) -> Self {
        i as char
    }
}

/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseCharError {
    kind: CharErrorKind,
}

impl ParseCharError {
    #[unstable(
        feature = "char_error_internals",
        reason = "this method should not be available publicly",
        issue = "none"
    )]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            CharErrorKind::EmptyString => "cannot parse char from empty string",
            CharErrorKind::TooManyChars => "too many characters in string",
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharErrorKind {
    EmptyString,
    TooManyChars,
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.__description().fmt(f)
    }
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl FromStr for char {
    type Err = ParseCharError;

    #[inline]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut chars = s.chars();
        match (chars.next(), chars.next()) {
            (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
            (Some(c), None) => Ok(c),
            _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
        }
    }
}

#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
    type Error = CharTryFromError;

    #[inline]
    fn try_from(i: u32) -> Result<Self, Self::Error> {
        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
            Err(CharTryFromError(()))
        } else {
            // SAFETY: checked that it's a legal unicode value
            Ok(unsafe { transmute(i) })
        }
    }
}

/// The error type returned when a conversion from u32 to char fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CharTryFromError(());

#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for CharTryFromError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "converted integer out of range for `char`".fmt(f)
    }
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```should_panic
/// use std::char;
///
/// // this panics
/// let c = char::from_digit(1, 37);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
    if radix > 36 {
        panic!("from_digit: radix is too high (maximum 36)");
    }
    if num < radix {
        let num = num as u8;
        if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
    } else {
        None
    }
}
<commit_msg>Add "chr" as doc alias to char::from_u32<commit_after>//! Character conversions.

use crate::convert::TryFrom;
use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;

use super::MAX;

/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid [`char`]:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[doc(alias = "chr")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_u32(i: u32) -> Option<char> {
    char::try_from(i).ok()
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
#[inline]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
    // SAFETY: the caller must guarantee that `i` is a valid char value.
    if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}

#[stable(feature = "char_convert", since = "1.13.0")]
impl From<char> for u32 {
    /// Converts a [`char`] into a [`u32`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = 'c';
    /// let u = u32::from(c);
    /// assert!(4 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        c as u32
    }
}

/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
///
/// Unicode is designed such that this effectively decodes bytes
/// with the character encoding that IANA calls ISO-8859-1.
/// This encoding is compatible with ASCII.
///
/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
/// which leaves some "blanks", byte values that are not assigned to any character.
/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
///
/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
/// to punctuation and various Latin characters.
///
/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
/// C0 and C1 control codes.
#[stable(feature = "char_convert", since = "1.13.0")]
impl From<u8> for char {
    /// Converts a [`u8`] into a [`char`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let u = 32 as u8;
    /// let c = char::from(u);
    /// assert!(4 == mem::size_of_val(&c))
    /// ```
    #[inline]
    fn from(i: u8) -> Self {
        i as char
    }
}

/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseCharError {
    kind: CharErrorKind,
}

impl ParseCharError {
    #[unstable(
        feature = "char_error_internals",
        reason = "this method should not be available publicly",
        issue = "none"
    )]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            CharErrorKind::EmptyString => "cannot parse char from empty string",
            CharErrorKind::TooManyChars => "too many characters in string",
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharErrorKind {
    EmptyString,
    TooManyChars,
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.__description().fmt(f)
    }
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl FromStr for char {
    type Err = ParseCharError;

    #[inline]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut chars = s.chars();
        match (chars.next(), chars.next()) {
            (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
            (Some(c), None) => Ok(c),
            _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
        }
    }
}

#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
    type Error = CharTryFromError;

    #[inline]
    fn try_from(i: u32) -> Result<Self, Self::Error> {
        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
            Err(CharTryFromError(()))
        } else {
            // SAFETY: checked that it's a legal unicode value
            Ok(unsafe { transmute(i) })
        }
    }
}

/// The error type returned when a conversion from u32 to char fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CharTryFromError(());

#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for CharTryFromError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "converted integer out of range for `char`".fmt(f)
    }
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```should_panic
/// use std::char;
///
/// // this panics
/// let c = char::from_digit(1, 37);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
    if radix > 36 {
        panic!("from_digit: radix is too high (maximum 36)");
    }
    if num < radix {
        let num = num as u8;
        if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
    } else {
        None
    }
}
<|endoftext|>


<commit_before>//! Character conversions.

use crate::convert::TryFrom;
use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;

use super::MAX;

/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid [`char`]:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_u32(i: u32) -> Option<char> {
    char::try_from(i).ok()
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
#[inline]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
    // SAFETY: the caller must guarantee that `i` is a valid char value.
    if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}

#[stable(feature = "char_convert", since = "1.13.0")]
impl From<char> for u32 {
    /// Converts a [`char`] into a [`u32`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = 'c';
    /// let u = u32::from(c);
    /// assert!(4 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        c as u32
    }
}

/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
///
/// Unicode is designed such that this effectively decodes bytes
/// with the character encoding that IANA calls ISO-8859-1.
/// This encoding is compatible with ASCII.
///
/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
/// which leaves some "blanks", byte values that are not assigned to any character.
/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
///
/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
/// to punctuation and various Latin characters.
///
/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
/// C0 and C1 control codes.
#[stable(feature = "char_convert", since = "1.13.0")]
impl From<u8> for char {
    /// Converts a [`u8`] into a [`char`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let u = 32 as u8;
    /// let c = char::from(u);
    /// assert!(4 == mem::size_of_val(&c))
    /// ```
    #[inline]
    fn from(i: u8) -> Self {
        i as char
    }
}

/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseCharError {
    kind: CharErrorKind,
}

impl ParseCharError {
    #[unstable(
        feature = "char_error_internals",
        reason = "this method should not be available publicly",
        issue = "none"
    )]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            CharErrorKind::EmptyString => "cannot parse char from empty string",
            CharErrorKind::TooManyChars => "too many characters in string",
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharErrorKind {
    EmptyString,
    TooManyChars,
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.__description().fmt(f)
    }
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl FromStr for char {
    type Err = ParseCharError;

    #[inline]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut chars = s.chars();
        match (chars.next(), chars.next()) {
            (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
            (Some(c), None) => Ok(c),
            _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
        }
    }
}

#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
    type Error = CharTryFromError;

    #[inline]
    fn try_from(i: u32) -> Result<Self, Self::Error> {
        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
            Err(CharTryFromError(()))
        } else {
            // SAFETY: checked that it's a legal unicode value
            Ok(unsafe { transmute(i) })
        }
    }
}

/// The error type returned when a conversion from u32 to char fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CharTryFromError(());

#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for CharTryFromError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "converted integer out of range for `char`".fmt(f)
    }
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```should_panic
/// use std::char;
///
/// // this panics
/// let c = char::from_digit(1, 37);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
    if radix > 36 {
        panic!("from_digit: radix is too high (maximum 36)");
    }
    if num < radix {
        let num = num as u8;
        if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
    } else {
        None
    }
}
<commit_msg>Implement From<char> for u64 and u128.<commit_after>//! Character conversions.

use crate::convert::TryFrom;
use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;

use super::MAX;

/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid [`char`]:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_u32(i: u32) -> Option<char> {
    char::try_from(i).ok()
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
#[inline]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
    // SAFETY: the caller must guarantee that `i` is a valid char value.
    if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}

#[stable(feature = "char_convert", since = "1.13.0")]
impl From<char> for u32 {
    /// Converts a [`char`] into a [`u32`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = 'c';
    /// let u = u32::from(c);
    /// assert!(4 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        c as u32
    }
}

#[stable(feature = "more_char_conversions", since = "1.50.0")]
impl From<char> for u64 {
    /// Converts a [`char`] into a [`u64`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = '👤';
    /// let u = u64::from(c);
    /// assert!(8 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        // The char is casted to the value of the code point, then zero-extended to 64 bit.
        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
        c as u64
    }
}

#[stable(feature = "more_char_conversions", since = "1.50.0")]
impl From<char> for u128 {
    /// Converts a [`char`] into a [`u128`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let c = '⚙';
    /// let u = u128::from(c);
    /// assert!(16 == mem::size_of_val(&u))
    /// ```
    #[inline]
    fn from(c: char) -> Self {
        // The char is casted to the value of the code point, then zero-extended to 128 bit.
        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
        c as u128
    }
}

/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
///
/// Unicode is designed such that this effectively decodes bytes
/// with the character encoding that IANA calls ISO-8859-1.
/// This encoding is compatible with ASCII.
///
/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
/// which leaves some "blanks", byte values that are not assigned to any character.
/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
///
/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
/// to punctuation and various Latin characters.
///
/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
/// C0 and C1 control codes.
#[stable(feature = "char_convert", since = "1.13.0")]
impl From<u8> for char {
    /// Converts a [`u8`] into a [`char`].
    ///
    /// # Examples
    ///
    /// ```
    /// use std::mem;
    ///
    /// let u = 32 as u8;
    /// let c = char::from(u);
    /// assert!(4 == mem::size_of_val(&c))
    /// ```
    #[inline]
    fn from(i: u8) -> Self {
        i as char
    }
}

/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseCharError {
    kind: CharErrorKind,
}

impl ParseCharError {
    #[unstable(
        feature = "char_error_internals",
        reason = "this method should not be available publicly",
        issue = "none"
    )]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            CharErrorKind::EmptyString => "cannot parse char from empty string",
            CharErrorKind::TooManyChars => "too many characters in string",
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharErrorKind {
    EmptyString,
    TooManyChars,
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.__description().fmt(f)
    }
}

#[stable(feature = "char_from_str", since = "1.20.0")]
impl FromStr for char {
    type Err = ParseCharError;

    #[inline]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut chars = s.chars();
        match (chars.next(), chars.next()) {
            (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
            (Some(c), None) => Ok(c),
            _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
        }
    }
}

#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
    type Error = CharTryFromError;

    #[inline]
    fn try_from(i: u32) -> Result<Self, Self::Error> {
        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
            Err(CharTryFromError(()))
        } else {
            // SAFETY: checked that it's a legal unicode value
            Ok(unsafe { transmute(i) })
        }
    }
}

/// The error type returned when a conversion from u32 to char fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CharTryFromError(());

#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for CharTryFromError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "converted integer out of range for `char`".fmt(f)
    }
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```should_panic
/// use std::char;
///
/// // this panics
/// let c = char::from_digit(1, 37);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
    if radix > 36 {
        panic!("from_digit: radix is too high (maximum 36)");
    }
    if num < radix {
        let num = num as u8;
        if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
    } else {
        None
    }
}
<|endoftext|>


<commit_before>extern crate pythagorean_triplet;

use pythagorean_triplet::find;
use std::{collections::HashSet, iter::FromIterator};

fn process_tripletswithsum_case(sum: u32, expected: Vec<[u32; 3]>) {
    let triplets = find(sum);

    if !expected.is_empty() {
        let expected = HashSet::from_iter(expected.iter().cloned());

        assert_eq!(expected, triplets);
    } else {
        assert!(triplets.is_empty());
    }
}

#[test]
fn test_triplets_whose_sum_is_12() {
    process_tripletswithsum_case(12, vec![[3, 4, 5]]);
}

#[test]
#[ignore]
fn test_triplets_whose_sum_is_108() {
    process_tripletswithsum_case(108, vec![[27, 36, 45]]);
}

#[test]
#[ignore]
fn test_triplets_whose_sum_is_1000() {
    process_tripletswithsum_case(1000, vec![[200, 375, 425]]);
}

#[test]
#[ignore]
fn test_no_matching_triplets_for_1001() {
    process_tripletswithsum_case(1001, vec![]);
}

#[test]
#[ignore]
fn test_returns_all_matching_triplets() {
    process_tripletswithsum_case(90, vec![[9, 40, 41], [15, 36, 39]]);
}

#[test]
#[ignore]
fn test_several_matching_triplets() {
    process_tripletswithsum_case(
        840,
        vec![
            [40, 399, 401],
            [56, 390, 394],
            [105, 360, 375],
            [120, 350, 370],
            [140, 336, 364],
            [168, 315, 357],
            [210, 280, 350],
            [240, 252, 348],
        ],
    );
}

#[test]
#[ignore]
fn test_triplets_for_large_number() {
    process_tripletswithsum_case(
        30000,
        vec![
            [1200, 14375, 14425],
            [1875, 14000, 14125],
            [5000, 12000, 13000],
            [6000, 11250, 12750],
            [7500, 10000, 12500],
        ],
    );
}
<commit_msg>pythagorean-triplet: Use `&[[u32; 3]]` not `Vec<[u32; 3]>`<commit_after>extern crate pythagorean_triplet;

use pythagorean_triplet::find;
use std::{collections::HashSet, iter::FromIterator};

fn process_tripletswithsum_case(sum: u32, expected: &[[u32; 3]]) {
    let triplets = find(sum);

    if !expected.is_empty() {
        let expected = HashSet::from_iter(expected.iter().cloned());

        assert_eq!(expected, triplets);
    } else {
        assert!(triplets.is_empty());
    }
}

#[test]
fn test_triplets_whose_sum_is_12() {
    process_tripletswithsum_case(12, &[[3, 4, 5]]);
}

#[test]
#[ignore]
fn test_triplets_whose_sum_is_108() {
    process_tripletswithsum_case(108, &[[27, 36, 45]]);
}

#[test]
#[ignore]
fn test_triplets_whose_sum_is_1000() {
    process_tripletswithsum_case(1000, &[[200, 375, 425]]);
}

#[test]
#[ignore]
fn test_no_matching_triplets_for_1001() {
    process_tripletswithsum_case(1001, &[]);
}

#[test]
#[ignore]
fn test_returns_all_matching_triplets() {
    process_tripletswithsum_case(90, &[[9, 40, 41], [15, 36, 39]]);
}

#[test]
#[ignore]
fn test_several_matching_triplets() {
    process_tripletswithsum_case(
        840,
        &[
            [40, 399, 401],
            [56, 390, 394],
            [105, 360, 375],
            [120, 350, 370],
            [140, 336, 364],
            [168, 315, 357],
            [210, 280, 350],
            [240, 252, 348],
        ],
    );
}

#[test]
#[ignore]
fn test_triplets_for_large_number() {
    process_tripletswithsum_case(
        30000,
        &[
            [1200, 14375, 14425],
            [1875, 14000, 14125],
            [5000, 12000, 13000],
            [6000, 11250, 12750],
            [7500, 10000, 12500],
        ],
    );
}
<|endoftext|>


<commit_before>use std::env::var_os;

use getopts;

use output::Colours;
use output::{Grid, Details, GridDetails};
use output::column::{Columns, TimeTypes, SizeFormat};
use output::file_name::Classify;
use options::{FileFilter, DirAction, Misfire};
use fs::feature::xattr;

/// The **view** contains all information about how to format output.
#[derive(PartialEq, Debug, Clone)]
pub struct View {
    pub mode: Mode,
    pub colours: Colours,
    pub classify: Classify,
}

impl View {

    /// Determine which view to use and all of that view’s arguments.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<View, Misfire> {
        let (mode, colours) = Mode::deduce(matches, filter, dir_action)?;
        let classify = Classify::deduce(matches);
        Ok(View { mode, colours, classify })
    }
}

/// The **mode** is the “type” of output.
#[derive(PartialEq, Debug, Clone)]
pub enum Mode {
    Details(Details),
    Grid(Grid),
    GridDetails(GridDetails),
    Lines,
}

impl Mode {

    /// Determine both the mode and the colours at the same time.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<(Mode, Colours), Misfire> {
        use options::misfire::Misfire::*;

        let long = || {
            if matches.opt_present("across") && !matches.opt_present("grid") {
                Err(Useless("across", true, "long"))
            }
            else if matches.opt_present("oneline") {
                Err(Useless("oneline", true, "long"))
            }
            else {
                let colours = Colours::deduce(matches)?;

                let details = Details {
                    columns: Some(Columns::deduce(matches)?),
                    header: matches.opt_present("header"),
                    recurse: dir_action.recurse_options(),
                    filter: filter.clone(),
                    xattr: xattr::ENABLED && matches.opt_present("extended"),
                };

                Ok((Mode::Details(details), colours))
            }
        };

        let long_options_scan = || {
            for option in &[ "binary", "bytes", "inode", "links", "header", "blocks", "time", "group" ] {
                if matches.opt_present(option) {
                    return Err(Useless(option, false, "long"));
                }
            }

            if cfg!(feature="git") && matches.opt_present("git") {
                Err(Useless("git", false, "long"))
            }
            else if matches.opt_present("level") && !matches.opt_present("recurse") && !matches.opt_present("tree") {
                Err(Useless2("level", "recurse", "tree"))
            }
            else if xattr::ENABLED && matches.opt_present("extended") {
                Err(Useless("extended", false, "long"))
            }
            else {
                Ok(())
            }
        };

        let other_options_scan = || {
            if let Some(width) = TerminalWidth::deduce()?.width() {
                let colours = Colours::deduce(matches)?;

                if matches.opt_present("oneline") {
                    if matches.opt_present("across") {
                        Err(Useless("across", true, "oneline"))
                    }
                    else {
                        Ok((Mode::Lines, colours))
                    }
                }
                else if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),  // TODO: clone
                        xattr: false,
                    };

                    Ok((Mode::Details(details), colours))
                }
                else {
                    let grid = Grid {
                        across: matches.opt_present("across"),
                        console_width: width,
                    };

                    Ok((Mode::Grid(grid), colours))
                }
            }
            else {
                // If the terminal width couldn’t be matched for some reason, such
                // as the program’s stdout being connected to a file, then
                // fallback to the lines view.

                let colours = Colours::deduce(matches)?;

                if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),
                        xattr: false,
                    };

                    Ok((Mode::Details(details), colours))
                }
                else {
                    Ok((Mode::Lines, colours))
                }
            }
        };

        if matches.opt_present("long") {
            let view = long()?;
            if matches.opt_present("grid") {
                if let (Mode::Details(details), _) = view {
                    let others = other_options_scan()?;
                    match others.0 {
                        Mode::Grid(grid) => return Ok((Mode::GridDetails(GridDetails { grid, details }), others.1 )),
                        _                => return Ok(others),
                    };
                }
                else {
                    unreachable!()
                }
            }
            else {
                return Ok(view);
            }
        }

        long_options_scan()?;

        other_options_scan()
    }
}

/// The width of the terminal requested by the user.
#[derive(PartialEq, Debug)]
enum TerminalWidth {

    /// The user requested this specific number of columns.
    Set(usize),

    /// The terminal was found to have this number of columns.
    Terminal(usize),

    /// The user didn’t request any particular terminal width.
    Unset,
}

impl TerminalWidth {

    /// Determine a requested terminal width from the command-line arguments.
    ///
    /// Returns an error if a requested width doesn’t parse to an integer.
    fn deduce() -> Result<TerminalWidth, Misfire> {
        if let Some(columns) = var_os("COLUMNS").and_then(|s| s.into_string().ok()) {
            match columns.parse() {
                Ok(width)  => Ok(TerminalWidth::Set(width)),
                Err(e)     => Err(Misfire::FailedParse(e)),
            }
        }
        else if let Some(width) = *TERM_WIDTH {
            Ok(TerminalWidth::Terminal(width))
        }
        else {
            Ok(TerminalWidth::Unset)
        }
    }

    fn width(&self) -> Option<usize> {
        match *self {
            TerminalWidth::Set(width)       |
            TerminalWidth::Terminal(width)  => Some(width),
            TerminalWidth::Unset            => None,
        }
    }
}

impl Columns {
    fn deduce(matches: &getopts::Matches) -> Result<Columns, Misfire> {
        Ok(Columns {
            size_format: SizeFormat::deduce(matches)?,
            time_types:  TimeTypes::deduce(matches)?,
            inode:  matches.opt_present("inode"),
            links:  matches.opt_present("links"),
            blocks: matches.opt_present("blocks"),
            group:  matches.opt_present("group"),
            git:    cfg!(feature="git") && matches.opt_present("git"),
        })
    }
}

impl SizeFormat {

    /// Determine which file size to use in the file size column based on
    /// the user’s options.
    ///
    /// The default mode is to use the decimal prefixes, as they are the
    /// most commonly-understood, and don’t involve trying to parse large
    /// strings of digits in your head. Changing the format to anything else
    /// involves the `--binary` or `--bytes` flags, and these conflict with
    /// each other.
    fn deduce(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
        let binary = matches.opt_present("binary");
        let bytes  = matches.opt_present("bytes");

        match (binary, bytes) {
            (true,  true )  => Err(Misfire::Conflict("binary", "bytes")),
            (true,  false)  => Ok(SizeFormat::BinaryBytes),
            (false, true )  => Ok(SizeFormat::JustBytes),
            (false, false)  => Ok(SizeFormat::DecimalBytes),
        }
    }
}

impl TimeTypes {

    /// Determine which of a file’s time fields should be displayed for it
    /// based on the user’s options.
    ///
    /// There are two separate ways to pick which fields to show: with a
    /// flag (such as `--modified`) or with a parameter (such as
    /// `--time=modified`). An error is signaled if both ways are used.
    ///
    /// It’s valid to show more than one column by passing in more than one
    /// option, but passing *no* options means that the user just wants to
    /// see the default set.
    fn deduce(matches: &getopts::Matches) -> Result<TimeTypes, Misfire> {
        let possible_word = matches.opt_str("time");
        let modified = matches.opt_present("modified");
        let created  = matches.opt_present("created");
        let accessed = matches.opt_present("accessed");

        if let Some(word) = possible_word {
            if modified {
                return Err(Misfire::Useless("modified", true, "time"));
            }
            else if created {
                return Err(Misfire::Useless("created", true, "time"));
            }
            else if accessed {
                return Err(Misfire::Useless("accessed", true, "time"));
            }

            static TIMES: &[& str] = &["modified", "accessed", "created"];
            match &*word {
                "mod" | "modified"  => Ok(TimeTypes { accessed: false, modified: true,  created: false }),
                "acc" | "accessed"  => Ok(TimeTypes { accessed: true,  modified: false, created: false }),
                "cr"  | "created"   => Ok(TimeTypes { accessed: false, modified: false, created: true  }),
                otherwise           => Err(Misfire::bad_argument("time", otherwise, TIMES))
            }
        }
        else if modified || created || accessed {
            Ok(TimeTypes { accessed, modified, created })
        }
        else {
            Ok(TimeTypes::default())
        }
    }
}

/// Under what circumstances we should display coloured, rather than plain,
/// output to the terminal.
///
/// By default, we want to display the colours when stdout can display them.
/// Turning them on when output is going to, say, a pipe, would make programs
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
/// this check and only displays colours when they can be truly appreciated.
#[derive(PartialEq, Debug)]
enum TerminalColours {

    /// Display them even when output isn’t going to a terminal.
    Always,

    /// Display them when output is going to a terminal, but not otherwise.
    Automatic,

    /// Never display them, even when output is going to a terminal.
    Never,
}

impl Default for TerminalColours {
    fn default() -> TerminalColours {
        TerminalColours::Automatic
    }
}

impl TerminalColours {

    /// Determine which terminal colour conditions to use.
    fn deduce(matches: &getopts::Matches) -> Result<TerminalColours, Misfire> {
        const COLOURS: &[&str] = &["always", "auto", "never"];

        if let Some(word) = matches.opt_str("color").or_else(|| matches.opt_str("colour")) {
            match &*word {
                "always"              => Ok(TerminalColours::Always),
                "auto" | "automatic"  => Ok(TerminalColours::Automatic),
                "never"               => Ok(TerminalColours::Never),
                otherwise             => Err(Misfire::bad_argument("color", otherwise, COLOURS))
            }
        }
        else {
            Ok(TerminalColours::default())
        }
    }
}

impl Colours {
    fn deduce(matches: &getopts::Matches) -> Result<Colours, Misfire> {
        use self::TerminalColours::*;

        let tc = TerminalColours::deduce(matches)?;
        if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
            let scale = matches.opt_present("color-scale") || matches.opt_present("colour-scale");
            Ok(Colours::colourful(scale))
        }
        else {
            Ok(Colours::plain())
        }
    }
}

impl Classify {
    fn deduce(matches: &getopts::Matches) -> Classify {
        if matches.opt_present("classify") { Classify::AddFileIndicators }
                                      else { Classify::JustFilenames }
    }
}

// Gets, then caches, the width of the terminal that exa is running in.
// This gets used multiple times above, with no real guarantee of order,
// so it’s easier to just cache it the first time it runs.
lazy_static! {
    static ref TERM_WIDTH: Option<usize> = {
        use term::dimensions;
        dimensions().map(|t| t.0)
    };
}
<commit_msg>Separate colours from mode deduction<commit_after>use std::env::var_os;

use getopts;

use output::Colours;
use output::{Grid, Details, GridDetails};
use output::column::{Columns, TimeTypes, SizeFormat};
use output::file_name::Classify;
use options::{FileFilter, DirAction, Misfire};
use fs::feature::xattr;

/// The **view** contains all information about how to format output.
#[derive(PartialEq, Debug, Clone)]
pub struct View {
    pub mode: Mode,
    pub colours: Colours,
    pub classify: Classify,
}

impl View {

    /// Determine which view to use and all of that view’s arguments.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<View, Misfire> {
        let mode     = Mode::deduce(matches, filter, dir_action)?;
        let colours  = Colours::deduce(matches)?;
        let classify = Classify::deduce(matches);
        Ok(View { mode, colours, classify })
    }
}

/// The **mode** is the “type” of output.
#[derive(PartialEq, Debug, Clone)]
pub enum Mode {
    Details(Details),
    Grid(Grid),
    GridDetails(GridDetails),
    Lines,
}

impl Mode {

    /// Determine the mode from the command-line arguments.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<Mode, Misfire> {
        use options::misfire::Misfire::*;

        let long = || {
            if matches.opt_present("across") && !matches.opt_present("grid") {
                Err(Useless("across", true, "long"))
            }
            else if matches.opt_present("oneline") {
                Err(Useless("oneline", true, "long"))
            }
            else {
                let details = Details {
                    columns: Some(Columns::deduce(matches)?),
                    header: matches.opt_present("header"),
                    recurse: dir_action.recurse_options(),
                    filter: filter.clone(),
                    xattr: xattr::ENABLED && matches.opt_present("extended"),
                };

                Ok(Mode::Details(details))
            }
        };

        let long_options_scan = || {
            for option in &[ "binary", "bytes", "inode", "links", "header", "blocks", "time", "group" ] {
                if matches.opt_present(option) {
                    return Err(Useless(option, false, "long"));
                }
            }

            if cfg!(feature="git") && matches.opt_present("git") {
                Err(Useless("git", false, "long"))
            }
            else if matches.opt_present("level") && !matches.opt_present("recurse") && !matches.opt_present("tree") {
                Err(Useless2("level", "recurse", "tree"))
            }
            else if xattr::ENABLED && matches.opt_present("extended") {
                Err(Useless("extended", false, "long"))
            }
            else {
                Ok(())
            }
        };

        let other_options_scan = || {
            if let Some(width) = TerminalWidth::deduce()?.width() {
                if matches.opt_present("oneline") {
                    if matches.opt_present("across") {
                        Err(Useless("across", true, "oneline"))
                    }
                    else {
                        Ok(Mode::Lines)
                    }
                }
                else if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),  // TODO: clone
                        xattr: false,
                    };

                    Ok(Mode::Details(details))
                }
                else {
                    let grid = Grid {
                        across: matches.opt_present("across"),
                        console_width: width,
                    };

                    Ok(Mode::Grid(grid))
                }
            }
            else {
                // If the terminal width couldn’t be matched for some reason, such
                // as the program’s stdout being connected to a file, then
                // fallback to the lines view.

                if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),
                        xattr: false,
                    };

                    Ok(Mode::Details(details))
                }
                else {
                    Ok(Mode::Lines)
                }
            }
        };

        if matches.opt_present("long") {
            let view = long()?;
            if matches.opt_present("grid") {
                if let Mode::Details(details) = view {
                    let others = other_options_scan()?;
                    match others {
                        Mode::Grid(grid) => return Ok(Mode::GridDetails(GridDetails { grid, details })),
                        _                => return Ok(others),
                    };
                }
                else {
                    unreachable!()
                }
            }
            else {
                return Ok(view);
            }
        }

        long_options_scan()?;

        other_options_scan()
    }
}

/// The width of the terminal requested by the user.
#[derive(PartialEq, Debug)]
enum TerminalWidth {

    /// The user requested this specific number of columns.
    Set(usize),

    /// The terminal was found to have this number of columns.
    Terminal(usize),

    /// The user didn’t request any particular terminal width.
    Unset,
}

impl TerminalWidth {

    /// Determine a requested terminal width from the command-line arguments.
    ///
    /// Returns an error if a requested width doesn’t parse to an integer.
    fn deduce() -> Result<TerminalWidth, Misfire> {
        if let Some(columns) = var_os("COLUMNS").and_then(|s| s.into_string().ok()) {
            match columns.parse() {
                Ok(width)  => Ok(TerminalWidth::Set(width)),
                Err(e)     => Err(Misfire::FailedParse(e)),
            }
        }
        else if let Some(width) = *TERM_WIDTH {
            Ok(TerminalWidth::Terminal(width))
        }
        else {
            Ok(TerminalWidth::Unset)
        }
    }

    fn width(&self) -> Option<usize> {
        match *self {
            TerminalWidth::Set(width)       |
            TerminalWidth::Terminal(width)  => Some(width),
            TerminalWidth::Unset            => None,
        }
    }
}

impl Columns {
    fn deduce(matches: &getopts::Matches) -> Result<Columns, Misfire> {
        Ok(Columns {
            size_format: SizeFormat::deduce(matches)?,
            time_types:  TimeTypes::deduce(matches)?,
            inode:  matches.opt_present("inode"),
            links:  matches.opt_present("links"),
            blocks: matches.opt_present("blocks"),
            group:  matches.opt_present("group"),
            git:    cfg!(feature="git") && matches.opt_present("git"),
        })
    }
}

impl SizeFormat {

    /// Determine which file size to use in the file size column based on
    /// the user’s options.
    ///
    /// The default mode is to use the decimal prefixes, as they are the
    /// most commonly-understood, and don’t involve trying to parse large
    /// strings of digits in your head. Changing the format to anything else
    /// involves the `--binary` or `--bytes` flags, and these conflict with
    /// each other.
    fn deduce(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
        let binary = matches.opt_present("binary");
        let bytes  = matches.opt_present("bytes");

        match (binary, bytes) {
            (true,  true )  => Err(Misfire::Conflict("binary", "bytes")),
            (true,  false)  => Ok(SizeFormat::BinaryBytes),
            (false, true )  => Ok(SizeFormat::JustBytes),
            (false, false)  => Ok(SizeFormat::DecimalBytes),
        }
    }
}

impl TimeTypes {

    /// Determine which of a file’s time fields should be displayed for it
    /// based on the user’s options.
    ///
    /// There are two separate ways to pick which fields to show: with a
    /// flag (such as `--modified`) or with a parameter (such as
    /// `--time=modified`). An error is signaled if both ways are used.
    ///
    /// It’s valid to show more than one column by passing in more than one
    /// option, but passing *no* options means that the user just wants to
    /// see the default set.
    fn deduce(matches: &getopts::Matches) -> Result<TimeTypes, Misfire> {
        let possible_word = matches.opt_str("time");
        let modified = matches.opt_present("modified");
        let created  = matches.opt_present("created");
        let accessed = matches.opt_present("accessed");

        if let Some(word) = possible_word {
            if modified {
                return Err(Misfire::Useless("modified", true, "time"));
            }
            else if created {
                return Err(Misfire::Useless("created", true, "time"));
            }
            else if accessed {
                return Err(Misfire::Useless("accessed", true, "time"));
            }

            static TIMES: &[& str] = &["modified", "accessed", "created"];
            match &*word {
                "mod" | "modified"  => Ok(TimeTypes { accessed: false, modified: true,  created: false }),
                "acc" | "accessed"  => Ok(TimeTypes { accessed: true,  modified: false, created: false }),
                "cr"  | "created"   => Ok(TimeTypes { accessed: false, modified: false, created: true  }),
                otherwise           => Err(Misfire::bad_argument("time", otherwise, TIMES))
            }
        }
        else if modified || created || accessed {
            Ok(TimeTypes { accessed, modified, created })
        }
        else {
            Ok(TimeTypes::default())
        }
    }
}

/// Under what circumstances we should display coloured, rather than plain,
/// output to the terminal.
///
/// By default, we want to display the colours when stdout can display them.
/// Turning them on when output is going to, say, a pipe, would make programs
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
/// this check and only displays colours when they can be truly appreciated.
#[derive(PartialEq, Debug)]
enum TerminalColours {

    /// Display them even when output isn’t going to a terminal.
    Always,

    /// Display them when output is going to a terminal, but not otherwise.
    Automatic,

    /// Never display them, even when output is going to a terminal.
    Never,
}

impl Default for TerminalColours {
    fn default() -> TerminalColours {
        TerminalColours::Automatic
    }
}

impl TerminalColours {

    /// Determine which terminal colour conditions to use.
    fn deduce(matches: &getopts::Matches) -> Result<TerminalColours, Misfire> {
        const COLOURS: &[&str] = &["always", "auto", "never"];

        if let Some(word) = matches.opt_str("color").or_else(|| matches.opt_str("colour")) {
            match &*word {
                "always"              => Ok(TerminalColours::Always),
                "auto" | "automatic"  => Ok(TerminalColours::Automatic),
                "never"               => Ok(TerminalColours::Never),
                otherwise             => Err(Misfire::bad_argument("color", otherwise, COLOURS))
            }
        }
        else {
            Ok(TerminalColours::default())
        }
    }
}

impl Colours {
    fn deduce(matches: &getopts::Matches) -> Result<Colours, Misfire> {
        use self::TerminalColours::*;

        let tc = TerminalColours::deduce(matches)?;
        if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
            let scale = matches.opt_present("color-scale") || matches.opt_present("colour-scale");
            Ok(Colours::colourful(scale))
        }
        else {
            Ok(Colours::plain())
        }
    }
}

impl Classify {
    fn deduce(matches: &getopts::Matches) -> Classify {
        if matches.opt_present("classify") { Classify::AddFileIndicators }
                                      else { Classify::JustFilenames }
    }
}

// Gets, then caches, the width of the terminal that exa is running in.
// This gets used multiple times above, with no real guarantee of order,
// so it’s easier to just cache it the first time it runs.
lazy_static! {
    static ref TERM_WIDTH: Option<usize> = {
        use term::dimensions;
        dimensions().map(|t| t.0)
    };
}
<|endoftext|>


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

#![allow(non_snake_case)]

register_long_diagnostics! {

E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
making them impossible to tell apart.

```
// Good.
enum Enum {
    P,
    X = 3,
    Y = 5
}

// Bad.
enum Enum {
    P = 3,
    X = 3,
    Y = 5
}
```

Note that variants without a manually specified discriminant are numbered from
top to bottom starting from 0, so clashes can occur with seemingly unrelated
variants.

```
enum Bad {
    X,
    Y = 0
}
```

Here `X` will have already been assigned the discriminant 0 by the time `Y` is
encountered, so a conflict occurs.
"##,

E0082: r##"
The default type for enum discriminants is `isize`, but it can be adjusted by
adding the `repr` attribute to the enum declaration. This error indicates that
an integer literal given as a discriminant is not a member of the discriminant
type. For example:

```
#[repr(u8)]
enum Thing {
    A = 1024,
    B = 5
}
```

Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
invalid. You may want to change representation types to fix this, or else change
invalid discriminant values so that they fit within the existing type.

Note also that without a representation manually defined, the compiler will
optimize by using the smallest integer type possible.
"##,

E0083: r##"
At present, it's not possible to define a custom representation for an enum with
a single variant. As a workaround you can add a `Dummy` variant.

See: https://github.com/rust-lang/rust/issues/10292
"##,

E0084: r##"
It is impossible to define an integer type to be used to represent zero-variant
enum values because there are no zero-variant enum values. There is no way to
construct an instance of the following type using only safe code:

```
enum Empty {}
```
"##

}

register_diagnostics! {
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0029,
    E0030,
    E0031,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0040, // explicit use of destructor method
    E0044,
    E0045,
    E0046,
    E0049,
    E0050,
    E0053,
    E0054,
    E0055,
    E0057,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0101,
    E0102,
    E0103,
    E0104,
    E0106,
    E0107,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0123,
    E0124,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0141,
    E0159,
    E0163,
    E0164,
    E0166,
    E0167,
    E0168,
    E0172,
    E0173, // manual implementations of unboxed closure traits are experimental
    E0174, // explicit use of unboxed closure methods are experimental
    E0178,
    E0182,
    E0183,
    E0184,
    E0185,
    E0186,
    E0187, // can't infer the kind of the closure
    E0188, // types differ in mutability
    E0189, // can only cast a boxed pointer to a boxed object
    E0190, // can only cast a &-pointer to an &-object
    E0191, // value of the associated type must be specified
    E0192, // negative imples are allowed just for `Send` and `Sync`
    E0193, // cannot bound type where clause bounds may only be attached to types
           // involving type parameters
    E0194,
    E0195, // lifetime parameters or bounds on method do not match the trait declaration
    E0196, // cannot determine a type for this closure
    E0197, // inherent impls cannot be declared as unsafe
    E0198, // negative implementations are not unsafe
    E0199, // implementing trait is not unsafe
    E0200, // trait requires an `unsafe impl` declaration
    E0201, // duplicate method in trait impl
    E0202, // associated items are not allowed in inherent impls
    E0203, // type parameter has more than one relaxed default bound,
           // and only one is supported
    E0204, // trait `Copy` may not be implemented for this type; field
           // does not implement `Copy`
    E0205, // trait `Copy` may not be implemented for this type; variant
           // does not implement `copy`
    E0206, // trait `Copy` may not be implemented for this type; type is
           // not a structure or enumeration
    E0207, // type parameter is not constrained by the impl trait, self type, or predicate
    E0208,
    E0209, // builtin traits can only be implemented on structs or enums
    E0210, // type parameter is not constrained by any local type
    E0211,
    E0212, // cannot extract an associated type from a higher-ranked trait bound
    E0213, // associated types are not accepted in this context
    E0214, // parenthesized parameters may only be used with a trait
    E0215, // angle-bracket notation is not stable with `Fn`
    E0216, // parenthetical notation is only stable with `Fn`
    E0217, // ambiguous associated type, defined in multiple supertraits
    E0218, // no associated type defined
    E0219, // associated type defined in higher-ranked supertrait
    E0220, // associated type not found for type parameter
    E0221, // ambiguous associated type in bounds
    E0222, // variadic function must have C calling convention
    E0223, // ambiguous associated type
    E0224, // at least one non-builtin train is required for an object type
    E0225, // only the builtin traits can be used as closure or object bounds
    E0226, // only a single explicit lifetime bound is permitted
    E0227, // ambiguous lifetime bound, explicit lifetime bound required
    E0228, // explicit lifetime bound required
    E0229, // associated type bindings are not allowed here
    E0230, // there is no type parameter on trait
    E0231, // only named substitution parameters are allowed
    E0232, // this attribute must have a value
    E0233,
    E0234, // `for` loop expression has type which does not implement the `Iterator` trait
    E0235, // structure constructor specifies a structure of type but
    E0236, // no lang item for range syntax
    E0237, // no lang item for range syntax
    E0238, // parenthesized parameters may only be used with a trait
    E0239, // `next` method of `Iterator` trait has unexpected type
    E0240,
    E0241,
    E0242, // internal error looking up a definition
    E0243, // wrong number of type arguments
    E0244, // wrong number of type arguments
    E0245, // not a trait
    E0246, // illegal recursive type
    E0247, // found module name used as a type
    E0248, // found value name used as a type
    E0249, // expected constant expr for array length
    E0250, // expected constant expr for array length
    E0318, // can't create default impls for traits outside their crates
    E0319, // trait impls for defaulted traits allowed just for structs/enums
    E0320, // recursive overflow during dropck
    E0321, // extended coherence rules for defaulted traits violated
    E0322, // cannot implement Sized explicitly
    E0323, // implemented an associated const when another trait item expected
    E0324, // implemented a method when another trait item expected
    E0325, // implemented an associated type when another trait item expected
    E0326, // associated const implemented with different type from trait
    E0327, // referred to method instead of constant in match pattern
    E0366, // dropck forbid specialization to concrete type or region
    E0367, // dropck forbid specialization to predicate not in struct/enum
    E0368, // binary operation `<op>=` cannot be applied to types
    E0369, // binary operation `<op>` cannot be applied to types
    E0371, // impl Trait for Trait is illegal
    E0372  // impl Trait for Trait where Trait is not object safe
}
<commit_msg>Add long diagnostic for E0046<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

register_long_diagnostics! {

E0046: r##"
When trying to make some type implement a trait `Foo`, you must, at minimum,
provide implementations for all of `Foo`'s required methods (meaning the
methods that do not have default implementations), as well as any required
trait items like associated types or constants.
"##,

E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
making them impossible to tell apart.

```
// Good.
enum Enum {
    P,
    X = 3,
    Y = 5
}

// Bad.
enum Enum {
    P = 3,
    X = 3,
    Y = 5
}
```

Note that variants without a manually specified discriminant are numbered from
top to bottom starting from 0, so clashes can occur with seemingly unrelated
variants.

```
enum Bad {
    X,
    Y = 0
}
```

Here `X` will have already been assigned the discriminant 0 by the time `Y` is
encountered, so a conflict occurs.
"##,

E0082: r##"
The default type for enum discriminants is `isize`, but it can be adjusted by
adding the `repr` attribute to the enum declaration. This error indicates that
an integer literal given as a discriminant is not a member of the discriminant
type. For example:

```
#[repr(u8)]
enum Thing {
    A = 1024,
    B = 5
}
```

Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
invalid. You may want to change representation types to fix this, or else change
invalid discriminant values so that they fit within the existing type.

Note also that without a representation manually defined, the compiler will
optimize by using the smallest integer type possible.
"##,

E0083: r##"
At present, it's not possible to define a custom representation for an enum with
a single variant. As a workaround you can add a `Dummy` variant.

See: https://github.com/rust-lang/rust/issues/10292
"##,

E0084: r##"
It is impossible to define an integer type to be used to represent zero-variant
enum values because there are no zero-variant enum values. There is no way to
construct an instance of the following type using only safe code:

```
enum Empty {}
```
"##

}

register_diagnostics! {
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0029,
    E0030,
    E0031,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0040, // explicit use of destructor method
    E0044,
    E0045,
    E0049,
    E0050,
    E0053,
    E0054,
    E0055,
    E0057,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0101,
    E0102,
    E0103,
    E0104,
    E0106,
    E0107,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0123,
    E0124,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0141,
    E0159,
    E0163,
    E0164,
    E0166,
    E0167,
    E0168,
    E0172,
    E0173, // manual implementations of unboxed closure traits are experimental
    E0174, // explicit use of unboxed closure methods are experimental
    E0178,
    E0182,
    E0183,
    E0184,
    E0185,
    E0186,
    E0187, // can't infer the kind of the closure
    E0188, // types differ in mutability
    E0189, // can only cast a boxed pointer to a boxed object
    E0190, // can only cast a &-pointer to an &-object
    E0191, // value of the associated type must be specified
    E0192, // negative imples are allowed just for `Send` and `Sync`
    E0193, // cannot bound type where clause bounds may only be attached to types
           // involving type parameters
    E0194,
    E0195, // lifetime parameters or bounds on method do not match the trait declaration
    E0196, // cannot determine a type for this closure
    E0197, // inherent impls cannot be declared as unsafe
    E0198, // negative implementations are not unsafe
    E0199, // implementing trait is not unsafe
    E0200, // trait requires an `unsafe impl` declaration
    E0201, // duplicate method in trait impl
    E0202, // associated items are not allowed in inherent impls
    E0203, // type parameter has more than one relaxed default bound,
           // and only one is supported
    E0204, // trait `Copy` may not be implemented for this type; field
           // does not implement `Copy`
    E0205, // trait `Copy` may not be implemented for this type; variant
           // does not implement `copy`
    E0206, // trait `Copy` may not be implemented for this type; type is
           // not a structure or enumeration
    E0207, // type parameter is not constrained by the impl trait, self type, or predicate
    E0208,
    E0209, // builtin traits can only be implemented on structs or enums
    E0210, // type parameter is not constrained by any local type
    E0211,
    E0212, // cannot extract an associated type from a higher-ranked trait bound
    E0213, // associated types are not accepted in this context
    E0214, // parenthesized parameters may only be used with a trait
    E0215, // angle-bracket notation is not stable with `Fn`
    E0216, // parenthetical notation is only stable with `Fn`
    E0217, // ambiguous associated type, defined in multiple supertraits
    E0218, // no associated type defined
    E0219, // associated type defined in higher-ranked supertrait
    E0220, // associated type not found for type parameter
    E0221, // ambiguous associated type in bounds
    E0222, // variadic function must have C calling convention
    E0223, // ambiguous associated type
    E0224, // at least one non-builtin train is required for an object type
    E0225, // only the builtin traits can be used as closure or object bounds
    E0226, // only a single explicit lifetime bound is permitted
    E0227, // ambiguous lifetime bound, explicit lifetime bound required
    E0228, // explicit lifetime bound required
    E0229, // associated type bindings are not allowed here
    E0230, // there is no type parameter on trait
    E0231, // only named substitution parameters are allowed
    E0232, // this attribute must have a value
    E0233,
    E0234, // `for` loop expression has type which does not implement the `Iterator` trait
    E0235, // structure constructor specifies a structure of type but
    E0236, // no lang item for range syntax
    E0237, // no lang item for range syntax
    E0238, // parenthesized parameters may only be used with a trait
    E0239, // `next` method of `Iterator` trait has unexpected type
    E0240,
    E0241,
    E0242, // internal error looking up a definition
    E0243, // wrong number of type arguments
    E0244, // wrong number of type arguments
    E0245, // not a trait
    E0246, // illegal recursive type
    E0247, // found module name used as a type
    E0248, // found value name used as a type
    E0249, // expected constant expr for array length
    E0250, // expected constant expr for array length
    E0318, // can't create default impls for traits outside their crates
    E0319, // trait impls for defaulted traits allowed just for structs/enums
    E0320, // recursive overflow during dropck
    E0321, // extended coherence rules for defaulted traits violated
    E0322, // cannot implement Sized explicitly
    E0323, // implemented an associated const when another trait item expected
    E0324, // implemented a method when another trait item expected
    E0325, // implemented an associated type when another trait item expected
    E0326, // associated const implemented with different type from trait
    E0327, // referred to method instead of constant in match pattern
    E0366, // dropck forbid specialization to concrete type or region
    E0367, // dropck forbid specialization to predicate not in struct/enum
    E0368, // binary operation `<op>=` cannot be applied to types
    E0369, // binary operation `<op>` cannot be applied to types
    E0371, // impl Trait for Trait is illegal
    E0372  // impl Trait for Trait where Trait is not object safe
}
<|endoftext|>