<commit_before>use park::DefaultPark;
use worker::{WorkerId};

use std::cell::UnsafeCell;
use std::fmt;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::{self, Acquire, AcqRel, Relaxed};
use std::time::{Duration, Instant};

/// State associated with a thread in the thread pool.
///
/// The pool manages a number of threads. Some of those threads are considered
/// "primary" threads and process the work queue. When a task being run on a
/// primary thread enters a blocking context, the responsibility of processing
/// the work queue must be handed off to another thread. This is done by first
/// checking for idle threads on the backup stack. If one is found, the worker
/// token (`WorkerId`) is handed off to that running thread. If none are found,
/// a new thread is spawned.
///
/// This state manages the exchange. A thread that is idle, not assigned to a
/// work queue, sits around for a specified amount of time. When the worker
/// token is handed off, it is first stored in `handoff`. The backup thread is
/// then signaled. At this point, the backup thread wakes up from sleep and
/// reads `handoff`. At that point, it has been promoted to a primary thread and
/// will begin processing inbound work on the work queue.
///
/// The name `Backup` isn't really great for what the type does, but I have not
/// come up with a better name... Maybe it should just be named `Thread`.
#[derive(Debug)]
pub(crate) struct Backup {
    /// Worker ID that is being handed to this thread.
    handoff: UnsafeCell<Option<WorkerId>>,

    /// Thread state.
    ///
    /// This tracks:
    ///
    /// * Is queued flag
    /// * If the pool is shutting down.
    /// * If the thread is running
    state: AtomicUsize,

    /// Next entry in the Treiber stack.
    next_sleeper: UnsafeCell<BackupId>,

    /// Used to put the thread to sleep
    park: DefaultPark,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub(crate) struct BackupId(pub(crate) usize);

#[derive(Debug)]
pub(crate) enum Handoff {
    Worker(WorkerId),
    Idle,
    Terminated,
}

/// Tracks thread state.
#[derive(Clone, Copy, Eq, PartialEq)]
struct State(usize);

/// Set when the worker is pushed onto the scheduler's stack of sleeping
/// threads.
///
/// This flag also serves as a "notification" bit. If another thread is
/// attempting to hand off a worker to the backup thread, then the pushed bit
/// will not be set when the thread tries to shutdown.
pub const PUSHED: usize = 0b001;

/// Set when the thread is running
pub const RUNNING: usize = 0b010;

/// Set when the thread pool has terminated
pub const TERMINATED: usize = 0b100;

// ===== impl Backup =====

impl Backup {
    pub fn new() -> Backup {
        Backup {
            handoff: UnsafeCell::new(None),
            state: AtomicUsize::new(State::new().into()),
            next_sleeper: UnsafeCell::new(BackupId(0)),
            park: DefaultPark::new(),
        }
    }

    /// Called when the thread is starting
    pub fn start(&self, worker_id: &WorkerId) {
        debug_assert!({
            let state: State = self.state.load(Relaxed).into();

            debug_assert!(!state.is_pushed());
            debug_assert!(state.is_running());
            debug_assert!(!state.is_terminated());

            true
        });

        // The handoff value is equal to `worker_id`
        debug_assert_eq!(unsafe { (*self.handoff.get()).as_ref()  }, Some(worker_id));

        unsafe { *self.handoff.get() = None; }
    }

    pub fn is_running(&self) -> bool {
        let state: State = self.state.load(Relaxed).into();
        state.is_running()
    }

    /// Hands off the worker to a thread.
    ///
    /// Returns `true` if the thread needs to be spawned.
    pub fn worker_handoff(&self, worker_id: WorkerId) -> bool {
        unsafe {
            // The backup worker should not already have been handoff a worker.
            debug_assert!((*self.handoff.get()).is_none());

            // Set the handoff
            *self.handoff.get() = Some(worker_id);
        }

        // This *probably* can just be `Release`... memory orderings, how do
        // they work?
        let prev = State::worker_handoff(&self.state);
        debug_assert!(prev.is_pushed());

        if prev.is_running() {
            // Wakeup the backup thread
            self.park.notify();
            false
        } else {
            true
        }
    }

    /// Terminate the worker
    pub fn signal_stop(&self) {
        let prev: State = self.state.fetch_xor(TERMINATED | PUSHED, AcqRel).into();

        debug_assert!(!prev.is_terminated());
        debug_assert!(prev.is_pushed());

        if prev.is_running() {
            self.park.notify();
        }
    }

    /// Release the worker
    pub fn release(&self) {
        let prev: State = self.state.fetch_xor(RUNNING, AcqRel).into();

        debug_assert!(prev.is_running());
    }

    /// Wait for a worker handoff
    pub fn wait_for_handoff(&self, timeout: Option<Duration>) -> Handoff {
        let sleep_until = timeout.map(|dur| Instant::now() + dur);
        let mut state: State = self.state.load(Acquire).into();

        // Run in a loop since there can be spurious wakeups
        loop {
            if !state.is_pushed() {
                if state.is_terminated() {
                    return Handoff::Terminated;
                }

                let worker_id = unsafe {
                    (*self.handoff.get()).take()
                        .expect("no worker handoff")
                };
                return Handoff::Worker(worker_id);
            }

            match sleep_until {
                None => {
                    self.park.park_sync(None);
                    state = self.state.load(Acquire).into();
                }
                Some(when) => {
                    let now = Instant::now();

                    if now < when {
                        self.park.park_sync(Some(when - now));
                        state = self.state.load(Acquire).into();
                    } else {
                        debug_assert!(state.is_running());

                        // Transition out of running
                        let mut next = state;
                        next.unset_running();

                        let actual = self.state.compare_and_swap(
                            state.into(),
                            next.into(),
                            AcqRel).into();

                        if actual == state {
                            debug_assert!(!next.is_running());
                            return Handoff::Idle;
                        }

                        state = actual;
                    }
                }
            }
        }
    }

    pub fn is_pushed(&self) -> bool {
        let state: State = self.state.load(Relaxed).into();
        state.is_pushed()
    }

    pub fn set_pushed(&self, ordering: Ordering) {
        let prev: State = self.state.fetch_or(PUSHED, ordering).into();
        debug_assert!(!prev.is_pushed());
    }

    #[inline]
    pub fn next_sleeper(&self) -> BackupId {
        unsafe { *self.next_sleeper.get() }
    }

    #[inline]
    pub fn set_next_sleeper(&self, val: BackupId) {
        unsafe { *self.next_sleeper.get() = val; }
    }
}

// ===== impl State =====

impl State {
    /// Returns a new, default, thread `State`
    pub fn new() -> State {
        State(0)
    }

    /// Returns true if the thread entry is pushed in the sleeper stack
    pub fn is_pushed(&self) -> bool {
        self.0 & PUSHED == PUSHED
    }

    pub fn set_pushed(&mut self) {
        self.0 |= PUSHED;
    }

    fn unset_pushed(&mut self) {
        self.0 &= !PUSHED;
    }

    pub fn is_running(&self) -> bool {
        self.0 & RUNNING == RUNNING
    }

    pub fn set_running(&mut self) {
        self.0 |= RUNNING;
    }

    pub fn unset_running(&mut self) {
        self.0 &= !RUNNING;
    }

    pub fn is_terminated(&self) -> bool {
        self.0 & TERMINATED == TERMINATED
    }

    fn worker_handoff(state: &AtomicUsize) -> State {
        let mut curr: State = state.load(Acquire).into();

        loop {
            let mut next = curr;
            next.set_running();
            next.unset_pushed();

            let actual = state.compare_and_swap(
                curr.into(), next.into(), AcqRel).into();

            if actual == curr {
                return curr;
            }

            curr = actual;
        }
    }
}

impl From<usize> for State {
    fn from(src: usize) -> State {
        State(src)
    }
}

impl From<State> for usize {
    fn from(src: State) -> usize {
        src.0
    }
}

impl fmt::Debug for State {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("backup::State")
            .field("is_pushed", &self.is_pushed())
            .field("is_running", &self.is_running())
            .field("is_terminated", &self.is_terminated())
            .finish()
    }
}
<commit_msg>threadpool: remove unused fn (#822)<commit_after>use park::DefaultPark;
use worker::{WorkerId};

use std::cell::UnsafeCell;
use std::fmt;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::{self, Acquire, AcqRel, Relaxed};
use std::time::{Duration, Instant};

/// State associated with a thread in the thread pool.
///
/// The pool manages a number of threads. Some of those threads are considered
/// "primary" threads and process the work queue. When a task being run on a
/// primary thread enters a blocking context, the responsibility of processing
/// the work queue must be handed off to another thread. This is done by first
/// checking for idle threads on the backup stack. If one is found, the worker
/// token (`WorkerId`) is handed off to that running thread. If none are found,
/// a new thread is spawned.
///
/// This state manages the exchange. A thread that is idle, not assigned to a
/// work queue, sits around for a specified amount of time. When the worker
/// token is handed off, it is first stored in `handoff`. The backup thread is
/// then signaled. At this point, the backup thread wakes up from sleep and
/// reads `handoff`. At that point, it has been promoted to a primary thread and
/// will begin processing inbound work on the work queue.
///
/// The name `Backup` isn't really great for what the type does, but I have not
/// come up with a better name... Maybe it should just be named `Thread`.
#[derive(Debug)]
pub(crate) struct Backup {
    /// Worker ID that is being handed to this thread.
    handoff: UnsafeCell<Option<WorkerId>>,

    /// Thread state.
    ///
    /// This tracks:
    ///
    /// * Is queued flag
    /// * If the pool is shutting down.
    /// * If the thread is running
    state: AtomicUsize,

    /// Next entry in the Treiber stack.
    next_sleeper: UnsafeCell<BackupId>,

    /// Used to put the thread to sleep
    park: DefaultPark,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub(crate) struct BackupId(pub(crate) usize);

#[derive(Debug)]
pub(crate) enum Handoff {
    Worker(WorkerId),
    Idle,
    Terminated,
}

/// Tracks thread state.
#[derive(Clone, Copy, Eq, PartialEq)]
struct State(usize);

/// Set when the worker is pushed onto the scheduler's stack of sleeping
/// threads.
///
/// This flag also serves as a "notification" bit. If another thread is
/// attempting to hand off a worker to the backup thread, then the pushed bit
/// will not be set when the thread tries to shutdown.
pub const PUSHED: usize = 0b001;

/// Set when the thread is running
pub const RUNNING: usize = 0b010;

/// Set when the thread pool has terminated
pub const TERMINATED: usize = 0b100;

// ===== impl Backup =====

impl Backup {
    pub fn new() -> Backup {
        Backup {
            handoff: UnsafeCell::new(None),
            state: AtomicUsize::new(State::new().into()),
            next_sleeper: UnsafeCell::new(BackupId(0)),
            park: DefaultPark::new(),
        }
    }

    /// Called when the thread is starting
    pub fn start(&self, worker_id: &WorkerId) {
        debug_assert!({
            let state: State = self.state.load(Relaxed).into();

            debug_assert!(!state.is_pushed());
            debug_assert!(state.is_running());
            debug_assert!(!state.is_terminated());

            true
        });

        // The handoff value is equal to `worker_id`
        debug_assert_eq!(unsafe { (*self.handoff.get()).as_ref()  }, Some(worker_id));

        unsafe { *self.handoff.get() = None; }
    }

    pub fn is_running(&self) -> bool {
        let state: State = self.state.load(Relaxed).into();
        state.is_running()
    }

    /// Hands off the worker to a thread.
    ///
    /// Returns `true` if the thread needs to be spawned.
    pub fn worker_handoff(&self, worker_id: WorkerId) -> bool {
        unsafe {
            // The backup worker should not already have been handoff a worker.
            debug_assert!((*self.handoff.get()).is_none());

            // Set the handoff
            *self.handoff.get() = Some(worker_id);
        }

        // This *probably* can just be `Release`... memory orderings, how do
        // they work?
        let prev = State::worker_handoff(&self.state);
        debug_assert!(prev.is_pushed());

        if prev.is_running() {
            // Wakeup the backup thread
            self.park.notify();
            false
        } else {
            true
        }
    }

    /// Terminate the worker
    pub fn signal_stop(&self) {
        let prev: State = self.state.fetch_xor(TERMINATED | PUSHED, AcqRel).into();

        debug_assert!(!prev.is_terminated());
        debug_assert!(prev.is_pushed());

        if prev.is_running() {
            self.park.notify();
        }
    }

    /// Release the worker
    pub fn release(&self) {
        let prev: State = self.state.fetch_xor(RUNNING, AcqRel).into();

        debug_assert!(prev.is_running());
    }

    /// Wait for a worker handoff
    pub fn wait_for_handoff(&self, timeout: Option<Duration>) -> Handoff {
        let sleep_until = timeout.map(|dur| Instant::now() + dur);
        let mut state: State = self.state.load(Acquire).into();

        // Run in a loop since there can be spurious wakeups
        loop {
            if !state.is_pushed() {
                if state.is_terminated() {
                    return Handoff::Terminated;
                }

                let worker_id = unsafe {
                    (*self.handoff.get()).take()
                        .expect("no worker handoff")
                };
                return Handoff::Worker(worker_id);
            }

            match sleep_until {
                None => {
                    self.park.park_sync(None);
                    state = self.state.load(Acquire).into();
                }
                Some(when) => {
                    let now = Instant::now();

                    if now < when {
                        self.park.park_sync(Some(when - now));
                        state = self.state.load(Acquire).into();
                    } else {
                        debug_assert!(state.is_running());

                        // Transition out of running
                        let mut next = state;
                        next.unset_running();

                        let actual = self.state.compare_and_swap(
                            state.into(),
                            next.into(),
                            AcqRel).into();

                        if actual == state {
                            debug_assert!(!next.is_running());
                            return Handoff::Idle;
                        }

                        state = actual;
                    }
                }
            }
        }
    }

    pub fn is_pushed(&self) -> bool {
        let state: State = self.state.load(Relaxed).into();
        state.is_pushed()
    }

    pub fn set_pushed(&self, ordering: Ordering) {
        let prev: State = self.state.fetch_or(PUSHED, ordering).into();
        debug_assert!(!prev.is_pushed());
    }

    #[inline]
    pub fn next_sleeper(&self) -> BackupId {
        unsafe { *self.next_sleeper.get() }
    }

    #[inline]
    pub fn set_next_sleeper(&self, val: BackupId) {
        unsafe { *self.next_sleeper.get() = val; }
    }
}

// ===== impl State =====

impl State {
    /// Returns a new, default, thread `State`
    pub fn new() -> State {
        State(0)
    }

    /// Returns true if the thread entry is pushed in the sleeper stack
    pub fn is_pushed(&self) -> bool {
        self.0 & PUSHED == PUSHED
    }

    fn unset_pushed(&mut self) {
        self.0 &= !PUSHED;
    }

    pub fn is_running(&self) -> bool {
        self.0 & RUNNING == RUNNING
    }

    pub fn set_running(&mut self) {
        self.0 |= RUNNING;
    }

    pub fn unset_running(&mut self) {
        self.0 &= !RUNNING;
    }

    pub fn is_terminated(&self) -> bool {
        self.0 & TERMINATED == TERMINATED
    }

    fn worker_handoff(state: &AtomicUsize) -> State {
        let mut curr: State = state.load(Acquire).into();

        loop {
            let mut next = curr;
            next.set_running();
            next.unset_pushed();

            let actual = state.compare_and_swap(
                curr.into(), next.into(), AcqRel).into();

            if actual == curr {
                return curr;
            }

            curr = actual;
        }
    }
}

impl From<usize> for State {
    fn from(src: usize) -> State {
        State(src)
    }
}

impl From<State> for usize {
    fn from(src: State) -> usize {
        src.0
    }
}

impl fmt::Debug for State {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("backup::State")
            .field("is_pushed", &self.is_pushed())
            .field("is_running", &self.is_running())
            .field("is_terminated", &self.is_terminated())
            .finish()
    }
}
<|endoftext|>


<commit_before>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

// use TheModule::prelude::*;

//

fn _basic()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );
}

//

fn _split_with_option_preserving_empty()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_preserving_delimeters()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_stripping()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .preserving_delimeters( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "c" ] );
}

//

fn _basic_split_generic()
{
  let src = "abc";
  let iter = TheModule::string::split_generic::< &str >()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let iter = TheModule::string::split_generic::< String >()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  /* */

  let src = "abc";
  let iter = TheModule::string::split_generic::< Vec< &str > >()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "abc", ] );

  let src = "abc";
  let iter = TheModule::string::split_generic::< Vec< &str > >()
  .src( src )
  .delimeter( vec![ "a", "b", "" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let iter = TheModule::string::split_generic::< Vec< &str > >()
  .src( src )
  .delimeter( vec![ "b", "d" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

test_suite!
{
  basic,
  split_with_option_preserving_empty,
  split_with_option_preserving_delimeters,
  split_with_option_stripping,
  basic_split_generic,
}
<commit_msg>Rewrite test routine `basic_split_generic`, transform it to `basic_split_with_vector`<commit_after>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

// use TheModule::prelude::*;

//

fn _basic()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );
}

//

fn _split_with_option_preserving_empty()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_preserving_delimeters()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_stripping()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .preserving_delimeters( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "c" ] );
}

//

fn _basic_split_with_vector()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "abc", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "a", "b", "" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "b", "d" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

test_suite!
{
  basic,
  split_with_option_preserving_empty,
  split_with_option_preserving_delimeters,
  split_with_option_stripping,
  basic_split_with_vector,
}
<|endoftext|>


<commit_before>//! Compile time optimized maps
#[crate_id="github.com/sfackler/rust-phf/phf"];
#[doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")];
#[crate_type="rlib"];
#[crate_type="dylib"];
#[warn(missing_doc)];

use std::iter;
use std::vec;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    len: uint,
    #[doc(hidden)]
    k1: u64,
    #[doc(hidden)]
    k2: u64,
    #[doc(hidden)]
    disps: &'static [(uint, uint)],
    #[doc(hidden)]
    entries: &'static [Option<(&'static str, T)>],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = s.hash_keyed(k1, k2);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.len
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        match self.entries[displace(f1, f2, d1, d2) % self.entries.len()] {
            Some((s, ref value)) if s == *key => Some(value),
            _ => None
        }
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary order.
    #[inline]
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries {
            iter: self.entries.iter().filter_map(|e| {
                match *e {
                    Some((key, ref value)) => Some((key, value)),
                    None => None
                }
            })
        }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary order.
    #[inline]
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary order.
    #[inline]
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    priv iter: iter::FilterMap<'a,
                               &'a Option<(&'static str, T)>,
                               (&'static str, &'a T),
                               vec::Items<'a, Option<(&'static str, T)>>>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<commit_msg>Update for new hash API<commit_after>//! Compile time optimized maps
#[crate_id="github.com/sfackler/rust-phf/phf"];
#[doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")];
#[crate_type="rlib"];
#[crate_type="dylib"];
#[warn(missing_doc)];

use std::iter;
use std::vec;
use std::hash::Hasher;
use std::hash::sip::SipHasher;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    len: uint,
    #[doc(hidden)]
    k1: u64,
    #[doc(hidden)]
    k2: u64,
    #[doc(hidden)]
    disps: &'static [(uint, uint)],
    #[doc(hidden)]
    entries: &'static [Option<(&'static str, T)>],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = SipHasher::new_with_keys(k1, k2).hash(&s);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.len
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        match self.entries[displace(f1, f2, d1, d2) % self.entries.len()] {
            Some((s, ref value)) if s == *key => Some(value),
            _ => None
        }
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary order.
    #[inline]
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries {
            iter: self.entries.iter().filter_map(|e| {
                match *e {
                    Some((key, ref value)) => Some((key, value)),
                    None => None
                }
            })
        }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary order.
    #[inline]
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary order.
    #[inline]
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    priv iter: iter::FilterMap<'a,
                               &'a Option<(&'static str, T)>,
                               (&'static str, &'a T),
                               vec::Items<'a, Option<(&'static str, T)>>>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>mod event;
mod input;
use std::mem;
use std::fs::{File, OpenOptions};
use std::io::{self, Write, Read};
use std::os::unix::io::AsRawFd;
use libc::{TCSANOW, TIOCGWINSZ, termios, winsize, c_int, c_ulong};

pub use self::input::*;
pub use self::event::*;

extern {
    fn tcgetattr(filedes: c_int, termptr: *mut termios) -> c_int;
    fn tcsetattr(filedes: c_int, opt: c_int, termptr: *const termios) -> c_int;
    fn cfmakeraw(termptr: *mut termios);
    fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

#[derive(Debug)]
pub enum Error {
    TcGetAttr,
    TcSetAttr
}

pub struct Terminal {
    file: File,
    prev_termios: Option<termios>,
    pub max_width: u16,
    pub max_height: u16,
}

impl Terminal {
    /// Creates a new Terminal from the provided filename
    pub fn from(filename: &str) -> io::Result<Terminal> {
        let file = OpenOptions::new().write(true).read(true).open(filename)?;
        let fd = file.as_raw_fd();

        let mut terminal = Terminal {
            file: file,
            prev_termios: None,
            max_width: 80,
            max_height: 25
        };

        unsafe {
            let mut ws: winsize = mem::zeroed();
            if ioctl(fd, TIOCGWINSZ, &mut ws) != -1 {
                terminal.max_width = ws.ws_col;
                terminal.max_height = ws.ws_row;
            }
        }

        Ok(terminal)
    }

    pub fn set_raw_mode(&mut self) -> Result<(), Error> {
        let fd = self.file.as_raw_fd();

        unsafe {
            let mut ios: termios = mem::zeroed();

            // get the existing termios
            let result = tcgetattr(fd, &mut ios);
            if result != 0 {
                return Err(Error::TcGetAttr);
            }

            self.prev_termios = Some(ios);

            // enable raw mode
            cfmakeraw(&mut ios);

            // apply the raw mode termios
            let result = tcsetattr(fd, TCSANOW, &ios);
            if result != 0 {
                return Err(Error::TcSetAttr);
            }
        }

        Ok(())
    }

    pub fn events(&self) -> io::Result<Events<File>> {
        self.file.try_clone().map(Events::new)
    }
}

impl Read for Terminal {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.file.read(buf)
    }
}

impl Write for Terminal {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.file.write(buf)
    }

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

impl Drop for Terminal {
    fn drop(&mut self) {
        if let Some(opts) = self.prev_termios {
            let fd = self.file.as_raw_fd();

            // disable raw mode, by setting the original termios
            unsafe { tcsetattr(fd, TCSANOW, &opts); }
        }
    }
}

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

    #[test]
    fn terminal() {
        let mut term = Terminal::from("/dev/tty").expect("Unable to open /dev/tty");

        // if all is good, this should _not_ break the terminal, because the
        // Drop trait impl will clean up
        term.set_raw_mode().expect("Unable to enable raw mode");

        write!(term, "").unwrap();
        term.flush().unwrap();
    }
}
<commit_msg>Make ability to reset Terminal publicly available<commit_after>mod event;
mod input;
use std::mem;
use std::fs::{File, OpenOptions};
use std::io::{self, Write, Read};
use std::os::unix::io::AsRawFd;
use libc::{TCSANOW, TIOCGWINSZ, termios, winsize, c_int, c_ulong};

pub use self::input::*;
pub use self::event::*;

extern {
    fn tcgetattr(filedes: c_int, termptr: *mut termios) -> c_int;
    fn tcsetattr(filedes: c_int, opt: c_int, termptr: *const termios) -> c_int;
    fn cfmakeraw(termptr: *mut termios);
    fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

#[derive(Debug)]
pub enum Error {
    TcGetAttr,
    TcSetAttr
}

pub struct Terminal {
    file: File,
    prev_termios: Option<termios>,
    pub max_width: u16,
    pub max_height: u16,
}

impl Terminal {
    /// Creates a new Terminal from the provided filename
    pub fn from(filename: &str) -> io::Result<Terminal> {
        let file = OpenOptions::new().write(true).read(true).open(filename)?;
        let fd = file.as_raw_fd();

        let mut terminal = Terminal {
            file: file,
            prev_termios: None,
            max_width: 80,
            max_height: 25
        };

        unsafe {
            let mut ws: winsize = mem::zeroed();
            if ioctl(fd, TIOCGWINSZ, &mut ws) != -1 {
                terminal.max_width = ws.ws_col;
                terminal.max_height = ws.ws_row;
            }
        }

        Ok(terminal)
    }

    pub fn set_raw_mode(&mut self) -> Result<(), Error> {
        let fd = self.file.as_raw_fd();

        unsafe {
            let mut ios: termios = mem::zeroed();

            // get the existing termios
            let result = tcgetattr(fd, &mut ios);
            if result != 0 {
                return Err(Error::TcGetAttr);
            }

            self.prev_termios = Some(ios);

            // enable raw mode
            cfmakeraw(&mut ios);

            // apply the raw mode termios
            let result = tcsetattr(fd, TCSANOW, &ios);
            if result != 0 {
                return Err(Error::TcSetAttr);
            }
        }

        Ok(())
    }

    pub fn reset(&mut self) {
        if let Some(opts) = self.prev_termios {
            let fd = self.file.as_raw_fd();

            // disable raw mode, by setting the original termios
            unsafe { tcsetattr(fd, TCSANOW, &opts); }
        }
    }

    pub fn events(&self) -> io::Result<Events<File>> {
        self.file.try_clone().map(Events::new)
    }
}

impl Read for Terminal {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.file.read(buf)
    }
}

impl Write for Terminal {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.file.write(buf)
    }

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

impl Drop for Terminal {
    fn drop(&mut self) {
        self.reset();
    }
}

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

    #[test]
    fn terminal() {
        let mut term = Terminal::from("/dev/tty").expect("Unable to open /dev/tty");

        // if all is good, this should _not_ break the terminal, because the
        // Drop trait impl will clean up
        term.set_raw_mode().expect("Unable to enable raw mode");

        write!(term, "").unwrap();
        term.flush().unwrap();
    }
}
<|endoftext|>


<commit_before>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_trusted: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Vec<String>,
    pub RepoDigests: Option<Vec<String>>,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<u64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    // pub MacAddress: String,
    pub OnBuild: Option<String>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: Option<u64>,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
    pub swap: u64,
    pub total_swap: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub status: Option<String>,
    pub id: Option<String>,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Debug)]
pub enum BuildOutput {
    Stream(String),
    Err(String),
}

// fixme: all fields are options because PullInfo.progressDefault is sometimes an empty object instead of a null/absent value
#[derive(Clone, Debug, RustcDecodable)]
pub struct ProgressDetail {
    current: Option<u64>,
    total: Option<u64>,
    status: Option<String>, // fixme: it looks like this field isn't deserializing properly
}

#[derive(Clone, Debug, RustcDecodable)]
#[allow(non_snake_case)]
pub struct PullInfo {
    pub id: Option<String>,
    pub status: String,
    pub progress: Option<String>,
    pub progressDetail: Option<ProgressDetail>,
}

#[derive(Debug)]
pub enum PullOutput {
    Status {
        id: Option<String>,
        status: String,
        progress: Option<String>,
        progress_detail: Option<ProgressDetail>,
    },
    Err(String),
}

#[derive(Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<commit_msg>raw size is always returned as non useful -1 in listing<commit_after>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_trusted: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Vec<String>,
    pub RepoDigests: Option<Vec<String>>,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<u64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    // pub MacAddress: String,
    pub OnBuild: Option<String>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: Option<u64>,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
    pub swap: u64,
    pub total_swap: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub status: Option<String>,
    pub id: Option<String>,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Debug)]
pub enum BuildOutput {
    Stream(String),
    Err(String),
}

// fixme: all fields are options because PullInfo.progressDefault is sometimes an empty object instead of a null/absent value
#[derive(Clone, Debug, RustcDecodable)]
pub struct ProgressDetail {
    current: Option<u64>,
    total: Option<u64>,
    status: Option<String>, // fixme: it looks like this field isn't deserializing properly
}

#[derive(Clone, Debug, RustcDecodable)]
#[allow(non_snake_case)]
pub struct PullInfo {
    pub id: Option<String>,
    pub status: String,
    pub progress: Option<String>,
    pub progressDetail: Option<ProgressDetail>,
}

#[derive(Debug)]
pub enum PullOutput {
    Status {
        id: Option<String>,
        status: String,
        progress: Option<String>,
        progress_detail: Option<ProgressDetail>,
    },
    Err(String),
}

#[derive(Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<|endoftext|>


<commit_before>extern crate libc;

use std::old_io::{stdio, File, Open, ReadWrite, Command};
use std::old_io::process::StdioContainer;
use std::os::unix::prelude::AsRawFd;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {
        let it = format!("{}\n", line);
        self.file.write_str(it.as_slice());
    }

    fn read(&mut self) -> Option<String> {
        let res = match self.file.read_byte() {
            Ok(c) => {
                let character = c as char;
                Some(character.to_string())
            },
            Err(_) => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = File::open_mode(&path, Open, ReadWrite).unwrap();
        let dimension = TTY::get_window_size();
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    pub fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_slice()]);
    }

    fn get_window_size() -> (usize, usize) {
        let (w,h) = stdio::stdout_raw().winsize().unwrap();
        (w as usize, h as usize)
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        let container = StdioContainer::InheritFd(file.as_raw_fd());
        let output = Command::new("stty").args(args).stdin(container).output().unwrap();
        String::from_utf8(output.output).ok()
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}

#[cfg(test)]

#[test]
fn can_create_a_tty() {
    let mut tty = TTY::new();
    tty.write("##### a string        \n");
    //tty.read();
}
<commit_msg>Remove unfinished TTY test<commit_after>extern crate libc;

use std::old_io::{stdio, File, Open, ReadWrite, Command};
use std::old_io::process::StdioContainer;
use std::os::unix::prelude::AsRawFd;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {
        let it = format!("{}\n", line);
        self.file.write_str(it.as_slice());
    }

    fn read(&mut self) -> Option<String> {
        let res = match self.file.read_byte() {
            Ok(c) => {
                let character = c as char;
                Some(character.to_string())
            },
            Err(_) => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = File::open_mode(&path, Open, ReadWrite).unwrap();
        let dimension = TTY::get_window_size();
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    pub fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_slice()]);
    }

    fn get_window_size() -> (usize, usize) {
        let (w,h) = stdio::stdout_raw().winsize().unwrap();
        (w as usize, h as usize)
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        let container = StdioContainer::InheritFd(file.as_raw_fd());
        let output = Command::new("stty").args(args).stdin(container).output().unwrap();
        String::from_utf8(output.output).ok()
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}
<|endoftext|>


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

#![feature(rustc_attrs)]

#[rustc_mir]
fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
    // Test passing a number of arguments including a fat pointer.
    // Also returning via an out pointer
    fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
        (a, b, c)
    }
    callee(a, b, c)
}

#[rustc_mir]
fn test2(a: isize) -> isize {
    // Test passing a single argument.
    // Not using out pointer.
    fn callee(a: isize) -> isize {
        a
    }
    callee(a)
}

struct Foo;
impl Foo {
    fn inherent_method(&self, a: isize) -> isize { a }
}

#[rustc_mir]
fn test3(x: &Foo, a: isize) -> isize {
    // Test calling inherent method
    x.inherent_method(a)
}

trait Bar {
    fn extension_method(&self, a: isize) -> isize { a }
}
impl Bar for Foo {}

#[rustc_mir]
fn test4(x: &Foo, a: isize) -> isize {
    // Test calling extension method
    x.extension_method(a)
}

#[rustc_mir]
fn test5(x: &Bar, a: isize) -> isize {
    // Test calling method on trait object
    x.extension_method(a)
}

// FIXME #30661: Although this function has the #[rustc_mir] attribute it never
//               was translated via the MIR implementation because attributes
//               where not passed along to trans::base::trans_fn() for generic
//               functions.
//               Uncomment this test once the thing it tests is fixed.
// #[rustc_mir]
// fn test6<T: Bar>(x: &T, a: isize) -> isize {
//     // Test calling extension method on generic callee
//     x.extension_method(a)
// }

trait One<T = Self> {
    fn one() -> T;
}
impl One for isize {
    fn one() -> isize { 1 }
}

#[rustc_mir]
fn test7() -> isize {
    // Test calling trait static method
    <isize as One>::one()
}

struct Two;
impl Two {
    fn two() -> isize { 2 }
}

#[rustc_mir]
fn test8() -> isize {
    // Test calling impl static method
    Two::two()
}

#[rustc_mir]
fn test_fn_impl(f: &&Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
    // This call goes through the Fn implementation for &Fn provided in
    // core::ops::impls. It expands to a static Fn::call() that calls the
    // Fn::call() implemenation of the object shim underneath.
    f(x, y)
}

#[rustc_mir]
fn test_fn_object(f: &Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
    f(x, y)
}

fn main() {
    assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
    assert_eq!(test2(98), 98);
    assert_eq!(test3(&Foo, 42), 42);
    assert_eq!(test4(&Foo, 970), 970);
    assert_eq!(test5(&Foo, 8576), 8576);
    // see definition of test6() above
    // assert_eq!(test6(&Foo, 12367), 12367);
    assert_eq!(test7(), 1);
    assert_eq!(test8(), 2);

    let function_object = (&|x: i32, y: i32| { x + y }) as &Fn(i32, i32) -> i32;
    assert_eq!(test_fn_object(function_object, 100, 1), 101);
    assert_eq!(test_fn_impl(&function_object, 100, 2), 102);
}
<commit_msg>[MIR] Add test case for translation of closure calls.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

#[rustc_mir]
fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
    // Test passing a number of arguments including a fat pointer.
    // Also returning via an out pointer
    fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
        (a, b, c)
    }
    callee(a, b, c)
}

#[rustc_mir]
fn test2(a: isize) -> isize {
    // Test passing a single argument.
    // Not using out pointer.
    fn callee(a: isize) -> isize {
        a
    }
    callee(a)
}

struct Foo;
impl Foo {
    fn inherent_method(&self, a: isize) -> isize { a }
}

#[rustc_mir]
fn test3(x: &Foo, a: isize) -> isize {
    // Test calling inherent method
    x.inherent_method(a)
}

trait Bar {
    fn extension_method(&self, a: isize) -> isize { a }
}
impl Bar for Foo {}

#[rustc_mir]
fn test4(x: &Foo, a: isize) -> isize {
    // Test calling extension method
    x.extension_method(a)
}

#[rustc_mir]
fn test5(x: &Bar, a: isize) -> isize {
    // Test calling method on trait object
    x.extension_method(a)
}

// FIXME #30661: Although this function has the #[rustc_mir] attribute it never
//               was translated via the MIR implementation because attributes
//               where not passed along to trans::base::trans_fn() for generic
//               functions.
//               Uncomment this test once the thing it tests is fixed.
// #[rustc_mir]
// fn test6<T: Bar>(x: &T, a: isize) -> isize {
//     // Test calling extension method on generic callee
//     x.extension_method(a)
// }

trait One<T = Self> {
    fn one() -> T;
}
impl One for isize {
    fn one() -> isize { 1 }
}

#[rustc_mir]
fn test7() -> isize {
    // Test calling trait static method
    <isize as One>::one()
}

struct Two;
impl Two {
    fn two() -> isize { 2 }
}

#[rustc_mir]
fn test8() -> isize {
    // Test calling impl static method
    Two::two()
}

#[rustc_mir]
fn test_closure<F>(f: &F, x: i32, y: i32) -> i32
    where F: Fn(i32, i32) -> i32
{
    f(x, y)
}

#[rustc_mir]
fn test_fn_object(f: &Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
    f(x, y)
}

#[rustc_mir]
fn test_fn_impl(f: &&Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
    // This call goes through the Fn implementation for &Fn provided in
    // core::ops::impls. It expands to a static Fn::call() that calls the
    // Fn::call() implemenation of the object shim underneath.
    f(x, y)
}

fn main() {
    assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
    assert_eq!(test2(98), 98);
    assert_eq!(test3(&Foo, 42), 42);
    assert_eq!(test4(&Foo, 970), 970);
    assert_eq!(test5(&Foo, 8576), 8576);
    // see definition of test6() above
    // assert_eq!(test6(&Foo, 12367), 12367);
    assert_eq!(test7(), 1);
    assert_eq!(test8(), 2);

    let closure = |x: i32, y: i32| { x + y };
    assert_eq!(test_closure(&closure, 100, 1), 101);
    let function_object = &closure as &Fn(i32, i32) -> i32;
    assert_eq!(test_fn_object(function_object, 100, 2), 102);
    assert_eq!(test_fn_impl(&function_object, 100, 3), 103);
}
<|endoftext|>


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

// To avoid problems with Windows UAC installer detection heuristics,
// Rust-produced executables need an application manifest.
// For details, see issue #10512.

// No-op on other platforms.

use driver::session::Session;
use std::path::Path;

#[cfg(not(windows))]
pub fn postprocess_executable(sess: Session, filename: &Path) {}

#[cfg(windows)]
pub fn postprocess_executable(sess: Session, filename: &Path) {

    let default_manifest = concat!(
        "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>",
        "<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>",
        "  <trustInfo xmlns='urn:schemas-microsoft-com:asm.v3'>",
        "    <security>",
        "      <requestedPrivileges>",
        "        <requestedExecutionLevel level='asInvoker' uiAccess='false' />",
        "      </requestedPrivileges>",
        "    </security>",
        "  </trustInfo>",
        "</assembly>");

    match windows::embed_manifest(filename, default_manifest) {
        Ok(_) => (),
        Err(msg) => sess.err(format!("Could not embed application manifest: {}", msg))
    }
}

#[cfg(windows)]
mod windows {
    use std::libc::types::os::arch::extra::{BOOL,WORD,DWORD,HANDLE,LPCWSTR,LPCVOID};
    use std::libc::consts::os::extra::FALSE;
    use std::cast::transmute;
    use std::os;

    // FIXME #9053: should import as_utf16_p from std rather than re-defining here
    //use std::os::win32::as_utf16_p;
    fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
        let mut t = s.to_utf16();
        // Null terminate before passing on.
        t.push(0u16);
        t.as_imm_buf(|buf, _len| f(buf))
    }

    #[link_name = "kernel32"]
    extern "system" {
        pub fn BeginUpdateResourceW(pFileName: LPCWSTR,
                                    bDeleteExistingResources: BOOL) -> HANDLE;
        pub fn UpdateResourceW(hUpdate: HANDLE,
                               lpType: LPCWSTR,
                               lpName: LPCWSTR,
                               wLanguage: WORD,
                               lpData: LPCVOID,
                               cbData: DWORD) -> BOOL;
        pub fn EndUpdateResourceW(hUpdate: HANDLE,
                                  fDiscard: BOOL) -> BOOL;
    }

    fn MAKEINTRESOURCEW(id: int) -> LPCWSTR {
        unsafe{ transmute(id) }
    }

    pub fn embed_manifest(filename: &Path,
                          manifest: &str) -> Result<(),~str> {
        unsafe {
            let hUpdate = as_utf16_p(filename.as_str().unwrap(), |path| {
                BeginUpdateResourceW(path, FALSE)
            });
            if hUpdate.is_null() {
                return Err(format!("failure in BeginUpdateResourceW: {}", os::last_os_error()));
            }

            let ok = manifest.as_imm_buf(|p, len| {
                UpdateResourceW(hUpdate,
                                MAKEINTRESOURCEW(24), // RT_MANIFEST
                                MAKEINTRESOURCEW(1),  // CREATEPROCESS_MANIFEST_RESOURCE_ID
                                0,                    // LANG_NEUTRAL, SUBLANG_NEUTRAL
                                p as LPCVOID,
                                len as u32)
            });
            if ok == FALSE {
                return Err(format!("failure in UpdateResourceW: {}", os::last_os_error()));
            }

            let ok = EndUpdateResourceW(hUpdate, FALSE);
            if ok == FALSE {
                return Err(format!("failure in EndUpdateResourceW: {}", os::last_os_error()));
            }
            Ok(())
        }
    }
}
<commit_msg>Fixed "unused variable" errors and trailing whitespace.<commit_after>// Copyright 2013 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.

// To avoid problems with Windows UAC installer detection heuristics,
// Rust-produced executables need an application manifest.
// For details, see issue #10512.

// No-op on other platforms.

use driver::session::Session;
use std::path::Path;

#[cfg(not(windows))]
pub fn postprocess_executable(_sess: Session, _filename: &Path) {}

#[cfg(windows)]
pub fn postprocess_executable(sess: Session, filename: &Path) {

    let default_manifest = concat!(
        "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>",
        "<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>",
        "  <trustInfo xmlns='urn:schemas-microsoft-com:asm.v3'>",
        "    <security>",
        "      <requestedPrivileges>",
        "        <requestedExecutionLevel level='asInvoker' uiAccess='false' />",
        "      </requestedPrivileges>",
        "    </security>",
        "  </trustInfo>",
        "</assembly>");

    match windows::embed_manifest(filename, default_manifest) {
        Ok(_) => (),
        Err(msg) => sess.err(format!("Could not embed application manifest: {}", msg))
    }
}

#[cfg(windows)]
mod windows {
    use std::libc::types::os::arch::extra::{BOOL,WORD,DWORD,HANDLE,LPCWSTR,LPCVOID};
    use std::libc::consts::os::extra::FALSE;
    use std::cast::transmute;
    use std::os;

    // FIXME #9053: should import as_utf16_p from std rather than re-defining here
    //use std::os::win32::as_utf16_p;
    fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
        let mut t = s.to_utf16();
        // Null terminate before passing on.
        t.push(0u16);
        t.as_imm_buf(|buf, _len| f(buf))
    }

    #[link_name = "kernel32"]
    extern "system" {
        pub fn BeginUpdateResourceW(pFileName: LPCWSTR,
                                    bDeleteExistingResources: BOOL) -> HANDLE;
        pub fn UpdateResourceW(hUpdate: HANDLE,
                               lpType: LPCWSTR,
                               lpName: LPCWSTR,
                               wLanguage: WORD,
                               lpData: LPCVOID,
                               cbData: DWORD) -> BOOL;
        pub fn EndUpdateResourceW(hUpdate: HANDLE,
                                  fDiscard: BOOL) -> BOOL;
    }

    fn MAKEINTRESOURCEW(id: int) -> LPCWSTR {
        unsafe{ transmute(id) }
    }

    pub fn embed_manifest(filename: &Path,
                          manifest: &str) -> Result<(),~str> {
        unsafe {
            let hUpdate = as_utf16_p(filename.as_str().unwrap(), |path| {
                BeginUpdateResourceW(path, FALSE)
            });
            if hUpdate.is_null() {
                return Err(format!("failure in BeginUpdateResourceW: {}", os::last_os_error()));
            }

            let ok = manifest.as_imm_buf(|p, len| {
                UpdateResourceW(hUpdate,
                                MAKEINTRESOURCEW(24), // RT_MANIFEST
                                MAKEINTRESOURCEW(1),  // CREATEPROCESS_MANIFEST_RESOURCE_ID
                                0,                    // LANG_NEUTRAL, SUBLANG_NEUTRAL
                                p as LPCVOID,
                                len as u32)
            });
            if ok == FALSE {
                return Err(format!("failure in UpdateResourceW: {}", os::last_os_error()));
            }

            let ok = EndUpdateResourceW(hUpdate, FALSE);
            if ok == FALSE {
                return Err(format!("failure in EndUpdateResourceW: {}", os::last_os_error()));
            }
            Ok(())
        }
    }
}
<|endoftext|>


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

use rustc_data_structures::fx::FxHashMap;

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: FxHashMap<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}\

    \
    {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 = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = 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,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(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>Rollup merge of #82584 - tazjin:rustdoc-aria, r=GuillaumeGomez<commit_after>use std::path::PathBuf;

use rustc_data_structures::fx::FxHashMap;

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: FxHashMap<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}\

    \
    {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 = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = 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,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(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|>