<commit_before>//! FBX parsing error.

use std::error;
use std::fmt;
use std::io;
use std::string;
use std::sync::Arc;

/// Result of parser function.
pub type Result<T> = ::std::result::Result<T, Error>;

/// FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// FBX footer is broken.
    BrokenFbxFooter,
    /// Successfully finished parsing FBX data.
    Finished,
    /// Specified FBX versions mismatched in header and footer.
    HeaderFooterVersionMismatch {
        /// Version specified in header.
        header: u32,
        /// Version specified in footer.
        footer: u32,
    },
    /// Invalid node attribute type code.
    InvalidNodeAttributeTypeCode {
        /// Got type code.
        got: u8,
        /// Position of the type code.
        position: u64,
    },
    /// Magic binary not detected.
    MagicNotDetected([u8; 21]),
    /// Node name has invalid UTF-8 sequences.
    NodeNameInvalidUtf8(Arc<string::FromUtf8Error>),
    /// I/O error.
    Io(io::Error),
    /// Unknown array attribute encoding.
    UnknownArrayAttributeEncoding(u32),
    /// End offset of a node is wrong.
    WrongNodeEndOffset {
        /// Start offset of the node.
        begin: u64,
        /// End offset of the node told by node header.
        expected_end: u64,
        /// Position of the end of the node detected while reading input.
        real_end: u64,
    },
}

impl Error {
    /// Creates `Error:NodeNameInvalidUtf8(_)` from the given error.
    pub fn node_name_invalid_utf8(e: string::FromUtf8Error) -> Self {
        Error::NodeNameInvalidUtf8(Arc::new(e))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::HeaderFooterVersionMismatch { header, footer } => {
                write!(f,
                       "FBX version is {} in the FBX header but {} in the footer",
                       header,
                       footer)
            },
            Error::InvalidNodeAttributeTypeCode { got, position } => {
                write!(f,
                       "Invalid node attribute type code: Got {:?} at position {}",
                       got,
                       position)
            },
            Error::MagicNotDetected(ref bytes) => {
                write!(f, "Magic binary not detected: Got {:?}", bytes)
            },
            Error::NodeNameInvalidUtf8(ref err) => {
                write!(f, "Node name is not vaiid UTF-8 string: {}", err)
            },
            Error::UnknownArrayAttributeEncoding(val) => {
                write!(f, "Unknown array attribute encoding: encoding={}", val)
            },
            Error::WrongNodeEndOffset { begin, expected_end, real_end } => {
                write!(f,
                       "Node ends with unexpected position: begin={}, expected_end={}, real_end={}",
                       begin,
                       expected_end,
                       real_end)
            },
            _ => write!(f, "{}", (self as &error::Error).description()),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::BrokenFbxFooter => "FBX footer is broken",
            Error::Finished => "Successfully finished parsing and there are no more data",
            Error::HeaderFooterVersionMismatch { .. } => {
                "Specified FBX versions mismatched in header and footer"
            },
            Error::InvalidNodeAttributeTypeCode { .. } => "Invalid node attribute type code",
            Error::MagicNotDetected(_) => "Magic binary not detected",
            Error::NodeNameInvalidUtf8(_) => "Node name is not vaiid UTF-8 string",
            Error::Io(ref err) => err.description(),
            Error::UnknownArrayAttributeEncoding(_) => "Unknown array attribute encoding",
            Error::WrongNodeEndOffset { .. } => "Wrong node end offset",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::NodeNameInvalidUtf8(ref err) => Some(&**err),
            Error::Io(ref err) => Some(err),
            _ => None,
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        match *self {
            Error::BrokenFbxFooter => Error::BrokenFbxFooter,
            Error::Finished => Error::Finished,
            Error::InvalidNodeAttributeTypeCode { got, position } => {
                Error::InvalidNodeAttributeTypeCode {
                    got: got,
                    position: position,
                }
            },
            Error::HeaderFooterVersionMismatch { header, footer } => {
                Error::HeaderFooterVersionMismatch {
                    header: header,
                    footer: footer,
                }
            },
            Error::MagicNotDetected(v) => Error::MagicNotDetected(v),
            Error::NodeNameInvalidUtf8(ref err) => Error::NodeNameInvalidUtf8(err.clone()),
            Error::Io(ref err) => {
                // To clone `io::Error`, convert inner error into string and use it as new inner error.
                Error::Io(io::Error::new(err.kind(), error::Error::description(err)))
            },
            Error::UnknownArrayAttributeEncoding(v) => Error::UnknownArrayAttributeEncoding(v),
            Error::WrongNodeEndOffset { begin, expected_end, real_end } => {
                Error::WrongNodeEndOffset {
                    begin: begin,
                    expected_end: expected_end,
                    real_end: real_end,
                }
            },
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

/// FBX parser warning.
#[derive(Debug, Clone, Copy)]
pub enum Warning {
    /// Invalid node attribute of boolean value.
    InvalidBooleanAttributeValue {
        /// Got value.
        got: u8,
        /// Assumed value.
        assumed: bool,
        /// Position of the attribute value.
        position: u64,
    },
    /// FBX footer has invalid padding.
    InvalidPaddingInFbxFooter {
        /// Expected padding length.
        expected: u8,
        /// Actual padding length.
        actual: u8,
    },
    /// Unknown 2 bytes right after FBX magic is unexpected.
    UnexpectedBytesAfterMagic([u8; 2]),
}

impl fmt::Display for Warning {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Warning::InvalidBooleanAttributeValue { got, assumed, position } => {
                write!(f,
                       "Invalid boolean node attribute value at position {}: got {:?}, assumed {}",
                       position,
                       got,
                       assumed)
            },
            Warning::InvalidPaddingInFbxFooter { expected, actual } => {
                write!(f,
                       "Invalid padding in FBX footer: expected {} bytes but got {} bytes",
                       expected,
                       actual)
            },
            Warning::UnexpectedBytesAfterMagic(ref bytes) => {
                write!(f,
                       "Unexpected bytes right after magic binary: expected [0x1a, 0x00] but got \
                        {:?}",
                       bytes)
            },
        }
    }
}

impl error::Error for Warning {
    fn description(&self) -> &str {
        match *self {
            Warning::InvalidBooleanAttributeValue { .. } => "Invalid boolean node attribute value",
            Warning::InvalidPaddingInFbxFooter { .. } => "Invalid padding in FBX footer",
            Warning::UnexpectedBytesAfterMagic(_) => "Unexpected bytes right after magic binary",
        }
    }
}
<commit_msg>Update documentation a little<commit_after>//! FBX parsing error.

use std::error;
use std::fmt;
use std::io;
use std::string;
use std::sync::Arc;

/// Result of parser function.
pub type Result<T> = ::std::result::Result<T, Error>;

/// FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// FBX footer is broken.
    BrokenFbxFooter,
    /// Successfully finished parsing the target FBX node(s).
    Finished,
    /// Specified FBX versions mismatched in header and footer.
    HeaderFooterVersionMismatch {
        /// Version specified in header.
        header: u32,
        /// Version specified in footer.
        footer: u32,
    },
    /// Invalid node attribute type code.
    InvalidNodeAttributeTypeCode {
        /// Got type code.
        got: u8,
        /// Position of the type code.
        position: u64,
    },
    /// Magic binary not detected.
    MagicNotDetected([u8; 21]),
    /// Node name has invalid UTF-8 sequences.
    NodeNameInvalidUtf8(Arc<string::FromUtf8Error>),
    /// I/O error.
    Io(io::Error),
    /// Unknown array attribute encoding.
    UnknownArrayAttributeEncoding(u32),
    /// End offset of a node is wrong.
    WrongNodeEndOffset {
        /// Start offset of the node.
        begin: u64,
        /// End offset of the node told by node header.
        expected_end: u64,
        /// Position of the end of the node detected while reading input.
        real_end: u64,
    },
}

impl Error {
    /// Creates `Error:NodeNameInvalidUtf8(_)` from the given error.
    pub fn node_name_invalid_utf8(e: string::FromUtf8Error) -> Self {
        Error::NodeNameInvalidUtf8(Arc::new(e))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::HeaderFooterVersionMismatch { header, footer } => {
                write!(f,
                       "FBX version is {} in the FBX header but {} in the footer",
                       header,
                       footer)
            },
            Error::InvalidNodeAttributeTypeCode { got, position } => {
                write!(f,
                       "Invalid node attribute type code: Got {:?} at position {}",
                       got,
                       position)
            },
            Error::MagicNotDetected(ref bytes) => {
                write!(f, "Magic binary not detected: Got {:?}", bytes)
            },
            Error::NodeNameInvalidUtf8(ref err) => {
                write!(f, "Node name is not vaiid UTF-8 string: {}", err)
            },
            Error::UnknownArrayAttributeEncoding(val) => {
                write!(f, "Unknown array attribute encoding: encoding={}", val)
            },
            Error::WrongNodeEndOffset { begin, expected_end, real_end } => {
                write!(f,
                       "Node ends with unexpected position: begin={}, expected_end={}, real_end={}",
                       begin,
                       expected_end,
                       real_end)
            },
            _ => write!(f, "{}", (self as &error::Error).description()),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::BrokenFbxFooter => "FBX footer is broken",
            Error::Finished => "Successfully finished parsing and there are no more data",
            Error::HeaderFooterVersionMismatch { .. } => {
                "Specified FBX versions mismatched in header and footer"
            },
            Error::InvalidNodeAttributeTypeCode { .. } => "Invalid node attribute type code",
            Error::MagicNotDetected(_) => "Magic binary not detected",
            Error::NodeNameInvalidUtf8(_) => "Node name is not vaiid UTF-8 string",
            Error::Io(ref err) => err.description(),
            Error::UnknownArrayAttributeEncoding(_) => "Unknown array attribute encoding",
            Error::WrongNodeEndOffset { .. } => "Wrong node end offset",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::NodeNameInvalidUtf8(ref err) => Some(&**err),
            Error::Io(ref err) => Some(err),
            _ => None,
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        match *self {
            Error::BrokenFbxFooter => Error::BrokenFbxFooter,
            Error::Finished => Error::Finished,
            Error::InvalidNodeAttributeTypeCode { got, position } => {
                Error::InvalidNodeAttributeTypeCode {
                    got: got,
                    position: position,
                }
            },
            Error::HeaderFooterVersionMismatch { header, footer } => {
                Error::HeaderFooterVersionMismatch {
                    header: header,
                    footer: footer,
                }
            },
            Error::MagicNotDetected(v) => Error::MagicNotDetected(v),
            Error::NodeNameInvalidUtf8(ref err) => Error::NodeNameInvalidUtf8(err.clone()),
            Error::Io(ref err) => {
                // To clone `io::Error`, convert inner error into string and use it as new inner error.
                Error::Io(io::Error::new(err.kind(), error::Error::description(err)))
            },
            Error::UnknownArrayAttributeEncoding(v) => Error::UnknownArrayAttributeEncoding(v),
            Error::WrongNodeEndOffset { begin, expected_end, real_end } => {
                Error::WrongNodeEndOffset {
                    begin: begin,
                    expected_end: expected_end,
                    real_end: real_end,
                }
            },
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

/// FBX parser warning.
#[derive(Debug, Clone, Copy)]
pub enum Warning {
    /// Invalid node attribute of boolean value.
    InvalidBooleanAttributeValue {
        /// Got value.
        got: u8,
        /// Assumed value.
        assumed: bool,
        /// Position of the attribute value.
        position: u64,
    },
    /// FBX footer has invalid padding.
    InvalidPaddingInFbxFooter {
        /// Expected padding length.
        expected: u8,
        /// Actual padding length.
        actual: u8,
    },
    /// Unknown 2 bytes right after FBX magic is unexpected.
    UnexpectedBytesAfterMagic([u8; 2]),
}

impl fmt::Display for Warning {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Warning::InvalidBooleanAttributeValue { got, assumed, position } => {
                write!(f,
                       "Invalid boolean node attribute value at position {}: got {:?}, assumed {}",
                       position,
                       got,
                       assumed)
            },
            Warning::InvalidPaddingInFbxFooter { expected, actual } => {
                write!(f,
                       "Invalid padding in FBX footer: expected {} bytes but got {} bytes",
                       expected,
                       actual)
            },
            Warning::UnexpectedBytesAfterMagic(ref bytes) => {
                write!(f,
                       "Unexpected bytes right after magic binary: expected [0x1a, 0x00] but got \
                        {:?}",
                       bytes)
            },
        }
    }
}

impl error::Error for Warning {
    fn description(&self) -> &str {
        match *self {
            Warning::InvalidBooleanAttributeValue { .. } => "Invalid boolean node attribute value",
            Warning::InvalidPaddingInFbxFooter { .. } => "Invalid padding in FBX footer",
            Warning::UnexpectedBytesAfterMagic(_) => "Unexpected bytes right after magic binary",
        }
    }
}
<|endoftext|>


<commit_before>enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Player {
    A,
    B,
    C,
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>Ask for a u8 input, break if it can't be parsed.<commit_after>use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Player {
    A,
    B,
    C,
}

fn main() {
    loop {
        println!("input:");
        let mut input = String::new();

        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };

        println!("your input: {}", input);
    }
}
<|endoftext|>


<commit_before>//! This module holds the machinery behind LabelledGeneric.
//!
//! A LabelledGeneric instance is pretty much exactly the same as a Generic instance, except
//! that the generic representation should contain information about field names.
//!
//! Having a separate trait for LabelledGenerics gives us the freedom to derive both
//! lablled and non-labelled generic type class instances for our types.
//!
//! Asides from the main LabelledGeneric trait, this module holds helper methods that allow
//! users to use LabelledGeneric without using universal function call syntax.
//!
//! In addition, this module holds macro-generated enums that map to letters in field names (identifiers).
//!
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "Lloyd"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```

use std::marker::PhantomData;
use hlist::*;
use std::fmt;

/// A trait that converts from a type to a labelled generic representation
///
/// For the most part, you should be using the derivation that is available through
/// frunk_derive to generate instances of this typeclass for your types.
///
/// I would highly recommend you check out `derivation_tests.rs` to see how to actually use
/// this trait in real life. Since frunk_derive depends on this trait, I can't actually
/// pull it in as a dependency here (otherwise the dependency would be circular) and show
/// how to use it in a proper doc test.
///
/// ```rust,ignore
/// #[derive(LabelledGeneric)]
/// struct NewUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// #[derive(LabelledGeneric)]
/// struct SavedUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// let n_user = NewUser {
///     first_name: "Joe",
///     last_name: "Blow",
///     age: 30,
/// };
///
/// let s_user = <SavedUser as LabelledGeneric>::sculpted_convert_from(n_user); // done
/// ```
pub trait LabelledGeneric {
    /// The labelled generic representation type
    type Repr;

    /// Go from something to Repr
    fn into(self) -> Self::Repr;

    /// Go from labelled Repr to something
    fn from(r: Self::Repr) -> Self;

    /// From one type to another using a type with a compatible labelled generic representation
    fn convert_from<A>(a: A) -> Self
        where A: LabelledGeneric<Repr = Self::Repr>,
              Self: Sized
    {
        let repr = <A as LabelledGeneric>::into(a);
        <Self as LabelledGeneric>::from(repr)
    }

    /// Converts from another type A into Self assuming that A and Self have labelled generic representations
    /// that can be sculpted into each other.
    ///
    /// Note that this method tosses away the "remainder" of the sculpted representation. In other
    /// words, anything that is not needed from A gets tossed out.
    fn sculpted_convert_from<A, Indices>(a: A) -> Self
        where A: LabelledGeneric,
              Self: Sized,
    // The labelled representation of A must be sculpt-able into the labelled representation of Self
              <A as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices> {
        let a_gen = <A as LabelledGeneric>::into(a);
        // We toss away the remainder.
        let (self_gen, _): (<Self as LabelledGeneric>::Repr, _) = a_gen.sculpt();
        <Self as LabelledGeneric>::from(self_gen)
    }
}

/// Given a labelled generic Representation of an A, returns A
pub fn from_labelled_generic<A, Repr>(gen: Repr) -> A
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::from(gen)
}

/// Given an A, returns its labelled generic Representation
pub fn into_labelled_generic<A, Repr>(a: A) -> Repr
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::into(a)
}

/// Converts one type into another assuming they have the same labelled generic Representation
pub fn labelled_convert_from<A, B, Repr>(a: A) -> B
    where A: LabelledGeneric<Repr = Repr>,
          B: LabelledGeneric<Repr = Repr>
{
    <B as LabelledGeneric>::convert_from(a)
}

/// Converts from one type into another assuming that their labelled generic representations
/// can be sculpted into each other.
///
/// The "Indices" type parameter allows the compiler to figure out that the two representations
/// can indeed be morphed into each other.
pub fn sculpted_convert_from<A, B, Indices>(a: A) -> B
    where A: LabelledGeneric,
          B: LabelledGeneric,
// The labelled representation of A must be sculpt-able into the labelled representation of B
          <A as LabelledGeneric>::Repr: Sculptor<<B as LabelledGeneric>::Repr, Indices> {
    <B as LabelledGeneric>::sculpted_convert_from(a)
}

// Create a bunch of enums that can be used to represent characters on the type level
macro_rules! create_enums_for {
    ($($i: ident)*) => {
        $(
            #[allow(non_snake_case, non_camel_case_types)]
            #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord)]
            pub enum $i {}
        )*
    }
}

// Add more as needed.
create_enums_for! { a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z __ _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 }

/// A Label contains a type-level Name, a runtime value, and
/// a reference to a `&'static str` name.
///
/// To construct one, use the `field!` macro.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "joe"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```
#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub struct Field<Name, Type> {
    name_type_holder: PhantomData<Name>,
    pub name: &'static str,
    pub value: Type,
}

impl <Name, Type> fmt::Debug for Field<Name, Type>
    where Type: fmt::Debug {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let v_debug = format!("{:?}", self.value);
        write!(f, "Field{{ name: {}, value: {} }}", self.name, v_debug)
    }
}

/// Returns a new Field for a given value and custom name.
///
/// If you don't want to provide a custom name and want to rely on the type you provide
/// to build a name, then please use the field! macro.
///
/// ```
/// # use frunk_core::labelled::*;
/// let l = field_with_name::<(n,a,m,e),_>("name", "joe");
/// assert_eq!(l.value, "joe");
/// assert_eq!(l.name, "name");
/// ```
pub fn field_with_name<Label, Value>(name: &'static str, value: Value) -> Field<Label, Value> {
    Field {
        name_type_holder: PhantomData,
        name: name,
        value: value,
    }
}

/// Trait for turning a Field HList into an un-labelled HList
pub trait IntoUnlabelled {
    type Output;

    /// Turns the current HList into an unlabelled on.
    ///
    /// Effectively extracts the values held inside the individual Field
    ///
    /// ```
    /// # #[macro_use] extern crate frunk_core;
    /// # use frunk_core::labelled::*;
    /// # use frunk_core::hlist::*;
    /// # fn main() {
    ///
    /// let labelled_hlist = hlist![
    ///     field!((n, a, m, e), "joe"),
    ///     field!((a, g, e), 3)
    /// ];
    ///
    /// let unlabelled = labelled_hlist.into_unlabelled();
    ///
    /// assert_eq!(unlabelled, hlist!["joe", 3])
    /// # }
    /// ```
    fn into_unlabelled(self) -> Self::Output;
}

/// Implementation for HNil
impl IntoUnlabelled for HNil {
    type Output = HNil;
    fn into_unlabelled(self) -> Self::Output {
        self
    }
}

/// Implementation when we have a non-empty HCons holding a label in its head
impl<Label, Value, Tail> IntoUnlabelled for HCons<Field<Label, Value>, Tail>
    where Tail: IntoUnlabelled
{
    type Output = HCons<Value, <Tail as IntoUnlabelled>::Output>;

    fn into_unlabelled(self) -> Self::Output {
        HCons {
            head: self.head.value,
            tail: self.tail.into_unlabelled(),
        }
    }
}

/// Used for creating a Field
///
/// There are 3 forms of this macro:
///
/// * Create an instance of the `Field` struct with a tuple name type
///   and any given value. The runtime-retrievable static name
///   field will be set to the the concatenation of the types passed in the
///   tuple type used as the first argument.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "joe"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```
///
/// * Create an instance of the `Field` struct with a custom, non-tuple
///   name type and a value. The runtime-retrievable static name field
///   will be set to the stringified version of the type provided.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// enum first_name {}
/// let labelled = field![first_name, "Joe"];
/// assert_eq!(labelled.name, "first_name");
/// # }
/// ```
///
/// * Create an instance of the `Field` struct with any name type and value,
///   _and_ a custom name, passed as the last argument in the macro
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(a,g,e), 30, "Age"];
/// assert_eq!(labelled.name, "Age");
/// # }
/// ```
#[macro_export]
macro_rules! field {
    // No name provided and type is a tuple
    (($($repeated: ty),*), $value: expr) => {
        field!( ($($repeated),*), $value, concat!( $(stringify!($repeated)),* ) )
    };
    // No name provided and type is a tuple, but with trailing commas
    (($($repeated: ty,)*), $value: expr) => {
        field!( ($($repeated),*), $value )
    };
    // We are provided any type, with no stable name
    ($name_type: ty, $value: expr) => {
        field!( $name_type, $value, stringify!($name_type) )
    };
    // We are provided any type, with a stable name
    ($name_type: ty, $value: expr, $name: expr) => {
        $crate::labelled::field_with_name::<$name_type,_>($name, $value)
    }
}

#[test]
fn test_label_new_building() {
    let l1 = field!((a, b, c), 3);
    assert_eq!(l1.value, 3);
    assert_eq!(l1.name, "abc");
    let l2 = field!((a, b, c,), 3);
    assert_eq!(l2.value, 3);
    assert_eq!(l2.name, "abc");

    // test named
    let l3 = field!((a,b,c), 3, "nope");
    assert_eq!(l3.value, 3);
    assert_eq!(l3.name, "nope");
    let l4 = field!((a,b,c,), 3, "nope");
    assert_eq!(l4.value, 3);
    assert_eq!(l4.name, "nope");
}

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

    #[test]
    fn test_field_construction() {
        let f1 = field!((a, g, e), 3);
        let f2 = field!((a, g, e), 3);
        assert_eq!(f1, f2)
    }

    #[test]
    fn test_anonymous_record_useage() {
        let record = hlist![
            field!((n, a, m, e), "Joe"),
            field!((a, g, e), 30)
        ];
        let (name, _): (Field<(n, a, m, e), _>, _) = record.pluck();
        assert_eq!(name.value, "Joe")
    }

    #[test]
    fn test_unlabelling() {
        let labelled_hlist = hlist![
            field!((n, a, m, e), "joe"),
            field!((a, g, e), 3)];
        let unlabelled = labelled_hlist.into_unlabelled();
        assert_eq!(unlabelled, hlist!["joe", 3])
    }

    #[test]
    fn test_name() {
        let labelled = field!((n, a, m, e), "joe");
        assert_eq!(labelled.name, "name")
    }
}
<commit_msg>Fix doc appearance for field macro<commit_after>//! This module holds the machinery behind LabelledGeneric.
//!
//! A LabelledGeneric instance is pretty much exactly the same as a Generic instance, except
//! that the generic representation should contain information about field names.
//!
//! Having a separate trait for LabelledGenerics gives us the freedom to derive both
//! lablled and non-labelled generic type class instances for our types.
//!
//! Asides from the main LabelledGeneric trait, this module holds helper methods that allow
//! users to use LabelledGeneric without using universal function call syntax.
//!
//! In addition, this module holds macro-generated enums that map to letters in field names (identifiers).
//!
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "Lloyd"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```

use std::marker::PhantomData;
use hlist::*;
use std::fmt;

/// A trait that converts from a type to a labelled generic representation
///
/// For the most part, you should be using the derivation that is available through
/// frunk_derive to generate instances of this typeclass for your types.
///
/// I would highly recommend you check out `derivation_tests.rs` to see how to actually use
/// this trait in real life. Since frunk_derive depends on this trait, I can't actually
/// pull it in as a dependency here (otherwise the dependency would be circular) and show
/// how to use it in a proper doc test.
///
/// ```rust,ignore
/// #[derive(LabelledGeneric)]
/// struct NewUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// #[derive(LabelledGeneric)]
/// struct SavedUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// let n_user = NewUser {
///     first_name: "Joe",
///     last_name: "Blow",
///     age: 30,
/// };
///
/// let s_user = <SavedUser as LabelledGeneric>::sculpted_convert_from(n_user); // done
/// ```
pub trait LabelledGeneric {
    /// The labelled generic representation type
    type Repr;

    /// Go from something to Repr
    fn into(self) -> Self::Repr;

    /// Go from labelled Repr to something
    fn from(r: Self::Repr) -> Self;

    /// From one type to another using a type with a compatible labelled generic representation
    fn convert_from<A>(a: A) -> Self
        where A: LabelledGeneric<Repr = Self::Repr>,
              Self: Sized
    {
        let repr = <A as LabelledGeneric>::into(a);
        <Self as LabelledGeneric>::from(repr)
    }

    /// Converts from another type A into Self assuming that A and Self have labelled generic representations
    /// that can be sculpted into each other.
    ///
    /// Note that this method tosses away the "remainder" of the sculpted representation. In other
    /// words, anything that is not needed from A gets tossed out.
    fn sculpted_convert_from<A, Indices>(a: A) -> Self
        where A: LabelledGeneric,
              Self: Sized,
    // The labelled representation of A must be sculpt-able into the labelled representation of Self
              <A as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices> {
        let a_gen = <A as LabelledGeneric>::into(a);
        // We toss away the remainder.
        let (self_gen, _): (<Self as LabelledGeneric>::Repr, _) = a_gen.sculpt();
        <Self as LabelledGeneric>::from(self_gen)
    }
}

/// Given a labelled generic Representation of an A, returns A
pub fn from_labelled_generic<A, Repr>(gen: Repr) -> A
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::from(gen)
}

/// Given an A, returns its labelled generic Representation
pub fn into_labelled_generic<A, Repr>(a: A) -> Repr
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::into(a)
}

/// Converts one type into another assuming they have the same labelled generic Representation
pub fn labelled_convert_from<A, B, Repr>(a: A) -> B
    where A: LabelledGeneric<Repr = Repr>,
          B: LabelledGeneric<Repr = Repr>
{
    <B as LabelledGeneric>::convert_from(a)
}

/// Converts from one type into another assuming that their labelled generic representations
/// can be sculpted into each other.
///
/// The "Indices" type parameter allows the compiler to figure out that the two representations
/// can indeed be morphed into each other.
pub fn sculpted_convert_from<A, B, Indices>(a: A) -> B
    where A: LabelledGeneric,
          B: LabelledGeneric,
// The labelled representation of A must be sculpt-able into the labelled representation of B
          <A as LabelledGeneric>::Repr: Sculptor<<B as LabelledGeneric>::Repr, Indices> {
    <B as LabelledGeneric>::sculpted_convert_from(a)
}

// Create a bunch of enums that can be used to represent characters on the type level
macro_rules! create_enums_for {
    ($($i: ident)*) => {
        $(
            #[allow(non_snake_case, non_camel_case_types)]
            #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord)]
            pub enum $i {}
        )*
    }
}

// Add more as needed.
create_enums_for! { a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z __ _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 }

/// A Label contains a type-level Name, a runtime value, and
/// a reference to a `&'static str` name.
///
/// To construct one, use the `field!` macro.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "joe"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```
#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub struct Field<Name, Type> {
    name_type_holder: PhantomData<Name>,
    pub name: &'static str,
    pub value: Type,
}

impl <Name, Type> fmt::Debug for Field<Name, Type>
    where Type: fmt::Debug {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let v_debug = format!("{:?}", self.value);
        write!(f, "Field{{ name: {}, value: {} }}", self.name, v_debug)
    }
}

/// Returns a new Field for a given value and custom name.
///
/// If you don't want to provide a custom name and want to rely on the type you provide
/// to build a name, then please use the field! macro.
///
/// ```
/// # use frunk_core::labelled::*;
/// let l = field_with_name::<(n,a,m,e),_>("name", "joe");
/// assert_eq!(l.value, "joe");
/// assert_eq!(l.name, "name");
/// ```
pub fn field_with_name<Label, Value>(name: &'static str, value: Value) -> Field<Label, Value> {
    Field {
        name_type_holder: PhantomData,
        name: name,
        value: value,
    }
}

/// Trait for turning a Field HList into an un-labelled HList
pub trait IntoUnlabelled {
    type Output;

    /// Turns the current HList into an unlabelled on.
    ///
    /// Effectively extracts the values held inside the individual Field
    ///
    /// ```
    /// # #[macro_use] extern crate frunk_core;
    /// # use frunk_core::labelled::*;
    /// # use frunk_core::hlist::*;
    /// # fn main() {
    ///
    /// let labelled_hlist = hlist![
    ///     field!((n, a, m, e), "joe"),
    ///     field!((a, g, e), 3)
    /// ];
    ///
    /// let unlabelled = labelled_hlist.into_unlabelled();
    ///
    /// assert_eq!(unlabelled, hlist!["joe", 3])
    /// # }
    /// ```
    fn into_unlabelled(self) -> Self::Output;
}

/// Implementation for HNil
impl IntoUnlabelled for HNil {
    type Output = HNil;
    fn into_unlabelled(self) -> Self::Output {
        self
    }
}

/// Implementation when we have a non-empty HCons holding a label in its head
impl<Label, Value, Tail> IntoUnlabelled for HCons<Field<Label, Value>, Tail>
    where Tail: IntoUnlabelled
{
    type Output = HCons<Value, <Tail as IntoUnlabelled>::Output>;

    fn into_unlabelled(self) -> Self::Output {
        HCons {
            head: self.head.value,
            tail: self.tail.into_unlabelled(),
        }
    }
}

/// Used for creating a Field
///
/// There are 3 forms of this macro:
///
/// * Create an instance of the `Field` struct with a tuple name type
///   and any given value. The runtime-retrievable static name
///   field will be set to the the concatenation of the types passed in the
///   tuple type used as the first argument.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(n,a,m,e), "joe"];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```
///
/// * Create an instance of the `Field` struct with a custom, non-tuple
///   name type and a value. The runtime-retrievable static name field
///   will be set to the stringified version of the type provided.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// enum first_name {}
/// let labelled = field![first_name, "Joe"];
/// assert_eq!(labelled.name, "first_name");
/// # }
/// ```
///
/// * Create an instance of the `Field` struct with any name type and value,
///   _and_ a custom name, passed as the last argument in the macro
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = field![(a,g,e), 30, "Age"];
/// assert_eq!(labelled.name, "Age");
/// # }
/// ```
#[macro_export]
macro_rules! field {
    // No name provided and type is a tuple
    (($($repeated: ty),*), $value: expr) => {
        field!( ($($repeated),*), $value, concat!( $(stringify!($repeated)),* ) )
    };
    // No name provided and type is a tuple, but with trailing commas
    (($($repeated: ty,)*), $value: expr) => {
        field!( ($($repeated),*), $value )
    };
    // We are provided any type, with no stable name
    ($name_type: ty, $value: expr) => {
        field!( $name_type, $value, stringify!($name_type) )
    };
    // We are provided any type, with a stable name
    ($name_type: ty, $value: expr, $name: expr) => {
        $crate::labelled::field_with_name::<$name_type,_>($name, $value)
    }
}

#[test]
fn test_label_new_building() {
    let l1 = field!((a, b, c), 3);
    assert_eq!(l1.value, 3);
    assert_eq!(l1.name, "abc");
    let l2 = field!((a, b, c,), 3);
    assert_eq!(l2.value, 3);
    assert_eq!(l2.name, "abc");

    // test named
    let l3 = field!((a,b,c), 3, "nope");
    assert_eq!(l3.value, 3);
    assert_eq!(l3.name, "nope");
    let l4 = field!((a,b,c,), 3, "nope");
    assert_eq!(l4.value, 3);
    assert_eq!(l4.name, "nope");
}

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

    #[test]
    fn test_field_construction() {
        let f1 = field!((a, g, e), 3);
        let f2 = field!((a, g, e), 3);
        assert_eq!(f1, f2)
    }

    #[test]
    fn test_anonymous_record_useage() {
        let record = hlist![
            field!((n, a, m, e), "Joe"),
            field!((a, g, e), 30)
        ];
        let (name, _): (Field<(n, a, m, e), _>, _) = record.pluck();
        assert_eq!(name.value, "Joe")
    }

    #[test]
    fn test_unlabelling() {
        let labelled_hlist = hlist![
            field!((n, a, m, e), "joe"),
            field!((a, g, e), 3)];
        let unlabelled = labelled_hlist.into_unlabelled();
        assert_eq!(unlabelled, hlist!["joe", 3])
    }

    #[test]
    fn test_name() {
        let labelled = field!((n, a, m, e), "joe");
        assert_eq!(labelled.name, "name")
    }
}
<|endoftext|>


<commit_before>extern crate lettre;

use lettre::{EmailTransport, SimpleSendableEmail};
use lettre::smtp::SmtpTransportBuilder;

fn main() {
    let email = SimpleSendableEmail::new(
        "user@localhost",
        vec!["root@localhost"],
        "file_id",
        "Hello file",
    );

    // Open a local connection on port 25
    let mut mailer = SmtpTransportBuilder::localhost().unwrap().build();
    // Send the email
    let result = mailer.send(email);

    if result.is_ok() {
        println!("Email sent");
    } else {
        println!("Could not send email: {:?}", result);
    }

    assert!(result.is_ok());
}
<commit_msg>feat(transport): Use utf-8 chars in example email<commit_after>extern crate lettre;

use lettre::{EmailTransport, SimpleSendableEmail};
use lettre::smtp::{SecurityLevel, SmtpTransportBuilder};

fn main() {
    let email = SimpleSendableEmail::new(
        "user@localhost",
        vec!["root@localhost"],
        "file_id",
        "Hello ß☺ example",
    );

    // Open a local connection on port 25
    let mut mailer = SmtpTransportBuilder::localhost().unwrap().security_level(SecurityLevel::Opportunistic).build();
    // Send the email
    let result = mailer.send(email);

    if result.is_ok() {
        println!("Email sent");
    } else {
        println!("Could not send email: {:?}", result);
    }

    assert!(result.is_ok());
}
<|endoftext|>


<commit_before>use base_db::fixture::WithFixture;
use expect_test::{expect, Expect};

use crate::{db::DefDatabase, test_db::TestDB};

fn check(ra_fixture: &str, expect: Expect) {
    let (db, file_id) = TestDB::with_single_file(ra_fixture);
    let item_tree = db.file_item_tree(file_id.into());
    let pretty = item_tree.pretty_print();
    expect.assert_eq(&pretty);
}

#[test]
fn imports() {
    check(
        r#"
//! file comment
#![no_std]
//! another file comment

extern crate self as renamed;
pub(super) extern crate bli;

pub use crate::path::{nested, items as renamed, Trait as _};
use globs::*;

/// docs on import
use crate::{A, B};

use a::{c, d::{e}};
        "#,
        expect![[r##"
            #![doc = " file comment"]
            #![no_std]
            #![doc = " another file comment"]

            pub(self) extern crate self as renamed;

            pub(super) extern crate bli;

            pub use crate::path::{nested, items as renamed, Trait as _};

            pub(self) use globs::*;

            #[doc = " docs on import"]
            pub(self) use crate::{A, B};

            pub(self) use a::{c, d::{e}};
        "##]],
    );
}

#[test]
fn extern_blocks() {
    check(
        r#"
#[on_extern_block]
extern "C" {
    #[on_extern_type]
    type ExType;

    #[on_extern_static]
    static EX_STATIC: u8;

    #[on_extern_fn]
    fn ex_fn();
}
        "#,
        expect![[r##"
            #[on_extern_block]
            extern "C" {
                #[on_extern_type]
                pub(self) type ExType;

                #[on_extern_static]
                pub(self) static EX_STATIC: u8 = _;

                #[on_extern_fn]
                pub(self) fn ex_fn() -> ();
            }
        "##]],
    );
}

#[test]
fn adts() {
    check(
        r#"
struct Unit;

#[derive(Debug)]
struct Struct {
    /// fld docs
    fld: (),
}

struct Tuple(#[attr] u8);

union Ize {
    a: (),
    b: (),
}

enum E {
    /// comment on Unit
    Unit,
    /// comment on Tuple
    Tuple(u8),
    Struct {
        /// comment on a: u8
        a: u8,
    }
}
        "#,
        expect![[r##"
            pub(self) struct Unit;

            #[derive(Debug)]
            pub(self) struct Struct {
                #[doc = " fld docs"]
                pub(self) fld: (),
            }

            pub(self) struct Tuple(
                #[attr]
                pub(self) 0: u8,
            );

            pub(self) union Ize {
                pub(self) a: (),
                pub(self) b: (),
            }

            pub(self) enum E {
                #[doc = " comment on Unit"]
                Unit,
                #[doc = " comment on Tuple"]
                Tuple(
                    pub(self) 0: u8,
                ),
                Struct {
                    #[doc = " comment on a: u8"]
                    pub(self) a: u8,
                },
            }
        "##]],
    );
}

#[test]
fn misc() {
    check(
        r#"
pub static mut ST: () = ();

const _: Anon = ();

#[attr]
fn f(#[attr] arg: u8, _: ()) {
    #![inner_attr_in_fn]
}

trait Tr: SuperTrait + 'lifetime {
    type Assoc: AssocBound = Default;
    fn method(&self);
}
        "#,
        expect![[r##"
            pub static mut ST: () = _;

            pub(self) const _: Anon = _;

            #[attr]
            #[inner_attr_in_fn]
            pub(self) fn f(
                #[attr]
                arg: u8,
                _: (),
            ) -> () { ... }

            pub(self) trait Tr<Self>
            where
                Self: SuperTrait,
                Self: 'lifetime
            {
                pub(self) type Assoc: AssocBound = Default;

                pub(self) fn method(
                    _: &Self,  // self
                ) -> ();
            }
        "##]],
    );
}

#[test]
fn modules() {
    check(
        r#"
/// outer
mod inline {
    //! inner

    use super::*;

    fn fn_in_module() {}
}

mod outline;
        "#,
        expect![[r##"
            #[doc = " outer"]
            #[doc = " inner"]
            pub(self) mod inline {
                pub(self) use super::*;

                pub(self) fn fn_in_module() -> () { ... }
            }

            pub(self) mod outline;
        "##]],
    );
}

#[test]
fn macros() {
    check(
        r#"
macro_rules! m {
    () => {};
}

pub macro m2() {}

m!();
        "#,
        expect![[r#"
            macro_rules! m { ... }

            pub macro m2 { ... }

            m!(...);
        "#]],
    );
}

#[test]
fn mod_paths() {
    check(
        r#"
struct S {
    a: self::Ty,
    b: super::SuperTy,
    c: super::super::SuperSuperTy,
    d: ::abs::Path,
    e: crate::Crate,
    f: plain::path::Ty,
}
        "#,
        expect![[r#"
            pub(self) struct S {
                pub(self) a: self::Ty,
                pub(self) b: super::SuperTy,
                pub(self) c: super::super::SuperSuperTy,
                pub(self) d: ::abs::Path,
                pub(self) e: crate::Crate,
                pub(self) f: plain::path::Ty,
            }
        "#]],
    )
}

#[test]
fn types() {
    check(
        r#"
struct S {
    a: Mixed<'a, T, Item=(), OtherItem=u8>,
    b: <Fully as Qualified>::Syntax,
    c: <TypeAnchored>::Path::<'a>,
    d: dyn for<'a> Trait<'a>,
}
        "#,
        expect![[r#"
            pub(self) struct S {
                pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>,
                pub(self) b: Qualified<Self=Fully>::Syntax,
                pub(self) c: <TypeAnchored>::Path<'a>,
                pub(self) d: dyn for<'a> Trait<'a>,
            }
        "#]],
    )
}

#[test]
fn generics() {
    check(
        r#"
struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {
    field: &'a &'b T,
}

struct Tuple<T: Copy, U: ?Sized>(T, U);

impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> {
    fn f<G: 'a>(arg: impl Copy) -> impl Copy {}
}

enum Enum<'a, T, const U: u8> {}
union Union<'a, T, const U: u8> {}

trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
        "#,
        expect![[r#"
            pub(self) struct S<'a, 'b, T, const K: u8>
            where
                T: Copy,
                T: 'a,
                T: 'b
            {
                pub(self) field: &'a &'b T,
            }

            pub(self) struct Tuple<T, U>(
                pub(self) 0: T,
                pub(self) 1: U,
            )
            where
                T: Copy,
                U: ?Sized;

            impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K>
            where
                T: Copy,
                T: 'a,
                T: 'b
            {
                pub(self) fn f<G>(
                    arg: impl Copy,
                ) -> impl Copy
                where
                    G: 'a { ... }
            }

            pub(self) enum Enum<'a, T, const U: u8> {
            }

            pub(self) union Union<'a, T, const U: u8> {
            }

            pub(self) trait Tr<'a, Self, T>
            where
                Self: Super,
                T: 'a,
                Self: for<'a> Tr<'a, T>
            {
            }
        "#]],
    )
}

// #[test]
// fn inherit_visibility() {
//     check(
//         r#"
// pub(crate) enum En {
//     Var1(u8),
//     Var2 {
//         fld: u8,
//     },
// }

// pub(crate) trait Tr {
//     fn f();
//     fn method(&self) {}
// }
//         "#,
//         expect![[r#"
//             pub(crate) enum En {
//                 Var1(
//                     pub(crate) 0: u8,
//                 ),
//                 Var2 {
//                     pub(crate) fld: u8,
//                 },
//             }

//             pub(crate) trait Tr<Self> {
//                 pub(crate) fn f() -> ();

//                 pub(crate) fn method(
//                     _: &Self,  // self
//                 ) -> () { ... }
//             }
//         "#]],
//     )
// }
<commit_msg>remove inherit_visibility test case in item_tree<commit_after>use base_db::fixture::WithFixture;
use expect_test::{expect, Expect};

use crate::{db::DefDatabase, test_db::TestDB};

fn check(ra_fixture: &str, expect: Expect) {
    let (db, file_id) = TestDB::with_single_file(ra_fixture);
    let item_tree = db.file_item_tree(file_id.into());
    let pretty = item_tree.pretty_print();
    expect.assert_eq(&pretty);
}

#[test]
fn imports() {
    check(
        r#"
//! file comment
#![no_std]
//! another file comment

extern crate self as renamed;
pub(super) extern crate bli;

pub use crate::path::{nested, items as renamed, Trait as _};
use globs::*;

/// docs on import
use crate::{A, B};

use a::{c, d::{e}};
        "#,
        expect![[r##"
            #![doc = " file comment"]
            #![no_std]
            #![doc = " another file comment"]

            pub(self) extern crate self as renamed;

            pub(super) extern crate bli;

            pub use crate::path::{nested, items as renamed, Trait as _};

            pub(self) use globs::*;

            #[doc = " docs on import"]
            pub(self) use crate::{A, B};

            pub(self) use a::{c, d::{e}};
        "##]],
    );
}

#[test]
fn extern_blocks() {
    check(
        r#"
#[on_extern_block]
extern "C" {
    #[on_extern_type]
    type ExType;

    #[on_extern_static]
    static EX_STATIC: u8;

    #[on_extern_fn]
    fn ex_fn();
}
        "#,
        expect![[r##"
            #[on_extern_block]
            extern "C" {
                #[on_extern_type]
                pub(self) type ExType;

                #[on_extern_static]
                pub(self) static EX_STATIC: u8 = _;

                #[on_extern_fn]
                pub(self) fn ex_fn() -> ();
            }
        "##]],
    );
}

#[test]
fn adts() {
    check(
        r#"
struct Unit;

#[derive(Debug)]
struct Struct {
    /// fld docs
    fld: (),
}

struct Tuple(#[attr] u8);

union Ize {
    a: (),
    b: (),
}

enum E {
    /// comment on Unit
    Unit,
    /// comment on Tuple
    Tuple(u8),
    Struct {
        /// comment on a: u8
        a: u8,
    }
}
        "#,
        expect![[r##"
            pub(self) struct Unit;

            #[derive(Debug)]
            pub(self) struct Struct {
                #[doc = " fld docs"]
                pub(self) fld: (),
            }

            pub(self) struct Tuple(
                #[attr]
                pub(self) 0: u8,
            );

            pub(self) union Ize {
                pub(self) a: (),
                pub(self) b: (),
            }

            pub(self) enum E {
                #[doc = " comment on Unit"]
                Unit,
                #[doc = " comment on Tuple"]
                Tuple(
                    pub(self) 0: u8,
                ),
                Struct {
                    #[doc = " comment on a: u8"]
                    pub(self) a: u8,
                },
            }
        "##]],
    );
}

#[test]
fn misc() {
    check(
        r#"
pub static mut ST: () = ();

const _: Anon = ();

#[attr]
fn f(#[attr] arg: u8, _: ()) {
    #![inner_attr_in_fn]
}

trait Tr: SuperTrait + 'lifetime {
    type Assoc: AssocBound = Default;
    fn method(&self);
}
        "#,
        expect![[r##"
            pub static mut ST: () = _;

            pub(self) const _: Anon = _;

            #[attr]
            #[inner_attr_in_fn]
            pub(self) fn f(
                #[attr]
                arg: u8,
                _: (),
            ) -> () { ... }

            pub(self) trait Tr<Self>
            where
                Self: SuperTrait,
                Self: 'lifetime
            {
                pub(self) type Assoc: AssocBound = Default;

                pub(self) fn method(
                    _: &Self,  // self
                ) -> ();
            }
        "##]],
    );
}

#[test]
fn modules() {
    check(
        r#"
/// outer
mod inline {
    //! inner

    use super::*;

    fn fn_in_module() {}
}

mod outline;
        "#,
        expect![[r##"
            #[doc = " outer"]
            #[doc = " inner"]
            pub(self) mod inline {
                pub(self) use super::*;

                pub(self) fn fn_in_module() -> () { ... }
            }

            pub(self) mod outline;
        "##]],
    );
}

#[test]
fn macros() {
    check(
        r#"
macro_rules! m {
    () => {};
}

pub macro m2() {}

m!();
        "#,
        expect![[r#"
            macro_rules! m { ... }

            pub macro m2 { ... }

            m!(...);
        "#]],
    );
}

#[test]
fn mod_paths() {
    check(
        r#"
struct S {
    a: self::Ty,
    b: super::SuperTy,
    c: super::super::SuperSuperTy,
    d: ::abs::Path,
    e: crate::Crate,
    f: plain::path::Ty,
}
        "#,
        expect![[r#"
            pub(self) struct S {
                pub(self) a: self::Ty,
                pub(self) b: super::SuperTy,
                pub(self) c: super::super::SuperSuperTy,
                pub(self) d: ::abs::Path,
                pub(self) e: crate::Crate,
                pub(self) f: plain::path::Ty,
            }
        "#]],
    )
}

#[test]
fn types() {
    check(
        r#"
struct S {
    a: Mixed<'a, T, Item=(), OtherItem=u8>,
    b: <Fully as Qualified>::Syntax,
    c: <TypeAnchored>::Path::<'a>,
    d: dyn for<'a> Trait<'a>,
}
        "#,
        expect![[r#"
            pub(self) struct S {
                pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>,
                pub(self) b: Qualified<Self=Fully>::Syntax,
                pub(self) c: <TypeAnchored>::Path<'a>,
                pub(self) d: dyn for<'a> Trait<'a>,
            }
        "#]],
    )
}

#[test]
fn generics() {
    check(
        r#"
struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {
    field: &'a &'b T,
}

struct Tuple<T: Copy, U: ?Sized>(T, U);

impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> {
    fn f<G: 'a>(arg: impl Copy) -> impl Copy {}
}

enum Enum<'a, T, const U: u8> {}
union Union<'a, T, const U: u8> {}

trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
        "#,
        expect![[r#"
            pub(self) struct S<'a, 'b, T, const K: u8>
            where
                T: Copy,
                T: 'a,
                T: 'b
            {
                pub(self) field: &'a &'b T,
            }

            pub(self) struct Tuple<T, U>(
                pub(self) 0: T,
                pub(self) 1: U,
            )
            where
                T: Copy,
                U: ?Sized;

            impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K>
            where
                T: Copy,
                T: 'a,
                T: 'b
            {
                pub(self) fn f<G>(
                    arg: impl Copy,
                ) -> impl Copy
                where
                    G: 'a { ... }
            }

            pub(self) enum Enum<'a, T, const U: u8> {
            }

            pub(self) union Union<'a, T, const U: u8> {
            }

            pub(self) trait Tr<'a, Self, T>
            where
                Self: Super,
                T: 'a,
                Self: for<'a> Tr<'a, T>
            {
            }
        "#]],
    )
}
<|endoftext|>


<commit_before>use super::*;

pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
    L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW,
    DYN_KW, L_ANGLE,
]);

const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA];

pub(super) fn type_(p: &mut Parser) {
    type_with_bounds_cond(p, true);
}

pub(super) fn type_no_bounds(p: &mut Parser) {
    type_with_bounds_cond(p, false);
}

fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
    match p.current() {
        L_PAREN => paren_or_tuple_type(p),
        EXCL => never_type(p),
        STAR => pointer_type(p),
        L_BRACK => array_or_slice_type(p),
        AMP => reference_type(p),
        UNDERSCORE => placeholder_type(p),
        FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
        FOR_KW => for_type(p),
        IMPL_KW => impl_trait_type(p),
        DYN_KW => dyn_trait_type(p),
        // Some path types are not allowed to have bounds (no plus)
        L_ANGLE => path_type_(p, allow_bounds),
        _ if paths::is_path_start(p) => path_type_(p, allow_bounds),
        _ => {
            p.err_recover("expected type", TYPE_RECOVERY_SET);
        }
    }
}

pub(super) fn is_type_start(p: &mut Parser) -> bool {
    match p.current() {
        L_PAREN | EXCL | STAR | L_BRACK | AMP | UNDERSCORE | FN_KW | FOR_KW | IMPL_KW | DYN_KW
        | L_ANGLE => true,
        _ => paths::is_path_start(p),
    }
}

pub(super) fn ascription(p: &mut Parser) {
    p.expect(COLON);
    type_(p)
}

fn paren_or_tuple_type(p: &mut Parser) {
    assert!(p.at(L_PAREN));
    let m = p.start();
    p.bump();
    let mut n_types: u32 = 0;
    let mut trailing_comma: bool = false;
    while !p.at(EOF) && !p.at(R_PAREN) {
        n_types += 1;
        type_(p);
        if p.eat(COMMA) {
            trailing_comma = true;
        } else {
            trailing_comma = false;
            break;
        }
    }
    p.expect(R_PAREN);

    let kind = if n_types == 1 && !trailing_comma {
        // test paren_type
        // type T = (i32);
        PAREN_TYPE
    } else {
        // test unit_type
        // type T = ();

        // test singleton_tuple_type
        // type T = (i32,);
        TUPLE_TYPE
    };
    m.complete(p, kind);
}

// test never_type
// type Never = !;
fn never_type(p: &mut Parser) {
    assert!(p.at(EXCL));
    let m = p.start();
    p.bump();
    m.complete(p, NEVER_TYPE);
}

fn pointer_type(p: &mut Parser) {
    assert!(p.at(STAR));
    let m = p.start();
    p.bump();

    match p.current() {
        // test pointer_type_mut
        // type M = *mut ();
        // type C = *mut ();
        MUT_KW | CONST_KW => p.bump(),
        _ => {
            // test_err pointer_type_no_mutability
            // type T = *();
            p.error(
                "expected mut or const in raw pointer type \
                 (use `*mut T` or `*const T` as appropriate)",
            );
        }
    };

    type_no_bounds(p);
    m.complete(p, POINTER_TYPE);
}

fn array_or_slice_type(p: &mut Parser) {
    assert!(p.at(L_BRACK));
    let m = p.start();
    p.bump();

    type_(p);
    let kind = match p.current() {
        // test slice_type
        // type T = [()];
        R_BRACK => {
            p.bump();
            SLICE_TYPE
        }

        // test array_type
        // type T = [(); 92];
        SEMI => {
            p.bump();
            expressions::expr(p);
            p.expect(R_BRACK);
            ARRAY_TYPE
        }
        // test_err array_type_missing_semi
        // type T = [() 92];
        _ => {
            p.error("expected `;` or `]`");
            SLICE_TYPE
        }
    };
    m.complete(p, kind);
}

// test reference_type;
// type A = &();
// type B = &'static ();
// type C = &mut ();
fn reference_type(p: &mut Parser) {
    assert!(p.at(AMP));
    let m = p.start();
    p.bump();
    p.eat(LIFETIME);
    p.eat(MUT_KW);
    type_no_bounds(p);
    m.complete(p, REFERENCE_TYPE);
}

// test placeholder_type
// type Placeholder = _;
fn placeholder_type(p: &mut Parser) {
    assert!(p.at(UNDERSCORE));
    let m = p.start();
    p.bump();
    m.complete(p, PLACEHOLDER_TYPE);
}

// test fn_pointer_type
// type A = fn();
// type B = unsafe fn();
// type C = unsafe extern "C" fn();
fn fn_pointer_type(p: &mut Parser) {
    let m = p.start();
    p.eat(UNSAFE_KW);
    if p.at(EXTERN_KW) {
        abi(p);
    }
    // test_err fn_pointer_type_missing_fn
    // type F = unsafe ();
    if !p.eat(FN_KW) {
        m.abandon(p);
        p.error("expected `fn`");
        return;
    }
    if p.at(L_PAREN) {
        params::param_list_opt_patterns(p);
    } else {
        p.error("expected parameters")
    }
    // test fn_pointer_type_with_ret
    // type F = fn() -> ();
    opt_fn_ret_type(p);
    m.complete(p, FN_POINTER_TYPE);
}

pub(super) fn for_binder(p: &mut Parser) {
    assert!(p.at(FOR_KW));
    p.bump();
    if p.at(L_ANGLE) {
        type_params::opt_type_param_list(p);
    } else {
        p.error("expected `<`");
    }
}

// test for_type
// type A = for<'a> fn() -> ();
pub(super) fn for_type(p: &mut Parser) {
    assert!(p.at(FOR_KW));
    let m = p.start();
    for_binder(p);
    match p.current() {
        FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
        _ if paths::is_path_start(p) => path_type_(p, false),
        _ => p.error("expected a path"),
    }
    m.complete(p, FOR_TYPE);
}

// test impl_trait_type
// type A = impl Iterator<Item=Foo<'a>> + 'a;
fn impl_trait_type(p: &mut Parser) {
    assert!(p.at(IMPL_KW));
    let m = p.start();
    p.bump();
    type_params::bounds_without_colon(p);
    m.complete(p, IMPL_TRAIT_TYPE);
}

// test dyn_trait_type
// type A = dyn Iterator<Item=Foo<'a>> + 'a;
fn dyn_trait_type(p: &mut Parser) {
    assert!(p.at(DYN_KW));
    let m = p.start();
    p.bump();
    type_params::bounds_without_colon(p);
    m.complete(p, DYN_TRAIT_TYPE);
}

// test path_type
// type A = Foo;
// type B = ::Foo;
// type C = self::Foo;
// type D = super::Foo;
pub(super) fn path_type(p: &mut Parser) {
    path_type_(p, true)
}

pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
    assert!(paths::is_path_start(p) || p.at(L_ANGLE));
    let m = p.start();
    paths::type_path(p);
    // test path_type_with_bounds
    // fn foo() -> Box<T + 'f> {}
    if allow_bounds && p.eat(PLUS) {
        type_params::bounds_without_colon(p);
    }
    m.complete(p, PATH_TYPE);
}
<commit_msg>Prefer TYPE_FIRST<commit_after>use super::*;

pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
    L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW,
    DYN_KW, L_ANGLE,
]);

const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA];

pub(super) fn type_(p: &mut Parser) {
    type_with_bounds_cond(p, true);
}

pub(super) fn type_no_bounds(p: &mut Parser) {
    type_with_bounds_cond(p, false);
}

fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
    match p.current() {
        L_PAREN => paren_or_tuple_type(p),
        EXCL => never_type(p),
        STAR => pointer_type(p),
        L_BRACK => array_or_slice_type(p),
        AMP => reference_type(p),
        UNDERSCORE => placeholder_type(p),
        FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
        FOR_KW => for_type(p),
        IMPL_KW => impl_trait_type(p),
        DYN_KW => dyn_trait_type(p),
        // Some path types are not allowed to have bounds (no plus)
        L_ANGLE => path_type_(p, allow_bounds),
        _ if paths::is_path_start(p) => path_type_(p, allow_bounds),
        _ => {
            p.err_recover("expected type", TYPE_RECOVERY_SET);
        }
    }
}

pub(super) fn is_type_start(p: &mut Parser) -> bool {
    if TYPE_FIRST.contains(p.current()) {
        true
    } else {
        paths::is_path_start(p)
    }
}

pub(super) fn ascription(p: &mut Parser) {
    p.expect(COLON);
    type_(p)
}

fn paren_or_tuple_type(p: &mut Parser) {
    assert!(p.at(L_PAREN));
    let m = p.start();
    p.bump();
    let mut n_types: u32 = 0;
    let mut trailing_comma: bool = false;
    while !p.at(EOF) && !p.at(R_PAREN) {
        n_types += 1;
        type_(p);
        if p.eat(COMMA) {
            trailing_comma = true;
        } else {
            trailing_comma = false;
            break;
        }
    }
    p.expect(R_PAREN);

    let kind = if n_types == 1 && !trailing_comma {
        // test paren_type
        // type T = (i32);
        PAREN_TYPE
    } else {
        // test unit_type
        // type T = ();

        // test singleton_tuple_type
        // type T = (i32,);
        TUPLE_TYPE
    };
    m.complete(p, kind);
}

// test never_type
// type Never = !;
fn never_type(p: &mut Parser) {
    assert!(p.at(EXCL));
    let m = p.start();
    p.bump();
    m.complete(p, NEVER_TYPE);
}

fn pointer_type(p: &mut Parser) {
    assert!(p.at(STAR));
    let m = p.start();
    p.bump();

    match p.current() {
        // test pointer_type_mut
        // type M = *mut ();
        // type C = *mut ();
        MUT_KW | CONST_KW => p.bump(),
        _ => {
            // test_err pointer_type_no_mutability
            // type T = *();
            p.error(
                "expected mut or const in raw pointer type \
                 (use `*mut T` or `*const T` as appropriate)",
            );
        }
    };

    type_no_bounds(p);
    m.complete(p, POINTER_TYPE);
}

fn array_or_slice_type(p: &mut Parser) {
    assert!(p.at(L_BRACK));
    let m = p.start();
    p.bump();

    type_(p);
    let kind = match p.current() {
        // test slice_type
        // type T = [()];
        R_BRACK => {
            p.bump();
            SLICE_TYPE
        }

        // test array_type
        // type T = [(); 92];
        SEMI => {
            p.bump();
            expressions::expr(p);
            p.expect(R_BRACK);
            ARRAY_TYPE
        }
        // test_err array_type_missing_semi
        // type T = [() 92];
        _ => {
            p.error("expected `;` or `]`");
            SLICE_TYPE
        }
    };
    m.complete(p, kind);
}

// test reference_type;
// type A = &();
// type B = &'static ();
// type C = &mut ();
fn reference_type(p: &mut Parser) {
    assert!(p.at(AMP));
    let m = p.start();
    p.bump();
    p.eat(LIFETIME);
    p.eat(MUT_KW);
    type_no_bounds(p);
    m.complete(p, REFERENCE_TYPE);
}

// test placeholder_type
// type Placeholder = _;
fn placeholder_type(p: &mut Parser) {
    assert!(p.at(UNDERSCORE));
    let m = p.start();
    p.bump();
    m.complete(p, PLACEHOLDER_TYPE);
}

// test fn_pointer_type
// type A = fn();
// type B = unsafe fn();
// type C = unsafe extern "C" fn();
fn fn_pointer_type(p: &mut Parser) {
    let m = p.start();
    p.eat(UNSAFE_KW);
    if p.at(EXTERN_KW) {
        abi(p);
    }
    // test_err fn_pointer_type_missing_fn
    // type F = unsafe ();
    if !p.eat(FN_KW) {
        m.abandon(p);
        p.error("expected `fn`");
        return;
    }
    if p.at(L_PAREN) {
        params::param_list_opt_patterns(p);
    } else {
        p.error("expected parameters")
    }
    // test fn_pointer_type_with_ret
    // type F = fn() -> ();
    opt_fn_ret_type(p);
    m.complete(p, FN_POINTER_TYPE);
}

pub(super) fn for_binder(p: &mut Parser) {
    assert!(p.at(FOR_KW));
    p.bump();
    if p.at(L_ANGLE) {
        type_params::opt_type_param_list(p);
    } else {
        p.error("expected `<`");
    }
}

// test for_type
// type A = for<'a> fn() -> ();
pub(super) fn for_type(p: &mut Parser) {
    assert!(p.at(FOR_KW));
    let m = p.start();
    for_binder(p);
    match p.current() {
        FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
        _ if paths::is_path_start(p) => path_type_(p, false),
        _ => p.error("expected a path"),
    }
    m.complete(p, FOR_TYPE);
}

// test impl_trait_type
// type A = impl Iterator<Item=Foo<'a>> + 'a;
fn impl_trait_type(p: &mut Parser) {
    assert!(p.at(IMPL_KW));
    let m = p.start();
    p.bump();
    type_params::bounds_without_colon(p);
    m.complete(p, IMPL_TRAIT_TYPE);
}

// test dyn_trait_type
// type A = dyn Iterator<Item=Foo<'a>> + 'a;
fn dyn_trait_type(p: &mut Parser) {
    assert!(p.at(DYN_KW));
    let m = p.start();
    p.bump();
    type_params::bounds_without_colon(p);
    m.complete(p, DYN_TRAIT_TYPE);
}

// test path_type
// type A = Foo;
// type B = ::Foo;
// type C = self::Foo;
// type D = super::Foo;
pub(super) fn path_type(p: &mut Parser) {
    path_type_(p, true)
}

pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
    assert!(paths::is_path_start(p) || p.at(L_ANGLE));
    let m = p.start();
    paths::type_path(p);
    // test path_type_with_bounds
    // fn foo() -> Box<T + 'f> {}
    if allow_bounds && p.eat(PLUS) {
        type_params::bounds_without_colon(p);
    }
    m.complete(p, PATH_TYPE);
}
<|endoftext|>


<commit_before>use ide_db::helpers::FamousDefs;
use syntax::{
    ast::{self, edit::AstNodeEdit, make, ArgListOwner},
    AstNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: convert_iter_for_each_to_for
//
// Converts an Iterator::for_each function into a for loop.
//
// ```
// # //- minicore: iterators
// # use core::iter;
// fn main() {
//     let iter = iter::repeat((9, 2));
//     iter.for_each$0(|(x, y)| {
//         println!("x: {}, y: {}", x, y);
//     });
// }
// ```
// ->
// ```
// # use core::iter;
// fn main() {
//     let iter = iter::repeat((9, 2));
//     for (x, y) in iter {
//         println!("x: {}, y: {}", x, y);
//     }
// }
// ```

pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let method = ctx.find_node_at_offset::<ast::MethodCallExpr>()?;

    let closure = match method.arg_list()?.args().next()? {
        ast::Expr::ClosureExpr(expr) => expr,
        _ => return None,
    };

    let (method, receiver) = validate_method_call_expr(ctx, method)?;

    let param_list = closure.param_list()?;
    let param = param_list.params().next()?.pat()?;
    let body = closure.body()?;

    let stmt = method.syntax().parent().and_then(ast::ExprStmt::cast);
    let syntax = stmt.as_ref().map_or(method.syntax(), |stmt| stmt.syntax());

    acc.add(
        AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite),
        "Replace this `Iterator::for_each` with a for loop",
        syntax.text_range(),
        |builder| {
            let indent = stmt.as_ref().map_or(method.indent_level(), |stmt| stmt.indent_level());

            let block = match body {
                ast::Expr::BlockExpr(block) => block,
                _ => make::block_expr(Vec::new(), Some(body)),
            }
            .reset_indent()
            .indent(indent);

            let expr_for_loop = make::expr_for_loop(param, receiver, block);
            builder.replace(syntax.text_range(), expr_for_loop.syntax().text())
        },
    )
}

fn validate_method_call_expr(
    ctx: &AssistContext,
    expr: ast::MethodCallExpr,
) -> Option<(ast::Expr, ast::Expr)> {
    let name_ref = expr.name_ref()?;
    if name_ref.syntax().text_range().intersect(ctx.frange.range).is_none() {
        cov_mark::hit!(test_for_each_not_applicable_invalid_cursor_pos);
        return None;
    }
    if name_ref.text() != "for_each" {
        return None;
    }

    let sema = &ctx.sema;

    let receiver = expr.receiver()?;
    let expr = ast::Expr::MethodCallExpr(expr);

    let it_type = sema.type_of_expr(&receiver)?.adjusted();
    let module = sema.scope(receiver.syntax()).module()?;
    let krate = module.krate();

    let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
    it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver))
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_for_each_in_method_stmt() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| {
        println!("x: {}, y: {}", x, y);
    });
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y);
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_in_method() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| {
        println!("x: {}, y: {}", x, y);
    })
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y);
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_without_braces_stmt() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| println!("x: {}, y: {}", x, y));
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y)
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_not_applicable() {
        check_assist_not_applicable(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    ().$0for_each(|x| println!("{}", x));
}"#,
        )
    }

    #[test]
    fn test_for_each_not_applicable_invalid_cursor_pos() {
        cov_mark::check!(test_for_each_not_applicable_invalid_cursor_pos);
        check_assist_not_applicable(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    core::iter::repeat(92).for_each(|(x, y)| $0println!("x: {}, y: {}", x, y));
}"#,
        )
    }
}
<commit_msg>internal: use the new `edit_in_place::Indent` API<commit_after>use ide_db::helpers::FamousDefs;
use syntax::{
    ast::{self, edit_in_place::Indent, make, ArgListOwner},
    AstNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: convert_iter_for_each_to_for
//
// Converts an Iterator::for_each function into a for loop.
//
// ```
// # //- minicore: iterators
// # use core::iter;
// fn main() {
//     let iter = iter::repeat((9, 2));
//     iter.for_each$0(|(x, y)| {
//         println!("x: {}, y: {}", x, y);
//     });
// }
// ```
// ->
// ```
// # use core::iter;
// fn main() {
//     let iter = iter::repeat((9, 2));
//     for (x, y) in iter {
//         println!("x: {}, y: {}", x, y);
//     }
// }
// ```

pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let method = ctx.find_node_at_offset::<ast::MethodCallExpr>()?;

    let closure = match method.arg_list()?.args().next()? {
        ast::Expr::ClosureExpr(expr) => expr,
        _ => return None,
    };

    let (method, receiver) = validate_method_call_expr(ctx, method)?;

    let param_list = closure.param_list()?;
    let param = param_list.params().next()?.pat()?;
    let body = closure.body()?;

    let stmt = method.syntax().parent().and_then(ast::ExprStmt::cast);
    let range = stmt.as_ref().map_or_else(|| method.syntax(), AstNode::syntax).text_range();

    acc.add(
        AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite),
        "Replace this `Iterator::for_each` with a for loop",
        range,
        |builder| {
            let indent =
                stmt.as_ref().map_or_else(|| method.indent_level(), ast::ExprStmt::indent_level);

            let block = match body {
                ast::Expr::BlockExpr(block) => block,
                _ => make::block_expr(Vec::new(), Some(body)),
            }
            .clone_for_update();
            block.reset_indent().indent(indent);

            let expr_for_loop = make::expr_for_loop(param, receiver, block);
            builder.replace(range, expr_for_loop.to_string())
        },
    )
}

fn validate_method_call_expr(
    ctx: &AssistContext,
    expr: ast::MethodCallExpr,
) -> Option<(ast::Expr, ast::Expr)> {
    let name_ref = expr.name_ref()?;
    if name_ref.syntax().text_range().intersect(ctx.frange.range).is_none() {
        cov_mark::hit!(test_for_each_not_applicable_invalid_cursor_pos);
        return None;
    }
    if name_ref.text() != "for_each" {
        return None;
    }

    let sema = &ctx.sema;

    let receiver = expr.receiver()?;
    let expr = ast::Expr::MethodCallExpr(expr);

    let it_type = sema.type_of_expr(&receiver)?.adjusted();
    let module = sema.scope(receiver.syntax()).module()?;
    let krate = module.krate();

    let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
    it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver))
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_for_each_in_method_stmt() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| {
        println!("x: {}, y: {}", x, y);
    });
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y);
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_in_method() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| {
        println!("x: {}, y: {}", x, y);
    })
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y);
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_without_braces_stmt() {
        check_assist(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    let it = core::iter::repeat(92);
    it.$0for_each(|(x, y)| println!("x: {}, y: {}", x, y));
}
"#,
            r#"
fn main() {
    let it = core::iter::repeat(92);
    for (x, y) in it {
        println!("x: {}, y: {}", x, y)
    }
}
"#,
        )
    }

    #[test]
    fn test_for_each_not_applicable() {
        check_assist_not_applicable(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    ().$0for_each(|x| println!("{}", x));
}"#,
        )
    }

    #[test]
    fn test_for_each_not_applicable_invalid_cursor_pos() {
        cov_mark::check!(test_for_each_not_applicable_invalid_cursor_pos);
        check_assist_not_applicable(
            convert_iter_for_each_to_for,
            r#"
//- minicore: iterators
fn main() {
    core::iter::repeat(92).for_each(|(x, y)| $0println!("x: {}, y: {}", x, y));
}"#,
        )
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
use std::default::Default;
use fn_box::FnBox;

pub struct Thread {
    pub id: ThreadId,
    pub state: ThreadState,
}

pub struct ThreadId(usize);

impl ThreadId {
    pub fn as_usize(&self) -> usize {
        self.0
    }
}

pub enum ThreadState {
    New {
        function: Box<FnBox() + Send>,
    },
    Active {
        rsp: uint,
    },
    Running,
}

impl Thread {

    fn next_id() -> ThreadId {
        static NEXT_ID: AtomicUint = ATOMIC_UINT_INIT;
        ThreadId(NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1) // start at id 1
    }

    pub fn new<F>(f: F) -> Thread where F : FnOnce(), F: Send {
        Thread {
            id: Thread::next_id(),
            state: ThreadState::New {
                function: Box::new(f),
            }
        }
    }
}

impl Default for Thread {
    fn default() -> Thread {
        Thread::new(|| print!("."))
    }
}
<commit_msg>first thread gets id 2 (main has id 1 and id 0 is reserved for spinlock); derive Show for ThreadId<commit_after>use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
use std::default::Default;
use fn_box::FnBox;

pub struct Thread {
    pub id: ThreadId,
    pub state: ThreadState,
}

#[derive(Show)]
pub struct ThreadId(usize);

impl ThreadId {
    pub fn as_usize(&self) -> usize {
        self.0
    }
}

pub enum ThreadState {
    New {
        function: Box<FnBox() + Send>,
    },
    Active {
        rsp: uint,
    },
    Running,
}

impl Thread {

    fn next_id() -> ThreadId {
        static NEXT_ID: AtomicUint = ATOMIC_UINT_INIT;
        ThreadId(NEXT_ID.fetch_add(1, Ordering::Relaxed) + 2) // start at id 2
    }

    pub fn new<F>(f: F) -> Thread where F : FnOnce(), F: Send {
        Thread {
            id: Thread::next_id(),
            state: ThreadState::New {
                function: Box::new(f),
            }
        }
    }
}

impl Default for Thread {
    fn default() -> Thread {
        Thread::new(|| println!("default"))
    }
}
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

//! Command-line interface for the main entry point.

use clap::Clap;
use log::{debug, error, info, LevelFilter};
use std::fs::File;
use std::io::{Read, Write};
use std::net::{IpAddr, SocketAddr};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::thread;
use std::time::{Duration, Instant};
use tokio::net::TcpListener;
use tonic::transport::Server;

use crate::commit::Commit;
use crate::logdir::LogdirLoader;
use crate::proto::tensorboard::data;
use crate::server::DataProviderHandler;

use data::tensor_board_data_provider_server::TensorBoardDataProviderServer;

#[derive(Clap, Debug)]
#[clap(name = "rustboard", version = "0.1.0")]
struct Opts {
    /// Log directory to load
    ///
    /// Directory to recursively scan for event files (files matching the `*tfevents*` glob). This
    /// directory, its descendants, and its event files will be periodically polled for new data.
    #[clap(long)]
    logdir: PathBuf,

    /// Bind to this IP address
    ///
    /// IP address to bind this server to. May be an IPv4 address (e.g., 127.0.0.1 or 0.0.0.0) or
    /// an IPv6 address (e.g., ::1 or ::0).
    #[clap(long, default_value = "::0")]
    host: IpAddr,

    /// Bind to this port
    ///
    /// Port to bind this server to. Use `0` to request an arbitrary free port from the OS.
    #[clap(long, default_value = "6806")]
    port: u16,

    /// Delay between reload cycles (seconds)
    ///
    /// Number of seconds to wait between finishing one load cycle and starting the next one. This
    /// does not include the time for the reload itself.
    #[clap(long, default_value = "5")]
    reload_interval: Seconds,

    /// Use verbose output (-vv for very verbose output)
    #[clap(long = "verbose", short, parse(from_occurrences))]
    verbosity: u32,

    /// Kill this server once stdin is closed
    ///
    /// While this server is running, read stdin to end of file and then kill the server. Used to
    /// portably ensure that the server exits when the parent process dies, even due to a crash.
    /// Don't set this if stdin is connected to a tty and the process will be backgrounded, since
    /// then the server will receive `SIGTTIN` and its process will be stopped (in the `SIGSTOP`
    /// sense) but not killed.
    #[clap(long)]
    die_after_stdin: bool,

    /// Write bound port to this file
    ///
    /// Once a server socket is opened, write the port on which it's listening to the file at this
    /// path. Useful with `--port 0`. Port will be written as ASCII decimal followed by a newline
    /// (e.g., "6806\n"). If the server fails to start, this file may not be written at all. If the
    /// port file is specified but cannot be written, the server will die.
    #[clap(long)]
    port_file: Option<PathBuf>,
}

/// A duration in seconds.
#[derive(Debug, Copy, Clone)]
struct Seconds(u64);
impl FromStr for Seconds {
    type Err = <u64 as FromStr>::Err;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse().map(Seconds)
    }
}
impl Seconds {
    fn duration(self) -> Duration {
        Duration::from_secs(self.0)
    }
}

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();
    init_logging(match opts.verbosity {
        0 => LevelFilter::Warn,
        1 => LevelFilter::Info,
        _ => LevelFilter::max(),
    });
    debug!("Parsed options: {:?}", opts);

    if opts.die_after_stdin {
        thread::Builder::new()
            .name("StdinWatcher".to_string())
            .spawn(die_after_stdin)
            .expect("failed to spawn stdin watcher thread");
    }

    let addr = SocketAddr::new(opts.host, opts.port);
    let listener = TcpListener::bind(addr).await?;
    let bound = listener.local_addr()?;
    eprintln!("listening on {:?}", bound);

    if let Some(port_file) = opts.port_file {
        let port = bound.port();
        if let Err(e) = write_port_file(&port_file, port) {
            error!(
                "Failed to write port \"{}\" to {}: {}",
                port,
                port_file.display(),
                e
            );
            std::process::exit(1);
        }
        info!("Wrote port \"{}\" to {}", port, port_file.display());
    }

    // Leak the commit object, since the Tonic server must have only 'static references. This only
    // leaks the outer commit structure (of constant size), not the pointers to the actual data.
    let commit: &'static Commit = Box::leak(Box::new(Commit::new()));

    thread::Builder::new()
        .name("Reloader".to_string())
        .spawn({
            let logdir = opts.logdir;
            let reload_interval = opts.reload_interval;
            move || {
                let mut loader = LogdirLoader::new(commit, logdir);
                loop {
                    info!("Starting load cycle");
                    let start = Instant::now();
                    loader.reload();
                    let end = Instant::now();
                    info!("Finished load cycle ({:?})", end - start);
                    thread::sleep(reload_interval.duration());
                }
            }
        })
        .expect("failed to spawn reloader thread");

    let handler = DataProviderHandler { commit };
    Server::builder()
        .add_service(TensorBoardDataProviderServer::new(handler))
        .serve_with_incoming(listener)
        .await?;
    Ok(())
}

/// Installs a logging handler whose behavior is determined by the `RUST_LOG` environment variable
/// (per <https://docs.rs/env_logger> semantics), or by including all logs at `default_log_level`
/// or above if `RUST_LOG_LEVEL` is not given.
fn init_logging(default_log_level: LevelFilter) {
    use env_logger::{Builder, Env};
    Builder::from_env(Env::default().default_filter_or(default_log_level.to_string())).init();
}

/// Locks stdin and reads it to EOF, then exits the process.
fn die_after_stdin() {
    let stdin = std::io::stdin();
    let stdin_lock = stdin.lock();
    for _ in stdin_lock.bytes() {}
    info!("Stdin closed; exiting");
    std::process::exit(0);
}

/// Writes `port` to file `path` as an ASCII decimal followed by newline.
fn write_port_file(path: &Path, port: u16) -> std::io::Result<()> {
    let mut f = File::create(path)?;
    writeln!(f, "{}", port)?;
    f.sync_all()?;
    Ok(())
}
<commit_msg>rust: bind server to `::1` by default (#4440)<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

//! Command-line interface for the main entry point.

use clap::Clap;
use log::{debug, error, info, LevelFilter};
use std::fs::File;
use std::io::{Read, Write};
use std::net::{IpAddr, SocketAddr};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::thread;
use std::time::{Duration, Instant};
use tokio::net::TcpListener;
use tonic::transport::Server;

use crate::commit::Commit;
use crate::logdir::LogdirLoader;
use crate::proto::tensorboard::data;
use crate::server::DataProviderHandler;

use data::tensor_board_data_provider_server::TensorBoardDataProviderServer;

#[derive(Clap, Debug)]
#[clap(name = "rustboard", version = "0.1.0")]
struct Opts {
    /// Log directory to load
    ///
    /// Directory to recursively scan for event files (files matching the `*tfevents*` glob). This
    /// directory, its descendants, and its event files will be periodically polled for new data.
    #[clap(long)]
    logdir: PathBuf,

    /// Bind to this IP address
    ///
    /// IP address to bind this server to. May be an IPv4 address (e.g., 127.0.0.1 or 0.0.0.0) or
    /// an IPv6 address (e.g., ::1 or ::0).
    #[clap(long, default_value = "::1")]
    host: IpAddr,

    /// Bind to this port
    ///
    /// Port to bind this server to. Use `0` to request an arbitrary free port from the OS.
    #[clap(long, default_value = "6806")]
    port: u16,

    /// Delay between reload cycles (seconds)
    ///
    /// Number of seconds to wait between finishing one load cycle and starting the next one. This
    /// does not include the time for the reload itself.
    #[clap(long, default_value = "5")]
    reload_interval: Seconds,

    /// Use verbose output (-vv for very verbose output)
    #[clap(long = "verbose", short, parse(from_occurrences))]
    verbosity: u32,

    /// Kill this server once stdin is closed
    ///
    /// While this server is running, read stdin to end of file and then kill the server. Used to
    /// portably ensure that the server exits when the parent process dies, even due to a crash.
    /// Don't set this if stdin is connected to a tty and the process will be backgrounded, since
    /// then the server will receive `SIGTTIN` and its process will be stopped (in the `SIGSTOP`
    /// sense) but not killed.
    #[clap(long)]
    die_after_stdin: bool,

    /// Write bound port to this file
    ///
    /// Once a server socket is opened, write the port on which it's listening to the file at this
    /// path. Useful with `--port 0`. Port will be written as ASCII decimal followed by a newline
    /// (e.g., "6806\n"). If the server fails to start, this file may not be written at all. If the
    /// port file is specified but cannot be written, the server will die.
    #[clap(long)]
    port_file: Option<PathBuf>,
}

/// A duration in seconds.
#[derive(Debug, Copy, Clone)]
struct Seconds(u64);
impl FromStr for Seconds {
    type Err = <u64 as FromStr>::Err;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse().map(Seconds)
    }
}
impl Seconds {
    fn duration(self) -> Duration {
        Duration::from_secs(self.0)
    }
}

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();
    init_logging(match opts.verbosity {
        0 => LevelFilter::Warn,
        1 => LevelFilter::Info,
        _ => LevelFilter::max(),
    });
    debug!("Parsed options: {:?}", opts);

    if opts.die_after_stdin {
        thread::Builder::new()
            .name("StdinWatcher".to_string())
            .spawn(die_after_stdin)
            .expect("failed to spawn stdin watcher thread");
    }

    let addr = SocketAddr::new(opts.host, opts.port);
    let listener = TcpListener::bind(addr).await?;
    let bound = listener.local_addr()?;
    eprintln!("listening on {:?}", bound);

    if let Some(port_file) = opts.port_file {
        let port = bound.port();
        if let Err(e) = write_port_file(&port_file, port) {
            error!(
                "Failed to write port \"{}\" to {}: {}",
                port,
                port_file.display(),
                e
            );
            std::process::exit(1);
        }
        info!("Wrote port \"{}\" to {}", port, port_file.display());
    }

    // Leak the commit object, since the Tonic server must have only 'static references. This only
    // leaks the outer commit structure (of constant size), not the pointers to the actual data.
    let commit: &'static Commit = Box::leak(Box::new(Commit::new()));

    thread::Builder::new()
        .name("Reloader".to_string())
        .spawn({
            let logdir = opts.logdir;
            let reload_interval = opts.reload_interval;
            move || {
                let mut loader = LogdirLoader::new(commit, logdir);
                loop {
                    info!("Starting load cycle");
                    let start = Instant::now();
                    loader.reload();
                    let end = Instant::now();
                    info!("Finished load cycle ({:?})", end - start);
                    thread::sleep(reload_interval.duration());
                }
            }
        })
        .expect("failed to spawn reloader thread");

    let handler = DataProviderHandler { commit };
    Server::builder()
        .add_service(TensorBoardDataProviderServer::new(handler))
        .serve_with_incoming(listener)
        .await?;
    Ok(())
}

/// Installs a logging handler whose behavior is determined by the `RUST_LOG` environment variable
/// (per <https://docs.rs/env_logger> semantics), or by including all logs at `default_log_level`
/// or above if `RUST_LOG_LEVEL` is not given.
fn init_logging(default_log_level: LevelFilter) {
    use env_logger::{Builder, Env};
    Builder::from_env(Env::default().default_filter_or(default_log_level.to_string())).init();
}

/// Locks stdin and reads it to EOF, then exits the process.
fn die_after_stdin() {
    let stdin = std::io::stdin();
    let stdin_lock = stdin.lock();
    for _ in stdin_lock.bytes() {}
    info!("Stdin closed; exiting");
    std::process::exit(0);
}

/// Writes `port` to file `path` as an ASCII decimal followed by newline.
fn write_port_file(path: &Path, port: u16) -> std::io::Result<()> {
    let mut f = File::create(path)?;
    writeln!(f, "{}", port)?;
    f.sync_all()?;
    Ok(())
}
<|endoftext|>