<commit_before>use crate::{
    app::{AppContext, AppContextPointer},
    errors::SondeError,
};
use gdk::Event;
use gtk::{self, prelude::*, Button, Menu, MenuItem, Notebook, Paned, Widget, Window};
use std::rc::Rc;

mod menu_callbacks;

const TABS: [(&str, &str); 8] = [
    ("skew_t", "Skew T"),
    ("hodograph_area", "Hodograph"),
    ("fire_plume_container", "Fire Plume"),
    ("text_area_container", "Text"),
    ("control_area", "Controls"),
    ("profiles_area_container", "Profiles"),
    ("indexes_scrolled_window", "Indexes"),
    ("provider_data_text_container", "Provider Data"),
];

pub fn set_up_main_window(ac: &AppContextPointer) -> Result<(), SondeError> {
    connect_header_bar(ac)?;
    configure_main_window(ac)?;

    Ok(())
}

macro_rules! set_up_button {
    ($ac:ident, $id:expr, $win:ident, $fn:expr) => {
        let button: Button = $ac.fetch_widget($id)?;
        let ac1 = Rc::clone($ac);
        let win1 = $win.clone();
        button.connect_clicked(move |_| {
            $fn(&ac1, &win1);
        });
    };
    ($ac:ident, $id:expr, $fn:expr) => {
        let button: Button = $ac.fetch_widget($id)?;
        let ac1: Rc<AppContext> = Rc::clone($ac);
        button.connect_clicked(move |_| {
            $fn(&ac1);
        });
    };
}

macro_rules! set_up_hamburger_menu_item {
    ($text:expr, $ac:ident, $win:ident, $fn:expr, $parent_menu:ident) => {
        let menu_item: MenuItem = MenuItem::with_label($text);
        let ac1 = Rc::clone($ac);
        let win1 = $win.clone();
        menu_item.connect_activate(move |_| $fn(&ac1, &win1));
        $parent_menu.append(&menu_item);
    };
}

fn connect_header_bar(ac: &AppContextPointer) -> Result<(), SondeError> {
    use menu_callbacks::{load_theme, open_toolbar_callback, save_image_callback, save_theme};

    let win: Window = ac.fetch_widget("main_window")?;

    set_up_button!(ac, "open-button", win, open_toolbar_callback);
    set_up_button!(ac, "save-image-button", win, save_image_callback);

    set_up_button!(ac, "go-first-button", |ac: &Rc<AppContext>| ac
        .display_first());
    set_up_button!(ac, "go-previous-button", |ac: &Rc<AppContext>| ac
        .display_previous());
    set_up_button!(ac, "go-next-button", |ac: &Rc<AppContext>| ac
        .display_next());
    set_up_button!(ac, "go-last-button", |ac: &Rc<AppContext>| ac
        .display_last());

    set_up_button!(ac, "zoom-in-button", |ac: &Rc<AppContext>| ac.zoom_in());
    set_up_button!(ac, "zoom-out-button", |ac: &Rc<AppContext>| ac.zoom_out());

    set_up_button!(ac, "quit-button", win, update_window_config_and_exit);

    // Set up the hamburger menu
    let menu: Menu = ac.fetch_widget("hamburger-menu")?;

    set_up_hamburger_menu_item!("Save Theme", ac, win, save_theme, menu);
    set_up_hamburger_menu_item!("Load Theme", ac, win, load_theme, menu);

    menu.show_all();

    Ok(())
}

fn configure_main_window(ac: &AppContextPointer) -> Result<(), SondeError> {
    let window: Window = ac.fetch_widget("main_window")?;

    layout_tabs_window(&window, ac)?;

    let ac1 = Rc::clone(ac);
    window.connect_delete_event(move |win, ev| on_delete(win, ev, &ac1));

    window.show_all();

    Ok(())
}

fn update_window_config_and_exit(ac: &AppContext, win: &Window) {
    let mut config = ac.config.borrow_mut();

    // Save the window dimensions
    let (width, height) = win.get_size();
    config.window_width = width;
    config.window_height = height;

    // Save the Paned view slider position.
    if let Ok(pane) = ac.fetch_widget::<Paned>("main_pane_view") {
        let pos = (pane.get_position() as f32) / (width as f32);
        config.pane_position = pos;
    }

    // Save the tabs, which notebook they are in, their order, and which ones were selected.
    if let (Ok(lnb), Ok(rnb)) = (
        ac.fetch_widget::<Notebook>("left_notebook"),
        ac.fetch_widget::<Notebook>("right_notebook"),
    ) {
        let tabs: Vec<Widget> = TABS
            .iter()
            // If there is an error here, it will ALWAYS fail. So go ahead and unwrap.
            .map(|&widget_id| {
                ac.fetch_widget::<Widget>(widget_id.0)
                    .expect("Error loading widget!")
            })
            .collect();

        let save_tabs = |cfg_tabs: &mut Vec<String>, nb: &Notebook| {
            cfg_tabs.clear();
            for child in nb.get_children() {
                for (idx, tab) in tabs.iter().enumerate() {
                    if child == *tab {
                        cfg_tabs.push(TABS[idx].0.to_owned());
                    }
                }
            }
        };

        save_tabs(&mut config.left_tabs, &lnb);
        save_tabs(&mut config.right_tabs, &rnb);

        config.left_page_selected = lnb.get_property_page();
        config.right_page_selected = rnb.get_property_page();
    }

    gtk::main_quit();
}

fn on_delete(win: &Window, _ev: &Event, ac: &AppContext) -> Inhibit {
    update_window_config_and_exit(ac, win);
    Inhibit(false)
}

fn layout_tabs_window(win: &Window, ac: &AppContext) -> Result<(), SondeError> {
    let cfg = ac.config.borrow();

    let pane: Paned = ac.fetch_widget("main_pane_view")?;

    let (width, height, pane_position) =
        { (cfg.window_width, cfg.window_height, cfg.pane_position) };

    if width > 0 || height > 0 {
        win.resize(width, height);
    }

    if pane_position > 0.0 {
        let (width, _) = win.get_size();
        let pos = (width as f32 * pane_position).round() as i32;

        debug_assert!(pos < width);
        pane.set_position(pos);
    }

    if !(cfg.left_tabs.is_empty() && cfg.right_tabs.is_empty()) {
        if let (Ok(lnb), Ok(rnb)) = (
            ac.fetch_widget::<Notebook>("left_notebook"),
            ac.fetch_widget::<Notebook>("right_notebook"),
        ) {
            let restore_tabs = |cfg_tabs: &Vec<String>, tgt_nb: &Notebook, other_nb: &Notebook| {
                for tab_id in cfg_tabs {
                    TABS.iter().position(|&s| s.0 == tab_id).and_then(|idx| {
                        ac.fetch_widget::<Widget>(TABS[idx].0)
                            .ok()
                            .and_then(|widget| {
                                let tgt_children = tgt_nb.get_children();
                                let other_children = other_nb.get_children();

                                if tgt_children.contains(&widget) {
                                    tgt_nb.remove(&widget);
                                } else if other_children.contains(&widget) {
                                    other_nb.remove(&widget);
                                }

                                tgt_nb.add(&widget);
                                tgt_nb.set_tab_label_text(&widget, TABS[idx].1);
                                tgt_nb.set_tab_detachable(&widget, true);
                                tgt_nb.set_tab_reorderable(&widget, true);

                                Some(())
                            })
                    });
                }
            };

            restore_tabs(&cfg.left_tabs, &lnb, &rnb);
            restore_tabs(&cfg.right_tabs, &rnb, &lnb);

            lnb.set_property_page(cfg.left_page_selected);
            rnb.set_property_page(cfg.right_page_selected);
        }
    }

    Ok(())
}
<commit_msg>Code cleanup.<commit_after>use crate::{
    app::{AppContext, AppContextPointer},
    errors::SondeError,
};
use gdk::Event;
use gtk::{self, prelude::*, Button, Menu, MenuItem, Notebook, Paned, Widget, Window};
use std::rc::Rc;

mod menu_callbacks;

const TABS: [(&str, &str); 8] = [
    ("skew_t", "Skew T"),
    ("hodograph_area", "Hodograph"),
    ("fire_plume_container", "Fire Plume"),
    ("text_area_container", "Text"),
    ("control_area", "Controls"),
    ("profiles_area_container", "Profiles"),
    ("indexes_scrolled_window", "Indexes"),
    ("provider_data_text_container", "Provider Data"),
];

pub fn set_up_main_window(ac: &AppContextPointer) -> Result<(), SondeError> {
    connect_header_bar(ac)?;
    configure_main_window(ac)?;

    Ok(())
}

macro_rules! set_up_button {
    ($ac:ident, $id:expr, $win:ident, $fn:expr) => {
        let button: Button = $ac.fetch_widget($id)?;
        let ac1 = Rc::clone($ac);
        let win1 = $win.clone();
        button.connect_clicked(move |_| {
            $fn(&ac1, &win1);
        });
    };
    ($ac:ident, $id:expr, $method:tt) => {
        let button: Button = $ac.fetch_widget($id)?;
        let ac1: Rc<AppContext> = Rc::clone($ac);
        button.connect_clicked(move |_| {
            ac1.$method();
        });
    };
}

macro_rules! set_up_hamburger_menu_item {
    ($text:expr, $ac:ident, $win:ident, $fn:expr, $parent_menu:ident) => {
        let menu_item: MenuItem = MenuItem::with_label($text);
        let ac1 = Rc::clone($ac);
        let win1 = $win.clone();
        menu_item.connect_activate(move |_| $fn(&ac1, &win1));
        $parent_menu.append(&menu_item);
    };
}

fn connect_header_bar(ac: &AppContextPointer) -> Result<(), SondeError> {
    use menu_callbacks::{load_theme, open_toolbar_callback, save_image_callback, save_theme};

    let win: Window = ac.fetch_widget("main_window")?;

    set_up_button!(ac, "open-button", win, open_toolbar_callback);
    set_up_button!(ac, "save-image-button", win, save_image_callback);

    set_up_button!(ac, "go-first-button", display_first);
    set_up_button!(ac, "go-previous-button", display_previous);
    set_up_button!(ac, "go-next-button", display_next);
    set_up_button!(ac, "go-last-button", display_last);

    set_up_button!(ac, "zoom-in-button", zoom_in);
    set_up_button!(ac, "zoom-out-button", zoom_out);

    set_up_button!(ac, "quit-button", win, update_window_config_and_exit);

    // Set up the hamburger menu
    let menu: Menu = ac.fetch_widget("hamburger-menu")?;

    set_up_hamburger_menu_item!("Save Theme", ac, win, save_theme, menu);
    set_up_hamburger_menu_item!("Load Theme", ac, win, load_theme, menu);

    menu.show_all();

    Ok(())
}

fn configure_main_window(ac: &AppContextPointer) -> Result<(), SondeError> {
    let window: Window = ac.fetch_widget("main_window")?;

    layout_tabs_window(&window, ac)?;

    let ac1 = Rc::clone(ac);
    window.connect_delete_event(move |win, ev| on_delete(win, ev, &ac1));

    window.show_all();

    Ok(())
}

fn update_window_config_and_exit(ac: &AppContext, win: &Window) {
    let mut config = ac.config.borrow_mut();

    // Save the window dimensions
    let (width, height) = win.get_size();
    config.window_width = width;
    config.window_height = height;

    // Save the Paned view slider position.
    if let Ok(pane) = ac.fetch_widget::<Paned>("main_pane_view") {
        let pos = (pane.get_position() as f32) / (width as f32);
        config.pane_position = pos;
    }

    // Save the tabs, which notebook they are in, their order, and which ones were selected.
    if let (Ok(lnb), Ok(rnb)) = (
        ac.fetch_widget::<Notebook>("left_notebook"),
        ac.fetch_widget::<Notebook>("right_notebook"),
    ) {
        let tabs: Vec<Widget> = TABS
            .iter()
            // If there is an error here, it will ALWAYS fail. So go ahead and unwrap.
            .map(|&widget_id| {
                ac.fetch_widget::<Widget>(widget_id.0)
                    .expect("Error loading widget!")
            })
            .collect();

        let save_tabs = |cfg_tabs: &mut Vec<String>, nb: &Notebook| {
            cfg_tabs.clear();
            for child in nb.get_children() {
                for (idx, tab) in tabs.iter().enumerate() {
                    if child == *tab {
                        cfg_tabs.push(TABS[idx].0.to_owned());
                    }
                }
            }
        };

        save_tabs(&mut config.left_tabs, &lnb);
        save_tabs(&mut config.right_tabs, &rnb);

        config.left_page_selected = lnb.get_property_page();
        config.right_page_selected = rnb.get_property_page();
    }

    gtk::main_quit();
}

fn on_delete(win: &Window, _ev: &Event, ac: &AppContext) -> Inhibit {
    update_window_config_and_exit(ac, win);
    Inhibit(false)
}

fn layout_tabs_window(win: &Window, ac: &AppContext) -> Result<(), SondeError> {
    let cfg = ac.config.borrow();

    let pane: Paned = ac.fetch_widget("main_pane_view")?;

    let (width, height, pane_position) =
        { (cfg.window_width, cfg.window_height, cfg.pane_position) };

    if width > 0 || height > 0 {
        win.resize(width, height);
    }

    if pane_position > 0.0 {
        let (width, _) = win.get_size();
        let pos = (width as f32 * pane_position).round() as i32;

        debug_assert!(pos < width);
        pane.set_position(pos);
    }

    if !(cfg.left_tabs.is_empty() && cfg.right_tabs.is_empty()) {
        if let (Ok(lnb), Ok(rnb)) = (
            ac.fetch_widget::<Notebook>("left_notebook"),
            ac.fetch_widget::<Notebook>("right_notebook"),
        ) {
            let restore_tabs = |cfg_tabs: &Vec<String>, tgt_nb: &Notebook, other_nb: &Notebook| {
                for tab_id in cfg_tabs {
                    TABS.iter().position(|&s| s.0 == tab_id).and_then(|idx| {
                        ac.fetch_widget::<Widget>(TABS[idx].0)
                            .ok()
                            .and_then(|widget| {
                                let tgt_children = tgt_nb.get_children();
                                let other_children = other_nb.get_children();

                                if tgt_children.contains(&widget) {
                                    tgt_nb.remove(&widget);
                                } else if other_children.contains(&widget) {
                                    other_nb.remove(&widget);
                                }

                                tgt_nb.add(&widget);
                                tgt_nb.set_tab_label_text(&widget, TABS[idx].1);
                                tgt_nb.set_tab_detachable(&widget, true);
                                tgt_nb.set_tab_reorderable(&widget, true);

                                Some(())
                            })
                    });
                }
            };

            restore_tabs(&cfg.left_tabs, &lnb, &rnb);
            restore_tabs(&cfg.right_tabs, &rnb, &lnb);

            lnb.set_property_page(cfg.left_page_selected);
            rnb.set_property_page(cfg.right_page_selected);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use cfb;
use internal::streamname::{self, SUMMARY_INFO_STREAM_NAME};
use std::io::{self, Read, Seek, Write};

// ========================================================================= //

/// An IO reader for an embedded binary stream in a package.
pub struct StreamReader<'a, F: 'a> {
    stream: cfb::Stream<'a, F>,
}

impl<'a, F> StreamReader<'a, F> {
    pub(crate) fn new(stream: cfb::Stream<'a, F>) -> StreamReader<'a, F> {
        StreamReader { stream: stream }
    }
}

impl<'a, F: Read + Seek> Read for StreamReader<'a, F> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.stream.read(buf)
    }
}

// ========================================================================= //

/// An IO writer for an embedded binary stream in a package.
pub struct StreamWriter<'a, F: 'a> {
    stream: cfb::Stream<'a, F>,
}

impl<'a, F> StreamWriter<'a, F> {
    pub(crate) fn new(stream: cfb::Stream<'a, F>) -> StreamWriter<'a, F> {
        StreamWriter { stream: stream }
    }
}

impl<'a, F: Read + Seek + Write> Write for StreamWriter<'a, F> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stream.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> { self.stream.flush() }
}

// ========================================================================= //

/// An iterator over the names of the binary streams in a package.
///
/// No guarantees are made about the order in which items are returned.
pub struct Streams<'a> {
    entries: cfb::Entries<'a>,
}

impl<'a> Streams<'a> {
    pub(crate) fn new(entries: cfb::Entries<'a>) -> Streams<'a> {
        Streams { entries: entries }
    }
}

impl<'a> Iterator for Streams<'a> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        loop {
            let entry = match self.entries.next() {
                Some(entry) => entry,
                None => return None,
            };
            if !entry.is_stream() || entry.name() == SUMMARY_INFO_STREAM_NAME {
                continue;
            }
            let (name, is_table) = streamname::decode(entry.name());
            if !is_table {
                return Some(name);
            }
        }
    }
}

// ========================================================================= //
<commit_msg>Add Seek implementations for StreamReader and StreamWriter<commit_after>use cfb;
use internal::streamname::{self, SUMMARY_INFO_STREAM_NAME};
use std::io::{self, Read, Seek, SeekFrom, Write};

// ========================================================================= //

/// An IO reader for an embedded binary stream in a package.
pub struct StreamReader<'a, F: 'a> {
    stream: cfb::Stream<'a, F>,
}

impl<'a, F> StreamReader<'a, F> {
    pub(crate) fn new(stream: cfb::Stream<'a, F>) -> StreamReader<'a, F> {
        StreamReader { stream: stream }
    }
}

impl<'a, F: Read + Seek> Read for StreamReader<'a, F> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.stream.read(buf)
    }
}

impl<'a, F: Read + Seek> Seek for StreamReader<'a, F> {
    fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
        self.stream.seek(from)
    }
}

// ========================================================================= //

/// An IO writer for an embedded binary stream in a package.
pub struct StreamWriter<'a, F: 'a> {
    stream: cfb::Stream<'a, F>,
}

impl<'a, F> StreamWriter<'a, F> {
    pub(crate) fn new(stream: cfb::Stream<'a, F>) -> StreamWriter<'a, F> {
        StreamWriter { stream: stream }
    }
}

impl<'a, F: Read + Seek + Write> Write for StreamWriter<'a, F> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stream.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> { self.stream.flush() }
}

impl<'a, F: Read + Seek + Write> Seek for StreamWriter<'a, F> {
    fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
        self.stream.seek(from)
    }
}

// ========================================================================= //

/// An iterator over the names of the binary streams in a package.
///
/// No guarantees are made about the order in which items are returned.
pub struct Streams<'a> {
    entries: cfb::Entries<'a>,
}

impl<'a> Streams<'a> {
    pub(crate) fn new(entries: cfb::Entries<'a>) -> Streams<'a> {
        Streams { entries: entries }
    }
}

impl<'a> Iterator for Streams<'a> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        loop {
            let entry = match self.entries.next() {
                Some(entry) => entry,
                None => return None,
            };
            if !entry.is_stream() || entry.name() == SUMMARY_INFO_STREAM_NAME {
                continue;
            }
            let (name, is_table) = streamname::decode(entry.name());
            if !is_table {
                return Some(name);
            }
        }
    }
}

// ========================================================================= //
<|endoftext|>


<commit_before>// Copyright 2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate rand;
extern crate ndarray;

use std::iter::FromIterator;

use rand::Rng;
use rand::distributions::Sample;
use rand::distributions::IndependentSample;

use ndarray::{
    ArrayBase,
    Dimension,
    DataOwned,
};

/// Constructors for n-dimensional arrays with random elements.
///
/// This trait extends ndarray’s `ArrayBase` and can not be implemented
/// for other types.
///
/// The default Rng is a fast automatically seeded rng (currently `rand::weak_rng`).
pub trait RandomExt<S, D>
    where S: DataOwned,
          D: Dimension,
{
    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`  using the default rng.
    ///
    /// ***Panics*** if the number of elements overflows usize.
    ///
    /// ```
    /// extern crate rand;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    ///
    /// use rand::distributions::Range;
    /// use ndarray::Array;
    /// use ndarray_rand::RandomExt;
    ///
    /// # fn main() {
    /// let a = Array::random((2, 5), Range::new(0., 10.));
    /// println!("{:8.4}", a);
    /// // Example Output:
    /// // [[  8.6900,   6.9824,   3.8922,   6.5861,   2.4890],
    /// //  [  0.0914,   5.5186,   5.8135,   5.2361,   3.1879]]
    /// # }
    fn random<IdS>(dim: D, distribution: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>;

    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`, using a specific Rng `rng`.
    ///
    /// ***Panics*** if the number of elements overflows usize.
    fn random_using<IdS, R>(dim: D, distribution: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng;
}

impl<S, D> RandomExt<S, D> for ArrayBase<S, D>
    where S: DataOwned,
          D: Dimension,
{
    fn random<IdS>(dim: D, dist: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>
    {
        Self::random_using(dim, dist, &mut rand::weak_rng())
    }

    fn random_using<IdS, R>(dim: D, dist: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng
    {
        let elements = Vec::from_iter((0..dim.size()).map(move |_| dist.ind_sample(rng)));
        Self::from_shape_vec(dim, elements).unwrap()
    }
}

/// A wrapper type that allows casting f64 distributions to f32
///
/// ```
/// extern crate rand;
/// extern crate ndarray;
/// extern crate ndarray_rand;
///
/// use rand::distributions::Normal;
/// use ndarray::Array;
/// use ndarray_rand::{RandomExt, F32};
///
/// # fn main() {
/// let a = Array::random((2, 5), F32(Normal::new(0., 1.)));
/// println!("{:8.4}", a);
/// // Example Output:
/// // [[ -0.6910,   1.1730,   1.0902,  -0.4092,  -1.7340],
/// //  [ -0.6810,   0.1678,  -0.9487,   0.3150,   1.2981]]
/// # }
#[derive(Copy, Clone, Debug)]
pub struct F32<S>(pub S);

impl<S> Sample<f32> for F32<S>
    where S: Sample<f64>
{
    fn sample<R>(&mut self, rng: &mut R) -> f32 where R: Rng {
        self.0.sample(rng) as f32
    }
}

impl<S> IndependentSample<f32> for F32<S>
    where S: IndependentSample<f64>
{
    fn ind_sample<R>(&self, rng: &mut R) -> f32 where R: Rng {
        self.0.ind_sample(rng) as f32
    }
}
<commit_msg>ndarray-rand: Update for IntoShape<commit_after>// Copyright 2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate rand;
extern crate ndarray;

use std::iter::FromIterator;

use rand::Rng;
use rand::distributions::Sample;
use rand::distributions::IndependentSample;

use ndarray::{
    ArrayBase,
    Dimension,
    DataOwned,
};
use ndarray::IntoShape;

/// Constructors for n-dimensional arrays with random elements.
///
/// This trait extends ndarray’s `ArrayBase` and can not be implemented
/// for other types.
///
/// The default Rng is a fast automatically seeded rng (currently `rand::weak_rng`).
pub trait RandomExt<S, D>
    where S: DataOwned,
          D: Dimension,
{
    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`  using the default rng.
    ///
    /// ***Panics*** if the number of elements overflows usize.
    ///
    /// ```
    /// extern crate rand;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    ///
    /// use rand::distributions::Range;
    /// use ndarray::Array;
    /// use ndarray_rand::RandomExt;
    ///
    /// # fn main() {
    /// let a = Array::random((2, 5), Range::new(0., 10.));
    /// println!("{:8.4}", a);
    /// // Example Output:
    /// // [[  8.6900,   6.9824,   3.8922,   6.5861,   2.4890],
    /// //  [  0.0914,   5.5186,   5.8135,   5.2361,   3.1879]]
    /// # }
    fn random<Sh, IdS>(shape: Sh, distribution: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              Sh: IntoShape<Dim=D>;

    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`, using a specific Rng `rng`.
    ///
    /// ***Panics*** if the number of elements overflows usize.
    fn random_using<Sh, IdS, R>(shape: Sh, distribution: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng,
              Sh: IntoShape<Dim=D>;
}

impl<S, D> RandomExt<S, D> for ArrayBase<S, D>
    where S: DataOwned,
          D: Dimension,
{
    fn random<Sh, IdS>(shape: Sh, dist: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              Sh: IntoShape<Dim=D>,
    {
        Self::random_using(shape, dist, &mut rand::weak_rng())
    }

    fn random_using<Sh, IdS, R>(shape: Sh, dist: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng,
              Sh: IntoShape<Dim=D>,
    {
        let shape = shape.into_shape();
        let elements = Vec::from_iter((0..shape.size()).map(move |_| dist.ind_sample(rng)));
        Self::from_shape_vec(shape, elements).unwrap()
    }
}

/// A wrapper type that allows casting f64 distributions to f32
///
/// ```
/// extern crate rand;
/// extern crate ndarray;
/// extern crate ndarray_rand;
///
/// use rand::distributions::Normal;
/// use ndarray::Array;
/// use ndarray_rand::{RandomExt, F32};
///
/// # fn main() {
/// let a = Array::random((2, 5), F32(Normal::new(0., 1.)));
/// println!("{:8.4}", a);
/// // Example Output:
/// // [[ -0.6910,   1.1730,   1.0902,  -0.4092,  -1.7340],
/// //  [ -0.6810,   0.1678,  -0.9487,   0.3150,   1.2981]]
/// # }
#[derive(Copy, Clone, Debug)]
pub struct F32<S>(pub S);

impl<S> Sample<f32> for F32<S>
    where S: Sample<f64>
{
    fn sample<R>(&mut self, rng: &mut R) -> f32 where R: Rng {
        self.0.sample(rng) as f32
    }
}

impl<S> IndependentSample<f32> for F32<S>
    where S: IndependentSample<f64>
{
    fn ind_sample<R>(&self, rng: &mut R) -> f32 where R: Rng {
        self.0.ind_sample(rng) as f32
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::PathBuf;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: HashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    {after_content}\
    \
    \
    {static_extra_scripts}\
    {extra_scripts}\
    \
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            let p = format!("{}{}", page.root_path, layout.krate);
            let p = ensure_trailing_slash(&p);
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    path = p,
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    p, layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        static_extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .collect::<String>(),
        extra_scripts = page
            .extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            })
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<commit_msg>Fixes submit event of the search input<commit_after>use std::collections::HashMap;
use std::path::PathBuf;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: HashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button type=\"button\" class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    {after_content}\
    \
    \
    {static_extra_scripts}\
    {extra_scripts}\
    \
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            let p = format!("{}{}", page.root_path, layout.krate);
            let p = ensure_trailing_slash(&p);
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    path = p,
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    p, layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        static_extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .collect::<String>(),
        extra_scripts = page
            .extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            })
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<|endoftext|>


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

//! Traits for conversions between types.
//!
//! The traits in this module provide a general way to talk about conversions
//! from one type to another. They follow the standard Rust conventions of
//! `as`/`into`/`from`.
//!
//! Like many traits, these are often used as bounds for generic functions, to
//! support arguments of multiple types.
//!
//! - Impl the `As*` traits for reference-to-reference conversions
//! - Impl the `Into` trait when you want to consume the value in the conversion
//! - The `From` trait is the most flexible, useful for value _and_ reference conversions
//! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the
//!   conversion to fail
//!
//! As a library author, you should prefer implementing `From<T>` or `TryFrom<T>` rather than
//! `Into<U>` or `TryInto<U>`, as `From` and `TryFrom` provide greater flexibility and offer
//! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation
//! in the standard library.
//!
//! # Generic impl
//!
//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference
//! - `From<U> for T` implies `Into<T> for U`
//! - `TryFrom<U> for T` implies `TryInto<T> for U`
//! - `From` and `Into` are reflexive, which means that all types can `into()`
//!   themselves and `from()` themselves
//!
//! See each trait for usage examples.

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;
use result::Result;

/// A cheap, reference-to-reference conversion.
///
/// `AsRef` is very similar to, but different than, `Borrow`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an `Option<T>` or a `Result<T, E>`.
///
/// # Examples
///
/// Both `String` and `&str` implement `AsRef<str>`:
///
/// ```
/// fn is_hello<T: AsRef<str>>(s: T) {
///    assert_eq!("hello", s.as_ref());
/// }
///
/// let s = "hello";
/// is_hello(s);
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `AsRef` auto-dereference if the inner type is a reference or a mutable
/// reference (eg: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_ref(&self) -> &T;
}

/// A cheap, mutable reference-to-mutable reference conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an `Option<T>` or a `Result<T, E>`.
///
/// # Generic Impls
///
/// - `AsMut` auto-dereference if the inner type is a reference or a mutable
/// reference (eg: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_mut(&mut self) -> &mut T;
}

/// A conversion that consumes `self`, which may or may not be expensive.
///
/// **Note: this trait must not fail**. If the conversion can fail, use `TryInto` or a dedicated
/// method which returns an `Option<T>` or a `Result<T, E>`.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the `From` trait, which offers greater flexibility and provides an equivalent `Into`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// # Examples
///
/// `String` implements `Into<Vec<u8>>`:
///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
///    let bytes = b"hello".to_vec();
///    assert_eq!(bytes, s.into());
/// }
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `From<T> for U` implies `Into<U> for T`
/// - `into()` is reflexive, which means that `Into<T> for T` is implemented
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into(self) -> T;
}

/// Construct `Self` via a conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use `TryFrom` or a dedicated
/// method which returns an `Option<T>` or a `Result<T, E>`.
///
/// # Examples
///
/// `String` implements `From<&str>`:
///
/// ```
/// let string = "hello".to_string();
/// let other_string = String::from("hello");
///
/// assert_eq!(string, other_string);
/// ```
/// # Generic impls
///
/// - `From<T> for U` implies `Into<U> for T`
/// - `from()` is reflexive, which means that `From<T> for T` is implemented
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait From<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from(T) -> Self;
}

/// An attempted conversion that consumes `self`, which may or may not be expensive.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the `TryFrom` trait, which offers greater flexibility and provides an equivalent `TryInto`
/// implementation for free, thanks to a blanket implementation in the standard library.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryInto<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_into(self) -> Result<T, Self::Err>;
}

/// Attempt to construct `Self` via a conversion.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

////////////////////////////////////////////////////////////////////////////////
// GENERIC IMPLS
////////////////////////////////////////////////////////////////////////////////

// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
// // As lifts over Deref
// impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
//     fn as_ref(&self) -> &U {
//         self.deref().as_ref()
//     }
// }

// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
    fn as_mut(&mut self) -> &mut U {
        (*self).as_mut()
    }
}

// FIXME (#23442): replace the above impl for &mut with the following more general one:
// // AsMut lifts over DerefMut
// impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
//     fn as_mut(&mut self) -> &mut U {
//         self.deref_mut().as_mut()
//     }
// }

// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
    fn into(self) -> U {
        U::from(self)
    }
}

// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
    fn from(t: T) -> T { t }
}

// TryFrom implies TryInto
#[unstable(feature = "try_from", issue = "33417")]
impl<T, U> TryInto<U> for T where U: TryFrom<T> {
    type Err = U::Err;

    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

////////////////////////////////////////////////////////////////////////////////
// CONCRETE IMPLS
////////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
    fn as_ref(&self) -> &[T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}
<commit_msg>fix small typos in std::convert documentation<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Traits for conversions between types.
//!
//! The traits in this module provide a general way to talk about conversions
//! from one type to another. They follow the standard Rust conventions of
//! `as`/`into`/`from`.
//!
//! Like many traits, these are often used as bounds for generic functions, to
//! support arguments of multiple types.
//!
//! - Impl the `As*` traits for reference-to-reference conversions
//! - Impl the `Into` trait when you want to consume the value in the conversion
//! - The `From` trait is the most flexible, useful for value _and_ reference conversions
//! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the
//!   conversion to fail
//!
//! As a library author, you should prefer implementing `From<T>` or `TryFrom<T>` rather than
//! `Into<U>` or `TryInto<U>`, as `From` and `TryFrom` provide greater flexibility and offer
//! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation
//! in the standard library.
//!
//! # Generic impl
//!
//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference
//! - `From<U> for T` implies `Into<T> for U`
//! - `TryFrom<U> for T` implies `TryInto<T> for U`
//! - `From` and `Into` are reflexive, which means that all types can `into()`
//!   themselves and `from()` themselves
//!
//! See each trait for usage examples.

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;
use result::Result;

/// A cheap, reference-to-reference conversion.
///
/// `AsRef` is very similar to, but different than, `Borrow`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an `Option<T>` or a `Result<T, E>`.
///
/// # Examples
///
/// Both `String` and `&str` implement `AsRef<str>`:
///
/// ```
/// fn is_hello<T: AsRef<str>>(s: T) {
///    assert_eq!("hello", s.as_ref());
/// }
///
/// let s = "hello";
/// is_hello(s);
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_ref(&self) -> &T;
}

/// A cheap, mutable reference-to-mutable reference conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an `Option<T>` or a `Result<T, E>`.
///
/// # Generic Impls
///
/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_mut(&mut self) -> &mut T;
}

/// A conversion that consumes `self`, which may or may not be expensive.
///
/// **Note: this trait must not fail**. If the conversion can fail, use `TryInto` or a dedicated
/// method which returns an `Option<T>` or a `Result<T, E>`.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the `From` trait, which offers greater flexibility and provides an equivalent `Into`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// # Examples
///
/// `String` implements `Into<Vec<u8>>`:
///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
///    let bytes = b"hello".to_vec();
///    assert_eq!(bytes, s.into());
/// }
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `From<T> for U` implies `Into<U> for T`
/// - `into()` is reflexive, which means that `Into<T> for T` is implemented
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into(self) -> T;
}

/// Construct `Self` via a conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use `TryFrom` or a dedicated
/// method which returns an `Option<T>` or a `Result<T, E>`.
///
/// # Examples
///
/// `String` implements `From<&str>`:
///
/// ```
/// let string = "hello".to_string();
/// let other_string = String::from("hello");
///
/// assert_eq!(string, other_string);
/// ```
/// # Generic impls
///
/// - `From<T> for U` implies `Into<U> for T`
/// - `from()` is reflexive, which means that `From<T> for T` is implemented
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait From<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from(T) -> Self;
}

/// An attempted conversion that consumes `self`, which may or may not be expensive.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the `TryFrom` trait, which offers greater flexibility and provides an equivalent `TryInto`
/// implementation for free, thanks to a blanket implementation in the standard library.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryInto<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_into(self) -> Result<T, Self::Err>;
}

/// Attempt to construct `Self` via a conversion.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

////////////////////////////////////////////////////////////////////////////////
// GENERIC IMPLS
////////////////////////////////////////////////////////////////////////////////

// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
// // As lifts over Deref
// impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
//     fn as_ref(&self) -> &U {
//         self.deref().as_ref()
//     }
// }

// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
    fn as_mut(&mut self) -> &mut U {
        (*self).as_mut()
    }
}

// FIXME (#23442): replace the above impl for &mut with the following more general one:
// // AsMut lifts over DerefMut
// impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
//     fn as_mut(&mut self) -> &mut U {
//         self.deref_mut().as_mut()
//     }
// }

// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
    fn into(self) -> U {
        U::from(self)
    }
}

// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
    fn from(t: T) -> T { t }
}

// TryFrom implies TryInto
#[unstable(feature = "try_from", issue = "33417")]
impl<T, U> TryInto<U> for T where U: TryFrom<T> {
    type Err = U::Err;

    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

////////////////////////////////////////////////////////////////////////////////
// CONCRETE IMPLS
////////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
    fn as_ref(&self) -> &[T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}
<|endoftext|>


<commit_before>//! Module providing the TermLogger Implementation

use log::{
    set_boxed_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record, SetLoggerError,
};
use std::error;
use std::fmt;
use std::io::{Error, Write};
use std::sync::Mutex;
use term;
use term::{color, StderrTerminal, StdoutTerminal, Terminal};

use self::TermLogError::{SetLogger, Term};
use super::logging::*;

use crate::{Config, SharedLogger};

/// TermLogger error type.
#[derive(Debug)]
pub enum TermLogError {
    ///The type returned by set_logger if set_logger has already been called.
    SetLogger(SetLoggerError),

    ///TermLogger initialization might also fail if stdout or stderr could not be opened,
    ///e.g. when no tty is attached to the process, it runs detached in the background, etc
    /// This is represented by the `Term` Kind
    Term,
}

impl fmt::Display for TermLogError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use std::error::Error as FmtError;

        write!(f, "{}", self.description())
    }
}

impl error::Error for TermLogError {
    fn description(&self) -> &str {
        match *self {
            SetLogger(ref err) => err.description(),
            Term => "A terminal could not be opened",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            SetLogger(ref err) => Some(err),
            Term => None,
        }
    }
}

impl From<SetLoggerError> for TermLogError {
    fn from(error: SetLoggerError) -> Self {
        SetLogger(error)
    }
}

enum StdTerminal {
    Stderr(Box<StderrTerminal>),
    Stdout(Box<StdoutTerminal>),
}

impl StdTerminal {
    fn flush(&mut self) -> Result<(), Error> {
        match self {
            StdTerminal::Stderr(term) => term.flush(),
            StdTerminal::Stdout(term) => term.flush(),
        }
    }
}

struct OutputStreams {
    err: StdTerminal,
    out: StdTerminal,
}

/// Specifies which streams should be used when logging
pub enum TerminalMode {
    /// Only use Stdout
    Stdout,
    /// Only use Stderr
    Stderr,
    /// Use Stderr for Errors and Stdout otherwise
    Mixed,
}

impl Default for TerminalMode {
    fn default() -> TerminalMode {
        TerminalMode::Mixed
    }
}

/// The TermLogger struct. Provides a stderr/out based Logger implementation
///
/// Supports colored output
pub struct TermLogger {
    level: LevelFilter,
    config: Config,
    streams: Mutex<OutputStreams>,
}

impl TermLogger {
    /// init function. Globally initializes the TermLogger as the one and only used log facility.
    ///
    /// Takes the desired `Level` and `Config` as arguments. They cannot be changed later on.
    /// Fails if another Logger was already initialized.
    ///
    /// # Examples
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let _ = TermLogger::init(LevelFilter::Info, Config::default(), TerminalMode::Mixed);
    /// # }
    /// ```
    pub fn init(
        log_level: LevelFilter,
        config: Config,
        mode: TerminalMode,
    ) -> Result<(), TermLogError> {
        let logger = TermLogger::new(log_level, config, mode).ok_or(Term)?;
        set_max_level(log_level.clone());
        set_boxed_logger(logger)?;
        Ok(())
    }

    /// allows to create a new logger, that can be independently used, no matter whats globally set.
    ///
    /// no macros are provided for this case and you probably
    /// dont want to use this function, but `init()`, if you dont want to build a `CombinedLogger`.
    ///
    /// Takes the desired `Level` and `Config` as arguments. They cannot be changed later on.
    ///
    /// Returns a `Box`ed TermLogger, or None if a terminal couldn't be opened.
    ///
    /// # Examples
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let term_logger = TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed).unwrap();
    /// # }
    /// ```
    pub fn new(
        log_level: LevelFilter,
        config: Config,
        mode: TerminalMode,
    ) -> Option<Box<TermLogger>> {
        let streams = match mode {
            TerminalMode::Stdout => term::stdout().and_then(|stdout| {
                term::stdout().map(|stdout2| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stdout(stdout),
                        out: StdTerminal::Stdout(stdout2),
                    })
                })
            }),
            TerminalMode::Stderr => term::stderr().and_then(|stderr| {
                term::stderr().map(|stderr2| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stderr(stderr),
                        out: StdTerminal::Stderr(stderr2),
                    })
                })
            }),
            TerminalMode::Mixed => term::stderr().and_then(|stderr| {
                term::stdout().map(|stdout| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stderr(stderr),
                        out: StdTerminal::Stdout(stdout),
                    })
                })
            }),
        };

        streams.map(|streams| {
            Box::new(TermLogger {
                level: log_level,
                config: config,
                streams: streams,
            })
        })
    }

    fn try_log_term<W>(
        &self,
        record: &Record<'_>,
        term_lock: &mut Box<dyn Terminal<Output = W> + Send>,
    ) -> Result<(), Error>
    where
        W: Write + Sized,
    {
        let color = match record.level() {
            Level::Error => color::RED,
            Level::Warn => color::YELLOW,
            Level::Info => color::BLUE,
            Level::Debug => color::CYAN,
            Level::Trace => color::WHITE,
        };

        if self.config.time <= record.level() {
            write_time(&mut *term_lock, &self.config)?;
        }

        if self.config.level <= record.level() {
            term_lock.fg(color)?;
            write_level(record, &mut *term_lock)?;
            term_lock.reset()?;
        }

        if self.config.thread <= record.level() {
            write_thread_id(&mut *term_lock)?;
        }

        if self.config.target <= record.level() {
            write_target(record, &mut *term_lock)?;
        }

        if self.config.location <= record.level() {
            write_location(record, &mut *term_lock)?;
        }

        write_args(record, &mut *term_lock)
    }

    fn try_log(&self, record: &Record<'_>) -> Result<(), Error> {
        if self.enabled(record.metadata()) {
            if should_skip(&self.config, record) {
                return Ok(());
            }

            let mut streams = self.streams.lock().unwrap();

            if record.level() == Level::Error {
                match streams.err {
                    StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
                    StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
                }
            } else {
                match streams.out {
                    StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
                    StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
                }
            }
        } else {
            Ok(())
        }
    }
}

impl Log for TermLogger {
    fn enabled(&self, metadata: &Metadata<'_>) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &Record<'_>) {
        let _ = self.try_log(record);
    }

    fn flush(&self) {
        let mut streams = self.streams.lock().unwrap();
        let _ = streams.out.flush();
        let _ = streams.err.flush();
    }
}

impl SharedLogger for TermLogger {
    fn level(&self) -> LevelFilter {
        self.level
    }

    fn config(&self) -> Option<&Config> {
        Some(&self.config)
    }

    fn as_log(self: Box<Self>) -> Box<dyn Log> {
        Box::new(*self)
    }
}
<commit_msg>Add further documentation on how to deal with `TermLogger` failing<commit_after>//! Module providing the TermLogger Implementation

use log::{
    set_boxed_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record, SetLoggerError,
};
use std::error;
use std::fmt;
use std::io::{Error, Write};
use std::sync::Mutex;
use term;
use term::{color, StderrTerminal, StdoutTerminal, Terminal};

use self::TermLogError::{SetLogger, Term};
use super::logging::*;

use crate::{Config, SharedLogger};

/// TermLogger error type.
#[derive(Debug)]
pub enum TermLogError {
    ///The type returned by set_logger if set_logger has already been called.
    SetLogger(SetLoggerError),

    ///TermLogger initialization might also fail if stdout or stderr could not be opened,
    ///e.g. when no tty is attached to the process, it runs detached in the background, etc
    /// This is represented by the `Term` Kind
    Term,
}

impl fmt::Display for TermLogError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use std::error::Error as FmtError;

        write!(f, "{}", self.description())
    }
}

impl error::Error for TermLogError {
    fn description(&self) -> &str {
        match *self {
            SetLogger(ref err) => err.description(),
            Term => "A terminal could not be opened",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            SetLogger(ref err) => Some(err),
            Term => None,
        }
    }
}

impl From<SetLoggerError> for TermLogError {
    fn from(error: SetLoggerError) -> Self {
        SetLogger(error)
    }
}

enum StdTerminal {
    Stderr(Box<StderrTerminal>),
    Stdout(Box<StdoutTerminal>),
}

impl StdTerminal {
    fn flush(&mut self) -> Result<(), Error> {
        match self {
            StdTerminal::Stderr(term) => term.flush(),
            StdTerminal::Stdout(term) => term.flush(),
        }
    }
}

struct OutputStreams {
    err: StdTerminal,
    out: StdTerminal,
}

/// Specifies which streams should be used when logging
pub enum TerminalMode {
    /// Only use Stdout
    Stdout,
    /// Only use Stderr
    Stderr,
    /// Use Stderr for Errors and Stdout otherwise
    Mixed,
}

impl Default for TerminalMode {
    fn default() -> TerminalMode {
        TerminalMode::Mixed
    }
}

/// The TermLogger struct. Provides a stderr/out based Logger implementation
///
/// Supports colored output
pub struct TermLogger {
    level: LevelFilter,
    config: Config,
    streams: Mutex<OutputStreams>,
}

impl TermLogger {
    /// init function. Globally initializes the TermLogger as the one and only used log facility.
    ///
    /// Takes the desired `Level` and `Config` as arguments. They cannot be changed later on.
    /// Fails if another Logger was already initialized or if a terminal couldn't be opened.
    ///
    /// Workaround the latter by either
    /// - panic'ing (not recommended). e.g. `TermLogger::init(LevelFilter::Warn, Config::default(), TerminalMode::Mixed).unwrap()`
    /// - silently ignoring (little better). e.g. `let _ = TermLogger::init(LevelFilter::Warn, Config::default(), TerminalMode::Mixed);`
    /// - falling back:
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// if let Err(_) = TermLogger::init(LevelFilter::Warn, Config::default(), TerminalMode::Mixed) {
    ///     SimpleLogger::init(LevelFilter::Warn, Config::default()).expect("No logger should be already set")
    /// }
    /// # }
    /// ```
    ///
    /// # Examples
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// TermLogger::init(LevelFilter::Info, Config::default(), TerminalMode::Mixed).expect("No interactive terminal");
    /// # }
    /// ```
    pub fn init(
        log_level: LevelFilter,
        config: Config,
        mode: TerminalMode,
    ) -> Result<(), TermLogError> {
        let logger = TermLogger::new(log_level, config, mode).ok_or(Term)?;
        set_max_level(log_level.clone());
        set_boxed_logger(logger)?;
        Ok(())
    }

    /// allows to create a new logger, that can be independently used, no matter whats globally set.
    ///
    /// no macros are provided for this case and you probably
    /// dont want to use this function, but `init()`, if you dont want to build a `CombinedLogger`.
    ///
    /// Takes the desired `Level` and `Config` as arguments. They cannot be changed later on.
    ///
    /// Returns a `Box`ed TermLogger, or None if a terminal couldn't be opened.
    /// Workaround this by either
    /// - panic'ing (not recommended). e.g. `TermLogger::new(LevelFilter::Warn, Config::default(), TerminalMode::Mixed).unwrap()`
    /// - silently ignoring (little better). e.g. `if let Some(logger) = TermLogger::new(LevelFilter::Warn, Config::default(), TerminalMode::Mixed) { /*...*/ }`
    /// - falling back:
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let mut multiple = vec![];
    /// match TermLogger::new(LevelFilter::Warn, Config::default(), TerminalMode::Mixed) {
    ///     Some(logger) => multiple.push(logger as Box<dyn SharedLogger>),
    ///     None => multiple.push(SimpleLogger::new(LevelFilter::Warn, Config::default())),
    /// }
    /// // Add more ...
    /// # }
    /// ```
    ///
    /// # Examples
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let term_logger = TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed).expect("No interactive terminal");
    /// # }
    /// ```
    pub fn new(
        log_level: LevelFilter,
        config: Config,
        mode: TerminalMode,
    ) -> Option<Box<TermLogger>> {
        let streams = match mode {
            TerminalMode::Stdout => term::stdout().and_then(|stdout| {
                term::stdout().map(|stdout2| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stdout(stdout),
                        out: StdTerminal::Stdout(stdout2),
                    })
                })
            }),
            TerminalMode::Stderr => term::stderr().and_then(|stderr| {
                term::stderr().map(|stderr2| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stderr(stderr),
                        out: StdTerminal::Stderr(stderr2),
                    })
                })
            }),
            TerminalMode::Mixed => term::stderr().and_then(|stderr| {
                term::stdout().map(|stdout| {
                    Mutex::new(OutputStreams {
                        err: StdTerminal::Stderr(stderr),
                        out: StdTerminal::Stdout(stdout),
                    })
                })
            }),
        };

        streams.map(|streams| {
            Box::new(TermLogger {
                level: log_level,
                config: config,
                streams: streams,
            })
        })
    }

    fn try_log_term<W>(
        &self,
        record: &Record<'_>,
        term_lock: &mut Box<dyn Terminal<Output = W> + Send>,
    ) -> Result<(), Error>
    where
        W: Write + Sized,
    {
        let color = match record.level() {
            Level::Error => color::RED,
            Level::Warn => color::YELLOW,
            Level::Info => color::BLUE,
            Level::Debug => color::CYAN,
            Level::Trace => color::WHITE,
        };

        if self.config.time <= record.level() {
            write_time(&mut *term_lock, &self.config)?;
        }

        if self.config.level <= record.level() {
            term_lock.fg(color)?;
            write_level(record, &mut *term_lock)?;
            term_lock.reset()?;
        }

        if self.config.thread <= record.level() {
            write_thread_id(&mut *term_lock)?;
        }

        if self.config.target <= record.level() {
            write_target(record, &mut *term_lock)?;
        }

        if self.config.location <= record.level() {
            write_location(record, &mut *term_lock)?;
        }

        write_args(record, &mut *term_lock)
    }

    fn try_log(&self, record: &Record<'_>) -> Result<(), Error> {
        if self.enabled(record.metadata()) {
            if should_skip(&self.config, record) {
                return Ok(());
            }

            let mut streams = self.streams.lock().unwrap();

            if record.level() == Level::Error {
                match streams.err {
                    StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
                    StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
                }
            } else {
                match streams.out {
                    StdTerminal::Stderr(ref mut term) => self.try_log_term(record, term),
                    StdTerminal::Stdout(ref mut term) => self.try_log_term(record, term),
                }
            }
        } else {
            Ok(())
        }
    }
}

impl Log for TermLogger {
    fn enabled(&self, metadata: &Metadata<'_>) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &Record<'_>) {
        let _ = self.try_log(record);
    }

    fn flush(&self) {
        let mut streams = self.streams.lock().unwrap();
        let _ = streams.out.flush();
        let _ = streams.err.flush();
    }
}

impl SharedLogger for TermLogger {
    fn level(&self) -> LevelFilter {
        self.level
    }

    fn config(&self) -> Option<&Config> {
        Some(&self.config)
    }

    fn as_log(self: Box<Self>) -> Box<dyn Log> {
        Box::new(*self)
    }
}
<|endoftext|>


<commit_before>use hir::{db::HirDatabase, ModPath};
use ra_syntax::{
    ast::{self, AstNode},
    SyntaxNode,
};

use crate::{
    assist_ctx::{ActionBuilder, Assist, AssistCtx},
    auto_import_text_edit, AssistId, ImportsLocator,
};

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap<|>::new();
// }
// ```
pub(crate) fn auto_import<F: ImportsLocator>(
    ctx: AssistCtx<impl HirDatabase>,
    imports_locator: &mut F,
) -> Option<Assist> {
    let path_to_import: ast::Path = ctx.find_node_at_offset()?;
    let path_to_import_syntax = path_to_import.syntax();
    if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }
    let name_to_import =
        path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string();

    let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;
    if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() {
        return None;
    }

    let proposed_imports = imports_locator
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<std::collections::BTreeSet<_>>();
    if proposed_imports.is_empty() {
        return None;
    }

    ctx.add_assist_group(
        AssistId("auto_import"),
        format!("Import {}", path_to_import_syntax),
        || {
            proposed_imports
                .into_iter()
                .map(|import| import_to_action(import, &position, &path_to_import_syntax))
                .collect()
        },
    )
}

fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
    let mut action_builder = ActionBuilder::default();
    action_builder.label(format!("Import `{}`", &import));
    auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
    action_builder
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::helpers::{
        check_assist_with_imports_locator, check_assist_with_imports_locator_not_applicable,
        TestImportsLocator,
    };

    #[test]
    fn applicable_when_found_an_import() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }
}
<commit_msg>Use proper import name in the label<commit_after>use hir::{db::HirDatabase, ModPath};
use ra_syntax::{
    ast::{self, AstNode},
    SyntaxNode,
};

use crate::{
    assist_ctx::{ActionBuilder, Assist, AssistCtx},
    auto_import_text_edit, AssistId, ImportsLocator,
};

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap<|>::new();
// }
// ```
pub(crate) fn auto_import<F: ImportsLocator>(
    ctx: AssistCtx<impl HirDatabase>,
    imports_locator: &mut F,
) -> Option<Assist> {
    let path_to_import: ast::Path = ctx.find_node_at_offset()?;
    let path_to_import_syntax = path_to_import.syntax();
    if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }
    let name_to_import =
        path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string();

    let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;
    if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() {
        return None;
    }

    let proposed_imports = imports_locator
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<std::collections::BTreeSet<_>>();
    if proposed_imports.is_empty() {
        return None;
    }

    ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || {
        proposed_imports
            .into_iter()
            .map(|import| import_to_action(import, &position, &path_to_import_syntax))
            .collect()
    })
}

fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
    let mut action_builder = ActionBuilder::default();
    action_builder.label(format!("Import `{}`", &import));
    auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
    action_builder
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::helpers::{
        check_assist_with_imports_locator, check_assist_with_imports_locator_not_applicable,
        TestImportsLocator,
    };

    #[test]
    fn applicable_when_found_an_import() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_with_imports_locator_not_applicable(
            auto_import,
            TestImportsLocator::new,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist_with_imports_locator(
            auto_import,
            TestImportsLocator::new,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }
}
<|endoftext|>