<commit_before>use std::io::SeekFrom;
use std::io::prelude::*;
use std::path::Path;

use curl::easy::{Easy, List};
use git2;
use rustc_serialize::hex::ToHex;
use rustc_serialize::json;
use url::Url;

use core::{PackageId, SourceId};
use ops;
use sources::git;
use sources::registry::{RegistryData, RegistryConfig, INDEX_LOCK};
use util::network;
use util::paths;
use util::{FileLock, Filesystem};
use util::{Config, CargoResult, ChainError, human, Sha256, ToUrl};

pub struct RemoteRegistry<'cfg> {
    index_path: Filesystem,
    cache_path: Filesystem,
    source_id: SourceId,
    config: &'cfg Config,
    handle: Option<Easy>,
}

impl<'cfg> RemoteRegistry<'cfg> {
    pub fn new(source_id: &SourceId, config: &'cfg Config, name: &str)
               -> RemoteRegistry<'cfg> {
        RemoteRegistry {
            index_path: config.registry_index_path().join(name),
            cache_path: config.registry_cache_path().join(name),
            source_id: source_id.clone(),
            config: config,
            handle: None,
        }
    }
}

impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
    fn index_path(&self) -> &Filesystem {
        &self.index_path
    }

    fn config(&self) -> CargoResult<Option<RegistryConfig>> {
        let lock = self.index_path.open_ro(Path::new(INDEX_LOCK),
                                           self.config,
                                           "the registry index")?;
        let path = lock.path().parent().unwrap();
        let contents = paths::read(&path.join("config.json"))?;
        let config = json::decode(&contents)?;
        Ok(Some(config))
    }

    fn update_index(&mut self) -> CargoResult<()> {
        // Ensure that we'll actually be able to acquire an HTTP handle later on
        // once we start trying to download crates. This will weed out any
        // problems with `.cargo/config` configuration related to HTTP.
        //
        // This way if there's a problem the error gets printed before we even
        // hit the index, which may not actually read this configuration.
        ops::http_handle(self.config)?;

        // Then we actually update the index
        self.index_path.create_dir()?;
        let lock = self.index_path.open_rw(Path::new(INDEX_LOCK),
                                           self.config,
                                           "the registry index")?;
        let path = lock.path().parent().unwrap();

        self.config.shell().status("Updating",
             format!("registry `{}`", self.source_id.url()))?;

        let repo = git2::Repository::open(path).or_else(|_| {
            let _ = lock.remove_siblings();
            git2::Repository::init(path)
        })?;

        if self.source_id.url().host_str() == Some("github.com") {
            if let Ok(oid) = repo.refname_to_id("refs/heads/master") {
                let handle = match self.handle {
                    Some(ref mut handle) => handle,
                    None => {
                        self.handle = Some(ops::http_handle(self.config)?);
                        self.handle.as_mut().unwrap()
                    }
                };
                debug!("attempting github fast path for {}",
                       self.source_id.url());
                if github_up_to_date(handle, &self.source_id.url(), &oid) {
                    return Ok(())
                }
                debug!("fast path failed, falling back to a git fetch");
            }
        }

        // git fetch origin
        let url = self.source_id.url().to_string();
        let refspec = "refs/heads/*:refs/remotes/origin/*";

        git::fetch(&repo, &url, refspec, &self.config).chain_error(|| {
            human(format!("failed to fetch `{}`", url))
        })?;

        // git reset --hard origin/master
        let reference = "refs/remotes/origin/master";
        let oid = repo.refname_to_id(reference)?;
        trace!("[{}] updating to rev {}", self.source_id, oid);
        let object = repo.find_object(oid, None)?;
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    fn download(&mut self, pkg: &PackageId, checksum: &str)
                -> CargoResult<FileLock> {
        let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
        let path = Path::new(&filename);

        // Attempt to open an read-only copy first to avoid an exclusive write
        // lock and also work with read-only filesystems. Note that we check the
        // length of the file like below to handle interrupted downloads.
        //
        // If this fails then we fall through to the exclusive path where we may
        // have to redownload the file.
        if let Ok(dst) = self.cache_path.open_ro(path, self.config, &filename) {
            let meta = dst.file().metadata()?;
            if meta.len() > 0 {
                return Ok(dst)
            }
        }
        let mut dst = self.cache_path.open_rw(path, self.config, &filename)?;
        let meta = dst.file().metadata()?;
        if meta.len() > 0 {
            return Ok(dst)
        }
        self.config.shell().status("Downloading", pkg)?;

        let config = self.config()?.unwrap();
        let mut url = config.dl.to_url()?;
        url.path_segments_mut().unwrap()
            .push(pkg.name())
            .push(&pkg.version().to_string())
            .push("download");

        let handle = match self.handle {
            Some(ref mut handle) => handle,
            None => {
                self.handle = Some(ops::http_handle(self.config)?);
                self.handle.as_mut().unwrap()
            }
        };
        // TODO: don't download into memory, but ensure that if we ctrl-c a
        //       download we should resume either from the start or the middle
        //       on the next time
        handle.get(true)?;
        handle.url(&url.to_string())?;
        handle.follow_location(true)?;
        let mut state = Sha256::new();
        let mut body = Vec::new();
        {
            let mut handle = handle.transfer();
            handle.write_function(|buf| {
                state.update(buf);
                body.extend_from_slice(buf);
                Ok(buf.len())
            })?;
            network::with_retry(self.config, || {
                handle.perform()
            })?
        }
        let code = handle.response_code()?;
        if code != 200 && code != 0 {
            bail!("failed to get 200 response from `{}`, got {}", url, code)
        }

        // Verify what we just downloaded
        if state.finish().to_hex() != checksum {
            bail!("failed to verify the checksum of `{}`", pkg)
        }

        dst.write_all(&body)?;
        dst.seek(SeekFrom::Start(0))?;
        Ok(dst)
    }
}

/// Updating the index is done pretty regularly so we want it to be as fast as
/// possible. For registries hosted on github (like the crates.io index) there's
/// a fast path available to use [1] to tell us that there's no updates to be
/// made.
///
/// This function will attempt to hit that fast path and verify that the `oid`
/// is actually the current `master` branch of the repository. If `true` is
/// returned then no update needs to be performed, but if `false` is returned
/// then the standard update logic still needs to happen.
///
/// [1]: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference
///
/// Note that this function should never cause an actual failure because it's
/// just a fast path. As a result all errors are ignored in this function and we
/// just return a `bool`. Any real errors will be reported through the normal
/// update path above.
fn github_up_to_date(handle: &mut Easy, url: &Url, oid: &git2::Oid) -> bool {
    macro_rules! try {
        ($e:expr) => (match $e {
            Some(e) => e,
            None => return false,
        })
    }

    // This expects github urls in the form `github.com/user/repo` and nothing
    // else
    let mut pieces = try!(url.path_segments());
    let username = try!(pieces.next());
    let repo = try!(pieces.next());
    if pieces.next().is_some() {
        return false
    }

    let url = format!("https://api.github.com/repos/{}/{}/commits/master",
                      username, repo);
    try!(handle.get(true).ok());
    try!(handle.url(&url).ok());
    try!(handle.useragent("cargo").ok());
    let mut headers = List::new();
    try!(headers.append("Accept: application/vnd.github.3.sha").ok());
    try!(headers.append(&format!("If-None-Match: \"{}\"", oid)).ok());
    try!(handle.http_headers(headers).ok());
    try!(handle.perform().ok());

    try!(handle.response_code().ok()) == 304
}
<commit_msg>Fix retrying crate downloads for network errors<commit_after>use std::io::SeekFrom;
use std::io::prelude::*;
use std::path::Path;

use curl::easy::{Easy, List};
use git2;
use rustc_serialize::hex::ToHex;
use rustc_serialize::json;
use url::Url;

use core::{PackageId, SourceId};
use ops;
use sources::git;
use sources::registry::{RegistryData, RegistryConfig, INDEX_LOCK};
use util::network;
use util::paths;
use util::{FileLock, Filesystem};
use util::{Config, CargoResult, ChainError, human, Sha256, ToUrl};

pub struct RemoteRegistry<'cfg> {
    index_path: Filesystem,
    cache_path: Filesystem,
    source_id: SourceId,
    config: &'cfg Config,
    handle: Option<Easy>,
}

impl<'cfg> RemoteRegistry<'cfg> {
    pub fn new(source_id: &SourceId, config: &'cfg Config, name: &str)
               -> RemoteRegistry<'cfg> {
        RemoteRegistry {
            index_path: config.registry_index_path().join(name),
            cache_path: config.registry_cache_path().join(name),
            source_id: source_id.clone(),
            config: config,
            handle: None,
        }
    }
}

impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
    fn index_path(&self) -> &Filesystem {
        &self.index_path
    }

    fn config(&self) -> CargoResult<Option<RegistryConfig>> {
        let lock = self.index_path.open_ro(Path::new(INDEX_LOCK),
                                           self.config,
                                           "the registry index")?;
        let path = lock.path().parent().unwrap();
        let contents = paths::read(&path.join("config.json"))?;
        let config = json::decode(&contents)?;
        Ok(Some(config))
    }

    fn update_index(&mut self) -> CargoResult<()> {
        // Ensure that we'll actually be able to acquire an HTTP handle later on
        // once we start trying to download crates. This will weed out any
        // problems with `.cargo/config` configuration related to HTTP.
        //
        // This way if there's a problem the error gets printed before we even
        // hit the index, which may not actually read this configuration.
        ops::http_handle(self.config)?;

        // Then we actually update the index
        self.index_path.create_dir()?;
        let lock = self.index_path.open_rw(Path::new(INDEX_LOCK),
                                           self.config,
                                           "the registry index")?;
        let path = lock.path().parent().unwrap();

        self.config.shell().status("Updating",
             format!("registry `{}`", self.source_id.url()))?;

        let repo = git2::Repository::open(path).or_else(|_| {
            let _ = lock.remove_siblings();
            git2::Repository::init(path)
        })?;

        if self.source_id.url().host_str() == Some("github.com") {
            if let Ok(oid) = repo.refname_to_id("refs/heads/master") {
                let handle = match self.handle {
                    Some(ref mut handle) => handle,
                    None => {
                        self.handle = Some(ops::http_handle(self.config)?);
                        self.handle.as_mut().unwrap()
                    }
                };
                debug!("attempting github fast path for {}",
                       self.source_id.url());
                if github_up_to_date(handle, &self.source_id.url(), &oid) {
                    return Ok(())
                }
                debug!("fast path failed, falling back to a git fetch");
            }
        }

        // git fetch origin
        let url = self.source_id.url().to_string();
        let refspec = "refs/heads/*:refs/remotes/origin/*";

        git::fetch(&repo, &url, refspec, &self.config).chain_error(|| {
            human(format!("failed to fetch `{}`", url))
        })?;

        // git reset --hard origin/master
        let reference = "refs/remotes/origin/master";
        let oid = repo.refname_to_id(reference)?;
        trace!("[{}] updating to rev {}", self.source_id, oid);
        let object = repo.find_object(oid, None)?;
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    fn download(&mut self, pkg: &PackageId, checksum: &str)
                -> CargoResult<FileLock> {
        let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
        let path = Path::new(&filename);

        // Attempt to open an read-only copy first to avoid an exclusive write
        // lock and also work with read-only filesystems. Note that we check the
        // length of the file like below to handle interrupted downloads.
        //
        // If this fails then we fall through to the exclusive path where we may
        // have to redownload the file.
        if let Ok(dst) = self.cache_path.open_ro(path, self.config, &filename) {
            let meta = dst.file().metadata()?;
            if meta.len() > 0 {
                return Ok(dst)
            }
        }
        let mut dst = self.cache_path.open_rw(path, self.config, &filename)?;
        let meta = dst.file().metadata()?;
        if meta.len() > 0 {
            return Ok(dst)
        }
        self.config.shell().status("Downloading", pkg)?;

        let config = self.config()?.unwrap();
        let mut url = config.dl.to_url()?;
        url.path_segments_mut().unwrap()
            .push(pkg.name())
            .push(&pkg.version().to_string())
            .push("download");

        let handle = match self.handle {
            Some(ref mut handle) => handle,
            None => {
                self.handle = Some(ops::http_handle(self.config)?);
                self.handle.as_mut().unwrap()
            }
        };
        // TODO: don't download into memory, but ensure that if we ctrl-c a
        //       download we should resume either from the start or the middle
        //       on the next time
        handle.get(true)?;
        handle.url(&url.to_string())?;
        handle.follow_location(true)?;
        let mut state = Sha256::new();
        let mut body = Vec::new();
        network::with_retry(self.config, || {
            state = Sha256::new();
            body = Vec::new();
            let mut handle = handle.transfer();
            handle.write_function(|buf| {
                state.update(buf);
                body.extend_from_slice(buf);
                Ok(buf.len())
            })?;
            handle.perform()
        })?;
        let code = handle.response_code()?;
        if code != 200 && code != 0 {
            bail!("failed to get 200 response from `{}`, got {}", url, code)
        }

        // Verify what we just downloaded
        if state.finish().to_hex() != checksum {
            bail!("failed to verify the checksum of `{}`", pkg)
        }

        dst.write_all(&body)?;
        dst.seek(SeekFrom::Start(0))?;
        Ok(dst)
    }
}

/// Updating the index is done pretty regularly so we want it to be as fast as
/// possible. For registries hosted on github (like the crates.io index) there's
/// a fast path available to use [1] to tell us that there's no updates to be
/// made.
///
/// This function will attempt to hit that fast path and verify that the `oid`
/// is actually the current `master` branch of the repository. If `true` is
/// returned then no update needs to be performed, but if `false` is returned
/// then the standard update logic still needs to happen.
///
/// [1]: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference
///
/// Note that this function should never cause an actual failure because it's
/// just a fast path. As a result all errors are ignored in this function and we
/// just return a `bool`. Any real errors will be reported through the normal
/// update path above.
fn github_up_to_date(handle: &mut Easy, url: &Url, oid: &git2::Oid) -> bool {
    macro_rules! try {
        ($e:expr) => (match $e {
            Some(e) => e,
            None => return false,
        })
    }

    // This expects github urls in the form `github.com/user/repo` and nothing
    // else
    let mut pieces = try!(url.path_segments());
    let username = try!(pieces.next());
    let repo = try!(pieces.next());
    if pieces.next().is_some() {
        return false
    }

    let url = format!("https://api.github.com/repos/{}/{}/commits/master",
                      username, repo);
    try!(handle.get(true).ok());
    try!(handle.url(&url).ok());
    try!(handle.useragent("cargo").ok());
    let mut headers = List::new();
    try!(headers.append("Accept: application/vnd.github.3.sha").ok());
    try!(headers.append(&format!("If-None-Match: \"{}\"", oid)).ok());
    try!(handle.http_headers(headers).ok());
    try!(handle.perform().ok());

    try!(handle.response_code().ok()) == 304
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::hir::*;
use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg};

/// **What it does:** Checks for fields in struct literals where shorthands
/// could be used.
///
/// **Why is this bad?** If the field and variable names are the same,
/// the field name is redundant.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let bar: u8 = 123;
///
/// struct Foo {
///     bar: u8,
/// }
///
/// let foo = Foo{ bar: bar }
/// ```
declare_lint! {
    pub REDUNDANT_FIELD_NAMES,
    Warn,
    "checks for fields in struct literals where shorthands could be used"
}

pub struct RedundantFieldNames;

impl LintPass for RedundantFieldNames {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_FIELD_NAMES)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        // Do not care about range expressions.
        // They could have redundant field name when desugared to structs.
        // e.g. `start..end` is desugared to `Range { start: start, end: end }`
        if in_macro(expr.span) || is_range_expression(expr.span) {
            return;
        }

        if let ExprStruct(_, ref fields, _) = expr.node {
            for field in fields {
                let name = field.name.node;

                if match_var(&field.expr, name) && !field.is_shorthand {
                    span_lint_and_sugg (
                        cx,
                        REDUNDANT_FIELD_NAMES,
                        field.span,
                        "redundant field names in struct initialization",
                        "replace it with",
                        name.to_string()
                    );
                }
            }
        }
    }
}
<commit_msg>Fix comment<commit_after>use rustc::lint::*;
use rustc::hir::*;
use utils::{in_macro, is_range_expression, match_var, span_lint_and_sugg};

/// **What it does:** Checks for fields in struct literals where shorthands
/// could be used.
///
/// **Why is this bad?** If the field and variable names are the same,
/// the field name is redundant.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let bar: u8 = 123;
///
/// struct Foo {
///     bar: u8,
/// }
///
/// let foo = Foo{ bar: bar }
/// ```
declare_lint! {
    pub REDUNDANT_FIELD_NAMES,
    Warn,
    "checks for fields in struct literals where shorthands could be used"
}

pub struct RedundantFieldNames;

impl LintPass for RedundantFieldNames {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_FIELD_NAMES)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        // Ignore all macros including range expressions.
        // They can have redundant field names when expanded.
        // e.g. range expression `start..end` is desugared to `Range { start: start, end: end }`
        if in_macro(expr.span) || is_range_expression(expr.span) {
            return;
        }

        if let ExprStruct(_, ref fields, _) = expr.node {
            for field in fields {
                let name = field.name.node;

                if match_var(&field.expr, name) && !field.is_shorthand {
                    span_lint_and_sugg (
                        cx,
                        REDUNDANT_FIELD_NAMES,
                        field.span,
                        "redundant field names in struct initialization",
                        "replace it with",
                        name.to_string()
                    );
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::job_queue::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::mem;
use std::sync::*;
use std::pin::{Pin};

///
/// The possible states of a future result
///
enum FutureResultState<T> {
    None,
    Some(T),
    ReturnedViaFuture
}

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: FutureResultState<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: FutureResultState::None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }
}

impl<T> FutureResultState<T> {
    ///
    /// Returns true if no result has ever been generated for this future
    ///
    fn is_none(&self) -> bool {
        match self {
            FutureResultState::None                 => true,
            FutureResultState::Some(_)              => false,
            FutureResultState::ReturnedViaFuture    => false
        }
    }

    ///
    /// If a result has been generated by this future and has not previously been taken, returns it
    ///
    fn take(&mut self) -> Option<T> {
        // Move the value out of this object
        let mut new_value = FutureResultState::ReturnedViaFuture;
        mem::swap(self, &mut new_value);

        // Return it if it contains a value
        match new_value {
            FutureResultState::None                 => { *self = FutureResultState::None; None },
            FutureResultState::ReturnedViaFuture    => { *self = FutureResultState::ReturnedViaFuture; None },
            FutureResultState::Some(value)          => { Some(value) }
        }
    }
}

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // If no result has been generated, then mark the future as canceled
            if future_result.result.is_none() {
                // Mark the future as canceled
                future_result.result = FutureResultState::Some(Err(oneshot::Canceled));

                // Wake up anything that was polling it
                let waker = future_result.waker.take();
                waker
            } else {
                // Result is already set, so don't wake anything up
                None
            }
        };

        // If we need to wake the future, then do so here (note that we're outside of the lock when we do this)
        waker.map(|waker| waker.wake());
    }
}

impl<T> SchedulerFutureSignaller<T> {
    ///
    /// Signals that the result of the calculation is available
    ///
    pub (super) fn signal(self, result: T) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // Set the result
            future_result.result = FutureResultState::Some(Ok(result));

            // Retrieve the waker
            future_result.waker.take()
        };

        // If we retrieved a waker from the result, wake it up
        waker.map(|waker| waker.wake());
    }
}

///
/// Possible actions we can take based on the state of the signal for the future
///
enum SchedulerAction<T> {
    /// Queue is running elsewhere: we should wait for it to reach the point where the future's result is available
    WaitForCompletion,

    /// Future has already completed: we should return the value to sender
    ReturnValue(T)
}

impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        // Lock the result and determine which action to take
        let next_action = {
            let mut future_result = self.result.lock().unwrap();

            if let Some(result) = future_result.result.take() {
                // The result is available: we should return it immediately
                SchedulerAction::ReturnValue(result)
            } else {
                // Wake us up when the future is available
                future_result.waker = Some(context.waker().clone());

                SchedulerAction::WaitForCompletion
            }
        };

        match next_action {
            SchedulerAction::WaitForCompletion  => task::Poll::Pending,
            SchedulerAction::ReturnValue(value) => task::Poll::Ready(value)
        }
    }
}
<commit_msg>Add a 'DrainQueue' state to indicate that we should try to finish the requested job on the current thread<commit_after>use super::job_queue::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::mem;
use std::sync::*;
use std::pin::{Pin};

///
/// The possible states of a future result
///
enum FutureResultState<T> {
    None,
    Some(T),
    ReturnedViaFuture
}

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: FutureResultState<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: FutureResultState::None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }
}

impl<T> FutureResultState<T> {
    ///
    /// Returns true if no result has ever been generated for this future
    ///
    fn is_none(&self) -> bool {
        match self {
            FutureResultState::None                 => true,
            FutureResultState::Some(_)              => false,
            FutureResultState::ReturnedViaFuture    => false
        }
    }

    ///
    /// If a result has been generated by this future and has not previously been taken, returns it
    ///
    fn take(&mut self) -> Option<T> {
        // Move the value out of this object
        let mut new_value = FutureResultState::ReturnedViaFuture;
        mem::swap(self, &mut new_value);

        // Return it if it contains a value
        match new_value {
            FutureResultState::None                 => { *self = FutureResultState::None; None },
            FutureResultState::ReturnedViaFuture    => { *self = FutureResultState::ReturnedViaFuture; None },
            FutureResultState::Some(value)          => { Some(value) }
        }
    }
}

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // If no result has been generated, then mark the future as canceled
            if future_result.result.is_none() {
                // Mark the future as canceled
                future_result.result = FutureResultState::Some(Err(oneshot::Canceled));

                // Wake up anything that was polling it
                let waker = future_result.waker.take();
                waker
            } else {
                // Result is already set, so don't wake anything up
                None
            }
        };

        // If we need to wake the future, then do so here (note that we're outside of the lock when we do this)
        waker.map(|waker| waker.wake());
    }
}

impl<T> SchedulerFutureSignaller<T> {
    ///
    /// Signals that the result of the calculation is available
    ///
    pub (super) fn signal(self, result: T) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // Set the result
            future_result.result = FutureResultState::Some(Ok(result));

            // Retrieve the waker
            future_result.waker.take()
        };

        // If we retrieved a waker from the result, wake it up
        waker.map(|waker| waker.wake());
    }
}

///
/// Possible actions we can take based on the state of the signal for the future
///
enum SchedulerAction<T> {
    /// Queue is running elsewhere: we should wait for it to reach the point where the future's result is available
    WaitForCompletion,

    /// Future has already completed: we should return the value to sender
    ReturnValue(T),

    /// We've claimed the 'running' state of the queue and should drain it
    DrainQueue
}

impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        // Lock the result and determine which action to take
        let next_action = {
            let mut future_result = self.result.lock().unwrap();

            if let Some(result) = future_result.result.take() {
                // The result is available: we should return it immediately
                SchedulerAction::ReturnValue(result)
            } else {
                // Wake us up when the future is available
                future_result.waker = Some(context.waker().clone());

                SchedulerAction::WaitForCompletion
            }
        };

        match next_action {
            SchedulerAction::WaitForCompletion  => task::Poll::Pending,
            SchedulerAction::ReturnValue(value) => task::Poll::Ready(value),
            SchedulerAction::DrainQueue         => unimplemented!()
        }
    }
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use hyper::{Error, Method, HttpVersion, StatusCode, Headers, Body};
use futures::{future, Future, Stream};
use farmhash;

use super::route::CacheRoute;
use super::check::CacheCheck;
use APP_CONF;
use APP_CACHE_STORE;
use header::janitor::HeaderJanitor;
use header::response_buckets::HeaderResponseBloomResponseBuckets;
use header::response_ttl::HeaderResponseBloomResponseTTL;

pub struct CacheWrite;

pub struct CacheWriteResult {
    pub body: Result<String, Option<String>>,
    pub fingerprint: Option<String>,
    pub status: StatusCode,
    pub headers: Headers,
}

pub type CacheWriteResultFuture = Box<Future<Item = CacheWriteResult, Error = Error>>;

impl CacheWrite {
    pub fn save(
        key: String,
        key_mask: String,
        auth_hash: String,
        shard: u8,
        method: Method,
        version: HttpVersion,
        status: StatusCode,
        mut headers: Headers,
        body: Body,
    ) -> CacheWriteResultFuture {
        Box::new(
            body.concat2()
                .map(|raw_data| String::from_utf8(raw_data.to_vec()))
                .and_then(move |body_result| {
                    if let Ok(body_value) = body_result {
                        debug!("checking whether to write cache for key: {}", &key);

                        if APP_CONF.cache.disable_write == false &&
                            CacheCheck::from_response(&method, &status, &headers) == true
                        {
                            debug!("key: {} cacheable, writing cache", &key);

                            // Acquire bucket from response, or fallback to no bucket
                            let mut key_tags =
                                match headers.get::<HeaderResponseBloomResponseBuckets>() {
                                    None => Vec::new(),
                                    Some(value) => {
                                        value
                                            .0
                                            .iter()
                                            .map(|value| {
                                                CacheRoute::gen_key_bucket_from_hash(
                                                    shard,
                                                    &CacheRoute::hash(value),
                                                )
                                            })
                                            .collect::<Vec<String>>()
                                    }
                                };

                            key_tags.push(CacheRoute::gen_key_auth_from_hash(shard, &auth_hash));

                            // Acquire TTL from response, or fallback to default TTL
                            let ttl = match headers.get::<HeaderResponseBloomResponseTTL>() {
                                None => APP_CONF.cache.ttl_default,
                                Some(value) => value.0,
                            };

                            // Clean headers before they get stored
                            HeaderJanitor::clean(&mut headers);

                            // Generate storable value
                            let body_string = format!(
                                "{}\n{}\n{}",
                                CacheWrite::generate_chain_banner(&version, &status),
                                CacheWrite::generate_chain_headers(&headers),
                                body_value
                            );

                            // Process value fingerprint
                            let fingerprint = Self::process_body_fingerprint(&body_string);

                            // Write to cache
                            Box::new(
                                APP_CACHE_STORE
                                    .set(key, key_mask, body_string, fingerprint, ttl, key_tags)
                                    .or_else(|_| Err(Error::Incomplete))
                                    .and_then(move |result| {
                                        future::ok(match result {
                                            Ok(fingerprint) => {
                                                debug!("wrote cache");

                                                CacheWriteResult {
                                                    body: Ok(body_value),
                                                    fingerprint: Some(fingerprint),
                                                    status: status,
                                                    headers: headers,
                                                }
                                            }
                                            Err(forward) => {
                                                warn!(
                                                    "could not write cache because: {:?}",
                                                    forward.0
                                                );

                                                CacheWriteResult {
                                                    body: Err(Some(body_value)),
                                                    fingerprint: Some(forward.1),
                                                    status: status,
                                                    headers: headers,
                                                }
                                            }
                                        })
                                    }),
                            )
                        } else {
                            debug!("key: {} not cacheable, ignoring", &key);

                            // Not cacheable, ignore
                            Self::result_cache_write_error(
                                Some(body_value),
                                status,
                                headers,
                            )
                        }
                    } else {
                        error!("failed unwrapping body value for key: {}, ignoring", &key);

                        Self::result_cache_write_error(None, status, headers)
                    }
                }),
        )
    }

    fn generate_chain_banner(version: &HttpVersion, status: &StatusCode) -> String {
        format!("{} {}", version, status)
    }

    fn generate_chain_headers(headers: &Headers) -> String {
        headers
            .iter()
            .filter(|header_view| {
                HeaderJanitor::is_contextual(&header_view) == false
            })
            .map(|header_view| {
                format!("{}: {}\n", header_view.name(), header_view.value_string())
            })
            .collect()
    }

    fn process_body_fingerprint(body_string: &str) -> String {
        format!("{:x}", farmhash::fingerprint64(body_string.as_bytes()))
    }

    fn result_cache_write_error(
        body: Option<String>,
        status: StatusCode,
        headers: Headers,
    ) -> CacheWriteResultFuture {
        Box::new(future::ok(CacheWriteResult {
            body: Err(body),
            fingerprint: None,
            status: status,
            headers: headers,
        }))
    }
}

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

    #[test]
    #[should_panic]
    fn it_fails_saving_cache() {
        assert!(
            CacheWrite::save(
                "bloom:0:c:90d52bc6:f773d6f1".to_string(),
                "90d52bc6:f773d6f1".to_string(),
                "90d52bc6".to_string(),
                0,
                Method::Get,
                HttpVersion::Http11,
                StatusCode::Ok,
                Headers::new(),
                Body::empty(),
            ).poll()
                .is_err()
        );
    }
}
<commit_msg>Rust format<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use hyper::{Error, Method, HttpVersion, StatusCode, Headers, Body};
use futures::{future, Future, Stream};
use farmhash;

use super::route::CacheRoute;
use super::check::CacheCheck;
use APP_CONF;
use APP_CACHE_STORE;
use header::janitor::HeaderJanitor;
use header::response_buckets::HeaderResponseBloomResponseBuckets;
use header::response_ttl::HeaderResponseBloomResponseTTL;

pub struct CacheWrite;

pub struct CacheWriteResult {
    pub body: Result<String, Option<String>>,
    pub fingerprint: Option<String>,
    pub status: StatusCode,
    pub headers: Headers,
}

pub type CacheWriteResultFuture = Box<Future<Item = CacheWriteResult, Error = Error>>;

impl CacheWrite {
    pub fn save(
        key: String,
        key_mask: String,
        auth_hash: String,
        shard: u8,
        method: Method,
        version: HttpVersion,
        status: StatusCode,
        mut headers: Headers,
        body: Body,
    ) -> CacheWriteResultFuture {
        Box::new(
            body.concat2()
                .map(|raw_data| String::from_utf8(raw_data.to_vec()))
                .and_then(move |body_result| {
                    if let Ok(body_value) = body_result {
                        debug!("checking whether to write cache for key: {}", &key);

                        if APP_CONF.cache.disable_write == false &&
                            CacheCheck::from_response(&method, &status, &headers) == true
                        {
                            debug!("key: {} cacheable, writing cache", &key);

                            // Acquire bucket from response, or fallback to no bucket
                            let mut key_tags =
                                match headers.get::<HeaderResponseBloomResponseBuckets>() {
                                    None => Vec::new(),
                                    Some(value) => {
                                        value
                                            .0
                                            .iter()
                                            .map(|value| {
                                                CacheRoute::gen_key_bucket_from_hash(
                                                    shard,
                                                    &CacheRoute::hash(value),
                                                )
                                            })
                                            .collect::<Vec<String>>()
                                    }
                                };

                            key_tags.push(CacheRoute::gen_key_auth_from_hash(shard, &auth_hash));

                            // Acquire TTL from response, or fallback to default TTL
                            let ttl = match headers.get::<HeaderResponseBloomResponseTTL>() {
                                None => APP_CONF.cache.ttl_default,
                                Some(value) => value.0,
                            };

                            // Clean headers before they get stored
                            HeaderJanitor::clean(&mut headers);

                            // Generate storable value
                            let body_string = format!(
                                "{}\n{}\n{}",
                                CacheWrite::generate_chain_banner(&version, &status),
                                CacheWrite::generate_chain_headers(&headers),
                                body_value
                            );

                            // Process value fingerprint
                            let fingerprint = Self::process_body_fingerprint(&body_string);

                            // Write to cache
                            Box::new(
                                APP_CACHE_STORE
                                    .set(key, key_mask, body_string, fingerprint, ttl, key_tags)
                                    .or_else(|_| Err(Error::Incomplete))
                                    .and_then(move |result| {
                                        future::ok(match result {
                                            Ok(fingerprint) => {
                                                debug!("wrote cache");

                                                CacheWriteResult {
                                                    body: Ok(body_value),
                                                    fingerprint: Some(fingerprint),
                                                    status: status,
                                                    headers: headers,
                                                }
                                            }
                                            Err(forward) => {
                                                warn!(
                                                    "could not write cache because: {:?}",
                                                    forward.0
                                                );

                                                CacheWriteResult {
                                                    body: Err(Some(body_value)),
                                                    fingerprint: Some(forward.1),
                                                    status: status,
                                                    headers: headers,
                                                }
                                            }
                                        })
                                    }),
                            )
                        } else {
                            debug!("key: {} not cacheable, ignoring", &key);

                            // Not cacheable, ignore
                            Self::result_cache_write_error(Some(body_value), status, headers)
                        }
                    } else {
                        error!("failed unwrapping body value for key: {}, ignoring", &key);

                        Self::result_cache_write_error(None, status, headers)
                    }
                }),
        )
    }

    fn generate_chain_banner(version: &HttpVersion, status: &StatusCode) -> String {
        format!("{} {}", version, status)
    }

    fn generate_chain_headers(headers: &Headers) -> String {
        headers
            .iter()
            .filter(|header_view| {
                HeaderJanitor::is_contextual(&header_view) == false
            })
            .map(|header_view| {
                format!("{}: {}\n", header_view.name(), header_view.value_string())
            })
            .collect()
    }

    fn process_body_fingerprint(body_string: &str) -> String {
        format!("{:x}", farmhash::fingerprint64(body_string.as_bytes()))
    }

    fn result_cache_write_error(
        body: Option<String>,
        status: StatusCode,
        headers: Headers,
    ) -> CacheWriteResultFuture {
        Box::new(future::ok(CacheWriteResult {
            body: Err(body),
            fingerprint: None,
            status: status,
            headers: headers,
        }))
    }
}

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

    #[test]
    #[should_panic]
    fn it_fails_saving_cache() {
        assert!(
            CacheWrite::save(
                "bloom:0:c:90d52bc6:f773d6f1".to_string(),
                "90d52bc6:f773d6f1".to_string(),
                "90d52bc6".to_string(),
                0,
                Method::Get,
                HttpVersion::Http11,
                StatusCode::Ok,
                Headers::new(),
                Body::empty(),
            ).poll()
                .is_err()
        );
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{manager::ShutdownConfig,
            sys::ShutdownMethod};
use habitat_core::os::process::{handle_from_pid,
                                windows_child::{ExitStatus,
                                                Handle},
                                Pid};
use std::{collections::HashMap,
          io,
          mem,
          thread,
          time::Duration as StdDuration};
use time::{Duration as TimeDuration,
           SteadyTime};
use winapi::{shared::minwindef::{DWORD,
                                 LPDWORD,
                                 MAX_PATH},
             um::{handleapi::{self,
                              INVALID_HANDLE_VALUE},
                  processthreadsapi,
                  tlhelp32::{self,
                             LPPROCESSENTRY32W,
                             PROCESSENTRY32W,
                             TH32CS_SNAPPROCESS},
                  wincon}};

const PROCESS_ACTIVE: u32 = 259;
type ProcessTable = HashMap<DWORD, Vec<DWORD>>;

/// Kill a service process
pub fn kill(pid: Pid, shutdown_config: &ShutdownConfig) -> ShutdownMethod {
    match handle_from_pid(pid) {
        None => {
            // Assume it's already gone if we can't resolve a proper process handle
            ShutdownMethod::AlreadyExited
        }
        Some(handle_ptr) => {
            let mut process = Process::new(Handle::new(handle_ptr));
            process.kill(shutdown_config)
        }
    }
}

///////////////////////////////////////////////////////////////////////
// Private Code

struct Process {
    handle:      Handle,
    last_status: Option<ExitStatus>,
}

impl Process {
    fn new(handle: Handle) -> Self {
        Process { handle,
                  last_status: None }
    }

    fn id(&self) -> u32 { unsafe { processthreadsapi::GetProcessId(self.handle.raw()) as u32 } }

    /// Attempt to gracefully terminate a process and then forcefully kill it after
    /// 8 seconds if it has not terminated.
    fn kill(&mut self, shutdown_config: &ShutdownConfig) -> ShutdownMethod {
        let ShutdownConfig { timeout } = *shutdown_config;

        if self.status().is_some() {
            return ShutdownMethod::AlreadyExited;
        }
        let ret = unsafe { wincon::GenerateConsoleCtrlEvent(1, self.id()) };
        if ret == 0 {
            debug!("Failed to send ctrl-break to pid {}: {}",
                   self.id(),
                   io::Error::last_os_error());
        }

        let timeout: TimeDuration = timeout.into();
        trace!("Waiting up to {} seconds before terminating process {}",
               timeout.num_seconds(),
               self.id());
        let stop_time = SteadyTime::now() + timeout;
        loop {
            if ret == 0 || SteadyTime::now() > stop_time {
                let proc_table = build_proc_table();
                terminate_process_descendants(&proc_table, self.id());
                return ShutdownMethod::Killed;
            }

            if self.status().is_some() {
                return ShutdownMethod::GracefulTermination;
            }
            thread::sleep(StdDuration::from_millis(5));
        }
    }

    fn status(&mut self) -> Option<ExitStatus> {
        if self.last_status.is_some() {
            return self.last_status;
        }
        match exit_code(&self.handle) {
            Some(PROCESS_ACTIVE) => None,
            Some(code) => {
                self.last_status = Some(ExitStatus::from(code));
                self.last_status
            }
            None => None,
        }
    }
}

fn build_proc_table() -> ProcessTable {
    let processes_snap_handle =
        unsafe { tlhelp32::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };

    if processes_snap_handle == INVALID_HANDLE_VALUE {
        error!("Failed to call CreateToolhelp32Snapshot: {}",
               io::Error::last_os_error());
        return ProcessTable::new();
    }
    let mut table = ProcessTable::new();
    let mut process_entry = PROCESSENTRY32W { dwSize:              mem::size_of::<PROCESSENTRY32W>()
                                                                   as u32,
                                              cntUsage:            0,
                                              th32ProcessID:       0,
                                              th32DefaultHeapID:   0,
                                              th32ModuleID:        0,
                                              cntThreads:          0,
                                              th32ParentProcessID: 0,
                                              pcPriClassBase:      0,
                                              dwFlags:             0,
                                              szExeFile:           [0; MAX_PATH], };
    // Get the first process from the snapshot.
    match unsafe {
              tlhelp32::Process32FirstW(processes_snap_handle,
                                        &mut process_entry as LPPROCESSENTRY32W)
          } {
        1 => {
            // First process worked, loop to find the process with the correct name.
            let mut process_success: i32 = 1;
            // Loop through all processes until we find one where `szExeFile` == `name`.
            while process_success == 1 {
                let children = table.entry(process_entry.th32ParentProcessID)
                                    .or_insert_with(Vec::new);
                (*children).push(process_entry.th32ProcessID);
                process_success =
                    unsafe { tlhelp32::Process32NextW(processes_snap_handle, &mut process_entry) };
            }
            unsafe { handleapi::CloseHandle(processes_snap_handle) };
        }
        0 | _ => unsafe {
            handleapi::CloseHandle(processes_snap_handle);
        },
    }
    table
}

fn exit_code(handle: &Handle) -> Option<u32> {
    let mut exit_code: u32 = 0;
    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle.raw(), &mut exit_code as LPDWORD);
        if ret == 0 {
            error!("Failed to retrieve Exit Code: {}",
                   io::Error::last_os_error());
            return None;
        }
    }
    Some(exit_code)
}

fn terminate_process_descendants(table: &ProcessTable, pid: DWORD) {
    if let Some(children) = table.get(&pid) {
        for child in children {
            terminate_process_descendants(table, *child);
        }
    }
    unsafe {
        if let Some(h) = handle_from_pid(pid) {
            if processthreadsapi::TerminateProcess(h, 1) == 0 {
                error!("Failed to call TerminateProcess on pid {}: {}",
                       pid,
                       io::Error::last_os_error());
            }
        }
    }
}
<commit_msg>Remove copyright<commit_after>use crate::{manager::ShutdownConfig,
            sys::ShutdownMethod};
use habitat_core::os::process::{handle_from_pid,
                                windows_child::{ExitStatus,
                                                Handle},
                                Pid};
use std::{collections::HashMap,
          io,
          mem,
          thread,
          time::Duration as StdDuration};
use time::{Duration as TimeDuration,
           SteadyTime};
use winapi::{shared::minwindef::{DWORD,
                                 LPDWORD,
                                 MAX_PATH},
             um::{handleapi::{self,
                              INVALID_HANDLE_VALUE},
                  processthreadsapi,
                  tlhelp32::{self,
                             LPPROCESSENTRY32W,
                             PROCESSENTRY32W,
                             TH32CS_SNAPPROCESS},
                  wincon}};

const PROCESS_ACTIVE: u32 = 259;
type ProcessTable = HashMap<DWORD, Vec<DWORD>>;

/// Kill a service process
pub fn kill(pid: Pid, shutdown_config: &ShutdownConfig) -> ShutdownMethod {
    match handle_from_pid(pid) {
        None => {
            // Assume it's already gone if we can't resolve a proper process handle
            ShutdownMethod::AlreadyExited
        }
        Some(handle_ptr) => {
            let mut process = Process::new(Handle::new(handle_ptr));
            process.kill(shutdown_config)
        }
    }
}

///////////////////////////////////////////////////////////////////////
// Private Code

struct Process {
    handle:      Handle,
    last_status: Option<ExitStatus>,
}

impl Process {
    fn new(handle: Handle) -> Self {
        Process { handle,
                  last_status: None }
    }

    fn id(&self) -> u32 { unsafe { processthreadsapi::GetProcessId(self.handle.raw()) as u32 } }

    /// Attempt to gracefully terminate a process and then forcefully kill it after
    /// 8 seconds if it has not terminated.
    fn kill(&mut self, shutdown_config: &ShutdownConfig) -> ShutdownMethod {
        let ShutdownConfig { timeout } = *shutdown_config;

        if self.status().is_some() {
            return ShutdownMethod::AlreadyExited;
        }
        let ret = unsafe { wincon::GenerateConsoleCtrlEvent(1, self.id()) };
        if ret == 0 {
            debug!("Failed to send ctrl-break to pid {}: {}",
                   self.id(),
                   io::Error::last_os_error());
        }

        let timeout: TimeDuration = timeout.into();
        trace!("Waiting up to {} seconds before terminating process {}",
               timeout.num_seconds(),
               self.id());
        let stop_time = SteadyTime::now() + timeout;
        loop {
            if ret == 0 || SteadyTime::now() > stop_time {
                let proc_table = build_proc_table();
                terminate_process_descendants(&proc_table, self.id());
                return ShutdownMethod::Killed;
            }

            if self.status().is_some() {
                return ShutdownMethod::GracefulTermination;
            }
            thread::sleep(StdDuration::from_millis(5));
        }
    }

    fn status(&mut self) -> Option<ExitStatus> {
        if self.last_status.is_some() {
            return self.last_status;
        }
        match exit_code(&self.handle) {
            Some(PROCESS_ACTIVE) => None,
            Some(code) => {
                self.last_status = Some(ExitStatus::from(code));
                self.last_status
            }
            None => None,
        }
    }
}

fn build_proc_table() -> ProcessTable {
    let processes_snap_handle =
        unsafe { tlhelp32::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };

    if processes_snap_handle == INVALID_HANDLE_VALUE {
        error!("Failed to call CreateToolhelp32Snapshot: {}",
               io::Error::last_os_error());
        return ProcessTable::new();
    }
    let mut table = ProcessTable::new();
    let mut process_entry = PROCESSENTRY32W { dwSize:              mem::size_of::<PROCESSENTRY32W>()
                                                                   as u32,
                                              cntUsage:            0,
                                              th32ProcessID:       0,
                                              th32DefaultHeapID:   0,
                                              th32ModuleID:        0,
                                              cntThreads:          0,
                                              th32ParentProcessID: 0,
                                              pcPriClassBase:      0,
                                              dwFlags:             0,
                                              szExeFile:           [0; MAX_PATH], };
    // Get the first process from the snapshot.
    match unsafe {
              tlhelp32::Process32FirstW(processes_snap_handle,
                                        &mut process_entry as LPPROCESSENTRY32W)
          } {
        1 => {
            // First process worked, loop to find the process with the correct name.
            let mut process_success: i32 = 1;
            // Loop through all processes until we find one where `szExeFile` == `name`.
            while process_success == 1 {
                let children = table.entry(process_entry.th32ParentProcessID)
                                    .or_insert_with(Vec::new);
                (*children).push(process_entry.th32ProcessID);
                process_success =
                    unsafe { tlhelp32::Process32NextW(processes_snap_handle, &mut process_entry) };
            }
            unsafe { handleapi::CloseHandle(processes_snap_handle) };
        }
        0 | _ => unsafe {
            handleapi::CloseHandle(processes_snap_handle);
        },
    }
    table
}

fn exit_code(handle: &Handle) -> Option<u32> {
    let mut exit_code: u32 = 0;
    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle.raw(), &mut exit_code as LPDWORD);
        if ret == 0 {
            error!("Failed to retrieve Exit Code: {}",
                   io::Error::last_os_error());
            return None;
        }
    }
    Some(exit_code)
}

fn terminate_process_descendants(table: &ProcessTable, pid: DWORD) {
    if let Some(children) = table.get(&pid) {
        for child in children {
            terminate_process_descendants(table, *child);
        }
    }
    unsafe {
        if let Some(h) = handle_from_pid(pid) {
            if processthreadsapi::TerminateProcess(h, 1) == 0 {
                error!("Failed to call TerminateProcess on pid {}: {}",
                       pid,
                       io::Error::last_os_error());
            }
        }
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{
    Direction, SyntaxNode, TextRange, TextUnit,
    algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
    SyntaxKind::*,
};

pub fn extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange> {
    let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
    if range.is_empty() {
        let offset = range.start();
        let mut leaves = find_leaf_at_offset(root, offset);
        if leaves.clone().all(|it| it.kind() == WHITESPACE) {
            return Some(extend_ws(root, leaves.next()?, offset));
        }
        let leaf_range = match leaves {
            LeafAtOffset::None => return None,
            LeafAtOffset::Single(l) => {
                if string_kinds.contains(&l.kind()) {
                    extend_single_word_in_comment_or_string(l, offset).unwrap_or_else(|| l.range())
                } else {
                    l.range()
                }
            }
            LeafAtOffset::Between(l, r) => pick_best(l, r).range(),
        };
        return Some(leaf_range);
    };
    let node = find_covering_node(root, range);
    if string_kinds.contains(&node.kind()) && range == node.range() {
        if let Some(range) = extend_comments(node) {
            return Some(range);
        }
    }

    match node.ancestors().skip_while(|n| n.range() == range).next() {
        None => None,
        Some(parent) => Some(parent.range()),
    }
}

fn extend_single_word_in_comment_or_string(
    leaf: &SyntaxNode,
    offset: TextUnit,
) -> Option<TextRange> {
    let text: &str = leaf.leaf_text()?;
    let cursor_position: u32 = (offset - leaf.range().start()).into();

    let (before, after) = text.split_at(cursor_position as usize);

    fn non_word_char(c: char) -> bool {
        !(c.is_alphanumeric() || c == '_')
    }

    let start_idx = before.rfind(non_word_char)? as u32;
    let end_idx = after.find(non_word_char).unwrap_or(after.len()) as u32;

    let from: TextUnit = (start_idx + 1).into();
    let to: TextUnit = (cursor_position + end_idx).into();

    let range = TextRange::from_to(from, to);
    if range.is_empty() {
        None
    } else {
        Some(range + leaf.range().start())
    }
}

fn extend_ws(root: &SyntaxNode, ws: &SyntaxNode, offset: TextUnit) -> TextRange {
    let ws_text = ws.leaf_text().unwrap();
    let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
    let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
    let ws_suffix = &ws_text.as_str()[suffix];
    let ws_prefix = &ws_text.as_str()[prefix];
    if ws_text.contains('\n') && !ws_suffix.contains('\n') {
        if let Some(node) = ws.next_sibling() {
            let start = match ws_prefix.rfind('\n') {
                Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
                None => node.range().start(),
            };
            let end = if root.text().char_at(node.range().end()) == Some('\n') {
                node.range().end() + TextUnit::of_char('\n')
            } else {
                node.range().end()
            };
            return TextRange::from_to(start, end);
        }
    }
    ws.range()
}

fn pick_best<'a>(l: &'a SyntaxNode, r: &'a SyntaxNode) -> &'a SyntaxNode {
    return if priority(r) > priority(l) { r } else { l };
    fn priority(n: &SyntaxNode) -> usize {
        match n.kind() {
            WHITESPACE => 0,
            IDENT | SELF_KW | SUPER_KW | CRATE_KW | LIFETIME => 2,
            _ => 1,
        }
    }
}

fn extend_comments(node: &SyntaxNode) -> Option<TextRange> {
    let prev = adj_comments(node, Direction::Prev);
    let next = adj_comments(node, Direction::Next);
    if prev != next {
        Some(TextRange::from_to(prev.range().start(), next.range().end()))
    } else {
        None
    }
}

fn adj_comments(node: &SyntaxNode, dir: Direction) -> &SyntaxNode {
    let mut res = node;
    for node in node.siblings(dir) {
        match node.kind() {
            COMMENT => res = node,
            WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
            _ => break,
        }
    }
    res
}

#[cfg(test)]
mod tests {
    use ra_syntax::{SourceFile, AstNode};
    use test_utils::extract_offset;

    use super::*;

    fn do_check(before: &str, afters: &[&str]) {
        let (cursor, before) = extract_offset(before);
        let file = SourceFile::parse(&before);
        let mut range = TextRange::offset_len(cursor, 0.into());
        for &after in afters {
            range = extend_selection(file.syntax(), range).unwrap();
            let actual = &before[range];
            assert_eq!(after, actual);
        }
    }

    #[test]
    fn test_extend_selection_arith() {
        do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]);
    }

    #[test]
    fn test_extend_selection_start_of_the_lind() {
        do_check(
            r#"
impl S {
<|>    fn foo() {

    }
}"#,
            &["    fn foo() {\n\n    }\n"],
        );
    }

    #[test]
    fn test_extend_selection_doc_comments() {
        do_check(
            r#"
struct A;

/// bla
/// bla
struct B {
    <|>
}
            "#,
            &[
                "\n    \n",
                "{\n    \n}",
                "/// bla\n/// bla\nstruct B {\n    \n}",
            ],
        )
    }

    #[test]
    fn test_extend_selection_comments() {
        do_check(
            r#"
fn bar(){}

// fn foo() {
// 1 + <|>1
// }

// fn foo(){}
    "#,
            &["1", "// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"],
        );

        do_check(
            r#"
// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
// pub enum Direction {
//  <|>   Next,
//     Prev
// }
"#,
            &[
                "//     Next,",
                "// #[derive(Debug, Clone, Copy, PartialEq, Eq)]\n// pub enum Direction {\n//     Next,\n//     Prev\n// }",
            ],
        );

        do_check(
            r#"
/*
foo
_bar1<|>*/
    "#,
            &["_bar1", "/*\nfoo\n_bar1*/"],
        );

        do_check(
            r#"
//!<|>foo_2 bar
    "#,
            &["foo_2", "//!foo_2 bar"],
        );

        do_check(
            r#"
/<|>/foo bar
    "#,
            &["//foo bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_idents() {
        do_check(
            r#"
fn main() { foo<|>+bar;}
    "#,
            &["foo", "foo+bar"],
        );
        do_check(
            r#"
fn main() { foo+<|>bar;}
    "#,
            &["bar", "foo+bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_lifetimes() {
        do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]);
        do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]);
    }

    #[test]
    fn test_extend_selection_select_first_word() {
        do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]);
        do_check(
            r#"
impl S {
    fn foo() {
        // hel<|>lo world
    }
}
        "#,
            &["hello", "// hello world"],
        );
    }

    #[test]
    fn test_extend_selection_string() {
        do_check(
            r#"
fn bar(){}

" fn f<|>oo() {"
    "#,
            &["foo", "\" fn foo() {\""],
        );
    }
}
<commit_msg>Extend selection for list items<commit_after>use ra_syntax::{
    Direction, SyntaxNode, TextRange, TextUnit,
    algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
    SyntaxKind::*,
};

pub fn extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange> {
    let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
    let list_kinds = [
        FIELD_PAT_LIST,
        MATCH_ARM_LIST,
        NAMED_FIELD_LIST,
        NAMED_FIELD_DEF_LIST,
        POS_FIELD_LIST,
        ENUM_VARIANT_LIST,
        USE_TREE_LIST,
        TYPE_PARAM_LIST,
        TYPE_ARG_LIST,
        PARAM_LIST,
        ARG_LIST,
        ARRAY_EXPR,
    ];

    if range.is_empty() {
        let offset = range.start();
        let mut leaves = find_leaf_at_offset(root, offset);
        if leaves.clone().all(|it| it.kind() == WHITESPACE) {
            return Some(extend_ws(root, leaves.next()?, offset));
        }
        let leaf_range = match leaves {
            LeafAtOffset::None => return None,
            LeafAtOffset::Single(l) => {
                if string_kinds.contains(&l.kind()) {
                    extend_single_word_in_comment_or_string(l, offset).unwrap_or_else(|| l.range())
                } else {
                    l.range()
                }
            }
            LeafAtOffset::Between(l, r) => pick_best(l, r).range(),
        };
        return Some(leaf_range);
    };
    let node = find_covering_node(root, range);

    // Using shallowest node with same range allows us to traverse siblings.
    let node = node
        .ancestors()
        .take_while(|n| n.range() == node.range())
        .last()
        .unwrap();

    if range == node.range() {
        if string_kinds.contains(&node.kind()) {
            if let Some(range) = extend_comments(node) {
                return Some(range);
            }
        }

        if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
            if let Some(range) = extend_list_item(node) {
                return Some(range);
            }
        }
    }

    match node.ancestors().skip_while(|n| n.range() == range).next() {
        None => None,
        Some(parent) => Some(parent.range()),
    }
}

fn extend_single_word_in_comment_or_string(
    leaf: &SyntaxNode,
    offset: TextUnit,
) -> Option<TextRange> {
    let text: &str = leaf.leaf_text()?;
    let cursor_position: u32 = (offset - leaf.range().start()).into();

    let (before, after) = text.split_at(cursor_position as usize);

    fn non_word_char(c: char) -> bool {
        !(c.is_alphanumeric() || c == '_')
    }

    let start_idx = before.rfind(non_word_char)? as u32;
    let end_idx = after.find(non_word_char).unwrap_or(after.len()) as u32;

    let from: TextUnit = (start_idx + 1).into();
    let to: TextUnit = (cursor_position + end_idx).into();

    let range = TextRange::from_to(from, to);
    if range.is_empty() {
        None
    } else {
        Some(range + leaf.range().start())
    }
}

fn extend_ws(root: &SyntaxNode, ws: &SyntaxNode, offset: TextUnit) -> TextRange {
    let ws_text = ws.leaf_text().unwrap();
    let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
    let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
    let ws_suffix = &ws_text.as_str()[suffix];
    let ws_prefix = &ws_text.as_str()[prefix];
    if ws_text.contains('\n') && !ws_suffix.contains('\n') {
        if let Some(node) = ws.next_sibling() {
            let start = match ws_prefix.rfind('\n') {
                Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
                None => node.range().start(),
            };
            let end = if root.text().char_at(node.range().end()) == Some('\n') {
                node.range().end() + TextUnit::of_char('\n')
            } else {
                node.range().end()
            };
            return TextRange::from_to(start, end);
        }
    }
    ws.range()
}

fn pick_best<'a>(l: &'a SyntaxNode, r: &'a SyntaxNode) -> &'a SyntaxNode {
    return if priority(r) > priority(l) { r } else { l };
    fn priority(n: &SyntaxNode) -> usize {
        match n.kind() {
            WHITESPACE => 0,
            IDENT | SELF_KW | SUPER_KW | CRATE_KW | LIFETIME => 2,
            _ => 1,
        }
    }
}

/// Extend list item selection to include nearby comma and whitespace.
fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
    fn is_single_line_ws(node: &SyntaxNode) -> bool {
        node.kind() == WHITESPACE && !node.leaf_text().unwrap().contains('\n')
    }

    fn nearby_comma(node: &SyntaxNode, dir: Direction) -> Option<&SyntaxNode> {
        node.siblings(dir)
            .skip(1)
            .skip_while(|node| is_single_line_ws(node))
            .next()
            .filter(|node| node.kind() == COMMA)
    }

    if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
        return Some(TextRange::from_to(
            comma_node.range().start(),
            node.range().end(),
        ));
    }

    if let Some(comma_node) = nearby_comma(node, Direction::Next) {
        // Include any following whitespace when comma if after list item.
        let final_node = comma_node
            .siblings(Direction::Next)
            .skip(1)
            .next()
            .filter(|node| is_single_line_ws(node))
            .unwrap_or(comma_node);

        return Some(TextRange::from_to(
            node.range().start(),
            final_node.range().end(),
        ));
    }

    return None;
}

fn extend_comments(node: &SyntaxNode) -> Option<TextRange> {
    let prev = adj_comments(node, Direction::Prev);
    let next = adj_comments(node, Direction::Next);
    if prev != next {
        Some(TextRange::from_to(prev.range().start(), next.range().end()))
    } else {
        None
    }
}

fn adj_comments(node: &SyntaxNode, dir: Direction) -> &SyntaxNode {
    let mut res = node;
    for node in node.siblings(dir) {
        match node.kind() {
            COMMENT => res = node,
            WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
            _ => break,
        }
    }
    res
}

#[cfg(test)]
mod tests {
    use ra_syntax::{SourceFile, AstNode};
    use test_utils::extract_offset;

    use super::*;

    fn do_check(before: &str, afters: &[&str]) {
        let (cursor, before) = extract_offset(before);
        let file = SourceFile::parse(&before);
        let mut range = TextRange::offset_len(cursor, 0.into());
        for &after in afters {
            range = extend_selection(file.syntax(), range).unwrap();
            let actual = &before[range];
            assert_eq!(after, actual);
        }
    }

    #[test]
    fn test_extend_selection_arith() {
        do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]);
    }

    #[test]
    fn test_extend_selection_list() {
        do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]);
        do_check(
            r#"fn foo(<|>x: i32, y: i32) {}"#,
            &["x", "x: i32", "x: i32, "],
        );
        do_check(
            r#"fn foo(<|>x: i32,y: i32) {}"#,
            &["x", "x: i32", "x: i32,"],
        );
        do_check(
            r#"fn foo(x: i32, <|>y: i32) {}"#,
            &["y", "y: i32", ", y: i32"],
        );
        do_check(
            r#"fn foo(x: i32, <|>y: i32, ) {}"#,
            &["y", "y: i32", ", y: i32"],
        );
        do_check(
            r#"fn foo(x: i32,<|>y: i32) {}"#,
            &["y", "y: i32", ",y: i32"],
        );

        do_check(
            r#"const FOO: [usize; 2] = [ 22<|> , 33];"#,
            &["22", "22 , "],
        );
        do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]);
        do_check(
            r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#,
            &["33", ", 33"],
        );

        do_check(
            r#"
const FOO: [usize; 2] = [
    22,
    <|>33,
]"#,
            &["33", "33,"],
        );

        do_check(
            r#"
const FOO: [usize; 2] = [
    22
    , 33<|>,
]"#,
            &["33", ", 33"],
        );
    }

    #[test]
    fn test_extend_selection_start_of_the_line() {
        do_check(
            r#"
impl S {
<|>    fn foo() {

    }
}"#,
            &["    fn foo() {\n\n    }\n"],
        );
    }

    #[test]
    fn test_extend_selection_doc_comments() {
        do_check(
            r#"
struct A;

/// bla
/// bla
struct B {
    <|>
}
            "#,
            &[
                "\n    \n",
                "{\n    \n}",
                "/// bla\n/// bla\nstruct B {\n    \n}",
            ],
        )
    }

    #[test]
    fn test_extend_selection_comments() {
        do_check(
            r#"
fn bar(){}

// fn foo() {
// 1 + <|>1
// }

// fn foo(){}
    "#,
            &["1", "// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"],
        );

        do_check(
            r#"
// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
// pub enum Direction {
//  <|>   Next,
//     Prev
// }
"#,
            &[
                "//     Next,",
                "// #[derive(Debug, Clone, Copy, PartialEq, Eq)]\n// pub enum Direction {\n//     Next,\n//     Prev\n// }",
            ],
        );

        do_check(
            r#"
/*
foo
_bar1<|>*/
    "#,
            &["_bar1", "/*\nfoo\n_bar1*/"],
        );

        do_check(
            r#"
//!<|>foo_2 bar
    "#,
            &["foo_2", "//!foo_2 bar"],
        );

        do_check(
            r#"
/<|>/foo bar
    "#,
            &["//foo bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_idents() {
        do_check(
            r#"
fn main() { foo<|>+bar;}
    "#,
            &["foo", "foo+bar"],
        );
        do_check(
            r#"
fn main() { foo+<|>bar;}
    "#,
            &["bar", "foo+bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_lifetimes() {
        do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]);
        do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]);
    }

    #[test]
    fn test_extend_selection_select_first_word() {
        do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]);
        do_check(
            r#"
impl S {
    fn foo() {
        // hel<|>lo world
    }
}
        "#,
            &["hello", "// hello world"],
        );
    }

    #[test]
    fn test_extend_selection_string() {
        do_check(
            r#"
fn bar(){}

" fn f<|>oo() {"
    "#,
            &["foo", "\" fn foo() {\""],
        );
    }
}
<|endoftext|>


<commit_before>//! `GET /_matrix/client/*/login/sso/redirect`

pub mod v3 {
    //! `/v3/` ([spec])
    //!
    //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientv3loginssoredirect

    use ruma_common::api::ruma_api;

    ruma_api! {
        metadata: {
            description: "",
            method: GET,
            name: "sso_login",
            unstable_path: "/_matrix/client/unstable/org.matrix.msc2858/login/sso/redirect",
            stable_path: "/_matrix/client/v3/login/sso/redirect",
            rate_limited: false,
            authentication: None,
            added: 1.1,
        }

        request: {
            /// URL to which the homeserver should return the user after completing
            /// authentication with the SSO identity provider.
            #[ruma_api(query)]
            #[serde(rename = "redirectUrl")]
            pub redirect_url: &'a str,
        }

        response: {
            /// Redirect URL to the SSO identity provider.
            #[ruma_api(header = LOCATION)]
            pub location: String,
        }

        error: crate::Error
    }

    impl<'a> Request<'a> {
        /// Creates a new `Request` with the given redirect URL.
        pub fn new(redirect_url: &'a str) -> Self {
            Self { redirect_url }
        }
    }

    impl Response {
        /// Creates a new `Response` with the given SSO URL.
        pub fn new(location: String) -> Self {
            Self { location }
        }
    }

    #[cfg(all(test, feature = "client"))]
    mod tests {
        use ruma_common::api::{MatrixVersion, OutgoingRequest, SendAccessToken};

        use super::Request;

        #[test]
        fn serialize_sso_login_request_uri() {
            let req: http::Request<Vec<u8>> = Request { redirect_url: "https://example.com/sso" }
                .try_into_http_request(
                    "https://homeserver.tld",
                    SendAccessToken::None,
                    &[MatrixVersion::V1_1],
                )
                .unwrap();

            assert_eq!(
            req.uri().to_string(),
            "https://homeserver.tld/_matrix/client/v3/login/sso/redirect?redirectUrl=https%3A%2F%2Fexample.com%2Fsso"
        );
        }
    }
}
<commit_msg>client-api: Fix sso_login added version<commit_after>//! `GET /_matrix/client/*/login/sso/redirect`

pub mod v3 {
    //! `/v3/` ([spec])
    //!
    //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientv3loginssoredirect

    use ruma_common::api::ruma_api;

    ruma_api! {
        metadata: {
            description: "",
            method: GET,
            name: "sso_login",
            r0_path: "/_matrix/client/r0/login/sso/redirect",
            stable_path: "/_matrix/client/v3/login/sso/redirect",
            rate_limited: false,
            authentication: None,
            added: 1.0,
        }

        request: {
            /// URL to which the homeserver should return the user after completing
            /// authentication with the SSO identity provider.
            #[ruma_api(query)]
            #[serde(rename = "redirectUrl")]
            pub redirect_url: &'a str,
        }

        response: {
            /// Redirect URL to the SSO identity provider.
            #[ruma_api(header = LOCATION)]
            pub location: String,
        }

        error: crate::Error
    }

    impl<'a> Request<'a> {
        /// Creates a new `Request` with the given redirect URL.
        pub fn new(redirect_url: &'a str) -> Self {
            Self { redirect_url }
        }
    }

    impl Response {
        /// Creates a new `Response` with the given SSO URL.
        pub fn new(location: String) -> Self {
            Self { location }
        }
    }

    #[cfg(all(test, feature = "client"))]
    mod tests {
        use ruma_common::api::{MatrixVersion, OutgoingRequest, SendAccessToken};

        use super::Request;

        #[test]
        fn serialize_sso_login_request_uri() {
            let req: http::Request<Vec<u8>> = Request { redirect_url: "https://example.com/sso" }
                .try_into_http_request(
                    "https://homeserver.tld",
                    SendAccessToken::None,
                    &[MatrixVersion::V1_1],
                )
                .unwrap();

            assert_eq!(
            req.uri().to_string(),
            "https://homeserver.tld/_matrix/client/v3/login/sso/redirect?redirectUrl=https%3A%2F%2Fexample.com%2Fsso"
        );
        }
    }
}
<|endoftext|>


<commit_before>// This test makes sure that the LLDB pretty printer does not throw an exception
// when trying to handle a Vec<> or anything else that contains zero-sized
// fields.

// min-lldb-version: 310
// ignore-gdb
// ignore-tidy-linelength

// compile-flags:-g

// === LLDB TESTS ==================================================================================
// lldb-command:run

// lldb-command:print v
// lldbg-check:[...]$0 = vec![1, 2, 3]
// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
// lldb-command:print zs
// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
// lldbr-command:continue

#![allow(unused_variables)]
#![allow(dead_code)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

struct ZeroSizedStruct;

struct StructWithZeroSizedField {
    x: ZeroSizedStruct,
    y: u32,
    z: ZeroSizedStruct,
    w: u64
}

fn main() {
    let v = vec![1,2,3];

    let zs = StructWithZeroSizedField {
        x: ZeroSizedStruct,
        y: 123,
        z: ZeroSizedStruct,
        w: 456
    };

    zzz(); // #break
}

fn zzz() { () }
<commit_msg>fix debuginfo/issue22656 with LLDB 8<commit_after>// This test makes sure that the LLDB pretty printer does not throw an exception
// when trying to handle a Vec<> or anything else that contains zero-sized
// fields.

// min-lldb-version: 310
// ignore-gdb
// ignore-tidy-linelength

// compile-flags:-g

// === LLDB TESTS ==================================================================================
// lldb-command:run

// lldb-command:print v
// lldbg-check:[...]$0 = vec![1, 2, 3]
// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
// lldb-command:print zs
// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct[...], y: 123, z: ZeroSizedStruct[...], w: 456 }
// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
// lldbr-command:continue

#![allow(unused_variables)]
#![allow(dead_code)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

struct ZeroSizedStruct;

struct StructWithZeroSizedField {
    x: ZeroSizedStruct,
    y: u32,
    z: ZeroSizedStruct,
    w: u64
}

fn main() {
    let v = vec![1,2,3];

    let zs = StructWithZeroSizedField {
        x: ZeroSizedStruct,
        y: 123,
        z: ZeroSizedStruct,
        w: 456
    };

    zzz(); // #break
}

fn zzz() { () }
<|endoftext|>


<commit_before>// https://leetcode.com/problems/number-of-ways-to-split-array/
pub fn ways_to_split_array(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", ways_to_split_array(vec![10, 4, -8, 7])); // 2
    println!("{}", ways_to_split_array(vec![2, 3, 1, 0])); // 2
}
<commit_msg>Solve problem 2270<commit_after>// https://leetcode.com/problems/number-of-ways-to-split-array/
pub fn ways_to_split_array(nums: Vec<i32>) -> i32 {
    let mut prefix_sums: Vec<i64> = vec![0; nums.len()];
    for (i, num) in nums.iter().enumerate() {
        prefix_sums[i] = if i == 0 {
            *num as i64
        } else {
            prefix_sums[i - 1] + *num as i64
        };
    }
    let mut answer = 0;
    for i in 0..(nums.len() - 1) {
        let left = prefix_sums[i];
        let right = prefix_sums[nums.len() - 1] - prefix_sums[i];
        if left >= right {
            answer += 1;
        }
    }
    answer
}

fn main() {
    println!("{}", ways_to_split_array(vec![10, 4, -8, 7])); // 2
    println!("{}", ways_to_split_array(vec![2, 3, 1, 0])); // 2
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/node-with-highest-edge-score/
pub fn edge_score(edges: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", edge_score(vec![1, 0, 0, 0, 0, 7, 7, 5])); // 7
    println!("{}", edge_score(vec![2, 0, 0, 2])); // 0
}
<commit_msg>Solve problem 2374<commit_after>use std::collections::HashMap;

// https://leetcode.com/problems/node-with-highest-edge-score/
pub fn edge_score(edges: Vec<i32>) -> i32 {
    let mut map: HashMap<i32, i64> = HashMap::new();
    for (i, edge) in edges.into_iter().enumerate() {
        *map.entry(edge).or_insert(0) += i as i64;
    }
    *map.iter()
        .max_by(|a, b| {
            if a.1 == b.1 {
                return b.0.cmp(a.0);
            }
            a.1.cmp(b.1)
        })
        .unwrap()
        .0
}

fn main() {
    println!("{}", edge_score(vec![1, 0, 0, 0, 0, 7, 7, 5])); // 7
    println!("{}", edge_score(vec![2, 0, 0, 2])); // 0
}
<|endoftext|>


<commit_before>#![crate_name = "helloworld-server"]
#![allow(unstable)]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::io;
use std::time::Duration;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new().unwrap();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        println!("Received {}", msg.as_str().unwrap());
        responder.send_str("World", 0).unwrap();
        io::timer::sleep(Duration::seconds(1));
    }
}
<commit_msg>io->old_io<commit_after>#![crate_name = "helloworld-server"]
#![allow(unstable)]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::old_io;
use std::time::Duration;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new().unwrap();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        println!("Received {}", msg.as_str().unwrap());
        responder.send_str("World", 0).unwrap();
        old_io::timer::sleep(Duration::seconds(1));
    }
}
<|endoftext|>


<commit_before>use diesel::*;

use helpers::connection;

table! {
    my_structs (foo) {
        foo -> Integer,
        bar -> Integer,
    }
}

#[test]
fn named_struct_definition() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct MyStruct {
        foo: i32,
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table
        .select_by::<MyStruct>()
        .get_result::<MyStruct>(&conn);
    assert!(data.is_err());
}

#[test]
fn tuple_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct MyStruct(
        #[column_name = "foo"] i32,
        #[table_name = "my_structs"]
        #[column_name = "bar"]
        i32,
    );

    let conn = connection();
    let data = my_structs::table
        .select_by::<MyStruct>()
        .get_result::<MyStruct>(&conn);
    assert!(data.is_err());
}

// FIXME: Test usage with renamed columns

#[test]
fn embedded_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: B,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    struct B {
        #[table_name = "my_structs"]
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table.select_by::<A>().get_result::<A>(&conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct B {
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table.select_by::<A>().get_result::<A>(&conn);
    assert!(data.is_err());
}
<commit_msg>Fix derive tests<commit_after>use diesel::*;

use helpers::connection;

table! {
    my_structs (foo) {
        foo -> Integer,
        bar -> Integer,
    }
}

#[test]
fn named_struct_definition() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct MyStruct {
        foo: i32,
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(&conn);
    assert!(data.is_err());
}

#[test]
fn tuple_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct MyStruct(#[column_name = "foo"] i32, #[column_name = "bar"] i32);

    let conn = connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(&conn);
    assert!(data.is_err());
}

// FIXME: Test usage with renamed columns

#[test]
fn embedded_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: B,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct B {
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table.select(A::as_select()).get_result(&conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[table_name = "my_structs"]
    struct B {
        bar: i32,
    }

    let conn = connection();
    let data = my_structs::table.select(A::as_select()).get_result(&conn);
    assert!(data.is_err());
}
<|endoftext|>