<commit_before>use crate::ast::Field;
use crate::attr::Display;
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::HashSet as Set;
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let fields: Set<Member> = fields.iter().map(|f| f.member.clone()).collect();

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !fields.contains(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let ident = take_ident(&mut read);
                    Member::Named(Ident::new(&ident, span))
                }
                _ => continue,
            };
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
                has_trailing_comma = false;
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if read.starts_with('}') && fields.contains(&member) {
                has_bonus_display = true;
                args.extend(quote_spanned!(span=> .as_display()));
            }
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident: Ident = input.parse()?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> String {
    let mut ident = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    ident
}
<commit_msg>Fix missing comma between named format elements<commit_after>use crate::ast::Field;
use crate::attr::Display;
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::HashSet as Set;
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let fields: Set<Member> = fields.iter().map(|f| f.member.clone()).collect();

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !fields.contains(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let ident = take_ident(&mut read);
                    Member::Named(Ident::new(&ident, span))
                }
                _ => continue,
            };
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if read.starts_with('}') && fields.contains(&member) {
                has_bonus_display = true;
                args.extend(quote_spanned!(span=> .as_display()));
            }
            has_trailing_comma = false;
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident: Ident = input.parse()?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> String {
    let mut ident = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    ident
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Author: Arun Raghavan <arun@arunraghavan.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_type = "cdylib"]

#[macro_use]
extern crate glib;
#[macro_use]
extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base;

mod s3src;
mod s3url;

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    s3src::register(plugin)
}

gst_plugin_define!(
    s3src,
    "Amazon S3 Plugin",
    plugin_init,
    "1.0",
    "MIT/X11",
    "s3",
    "s3",
    "https://github.com/ford-prefect/gst-plugin-s3",
    "2017-04-17"
);
<commit_msg>s3: Fix plugin name<commit_after>// Copyright (C) 2017 Author: Arun Raghavan <arun@arunraghavan.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_type = "cdylib"]

#[macro_use]
extern crate glib;
#[macro_use]
extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base;

mod s3src;
mod s3url;

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    s3src::register(plugin)
}

gst_plugin_define!(
    s3,
    "Amazon S3 Plugin",
    plugin_init,
    "1.0",
    "MIT/X11",
    "s3",
    "s3",
    "https://github.com/ford-prefect/gst-plugin-s3",
    "2017-04-17"
);
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{
    code_action::on_code_action,
    completion::on_completion,
    goto_definition::on_goto_definition,
    hover::on_hover,
    lsp::{
        set_actual_server_status, set_starting_status, CompletionOptions, Connection,
        GotoDefinition, HoverRequest, InitializeParams, Message, ServerCapabilities,
        ServerResponse, TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
    },
    lsp_process_error::{LSPProcessError, LSPProcessResult},
    references::on_references,
    shutdown::{on_exit, on_shutdown},
    status_reporting::LSPStatusReporter,
    text_documents::on_did_save_text_document,
    text_documents::{
        on_did_change_text_document, on_did_close_text_document, on_did_open_text_document,
    },
};
use common::{PerfLogEvent, PerfLogger};
use crossbeam::{SendError, Sender};
use log::debug;
use lsp_server::{ErrorCode, Notification, ResponseError};
use lsp_types::{
    notification::{
        DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, DidSaveTextDocument, Exit,
    },
    request::{CodeActionRequest, Completion, References, Shutdown},
    CodeActionProviderCapability,
};
use relay_compiler::config::Config;
use std::sync::{Arc, RwLock};
mod lsp_request_dispatch;
use lsp_request_dispatch::LSPRequestDispatch;
mod lsp_notification_dispatch;
use lsp_notification_dispatch::LSPNotificationDispatch;
mod lsp_state;
pub use lsp_state::LSPExtraDataProvider;
pub(crate) use lsp_state::{LSPState, LSPStateError};

/// Initializes an LSP connection, handling the `initialize` message and `initialized` notification
/// handshake.
pub fn initialize(connection: &Connection) -> LSPProcessResult<InitializeParams> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: Some(vec!["(".into(), "\n".into(), ",".into(), "@".into()]),
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });

    server_capabilities.hover_provider = Some(true);
    server_capabilities.definition_provider = Some(true);
    server_capabilities.references_provider = Some(true);
    server_capabilities.code_action_provider = Some(CodeActionProviderCapability::Simple(true));

    let server_capabilities = serde_json::to_value(&server_capabilities)?;
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params)?;
    Ok(params)
}

/// Run the main server loop
pub async fn run<TPerfLogger: PerfLogger + 'static>(
    connection: Connection,
    mut config: Config,
    _params: InitializeParams,
    perf_logger: Arc<TPerfLogger>,
    extra_data_provider: Box<dyn LSPExtraDataProvider + Send + Sync>,
) -> LSPProcessResult<()>
where
    TPerfLogger: PerfLogger + 'static,
{
    debug!(
        "Running language server with config root {:?}",
        config.root_dir
    );
    set_starting_status(&connection.sender);

    let lsp_state_errors: Arc<RwLock<Vec<LSPStateError>>> = Default::default();

    config.status_reporter = Box::new(LSPStatusReporter::new(
        config.root_dir.clone(),
        connection.sender.clone(),
        Arc::clone(&lsp_state_errors),
    ));

    let mut lsp_state = LSPState::create_state(
        Arc::new(config),
        lsp_state_errors,
        extra_data_provider,
        Arc::clone(&perf_logger),
    )
    .await?;

    set_actual_server_status(&connection.sender, &lsp_state.get_errors());

    for msg in connection.receiver {
        debug!("LSP message received {:?}", msg);
        match msg {
            Message::Request(req) => {
                handle_request(&mut lsp_state, req, &connection.sender, &perf_logger)
                    .map_err(LSPProcessError::from)?;
            }
            Message::Notification(notification) => {
                handle_notification(&mut lsp_state, notification, &perf_logger);
            }
            _ => {
                // Ignore responses for now
            }
        }
    }

    Ok(())
}

fn handle_request<TPerfLogger: PerfLogger + 'static>(
    lsp_state: &mut LSPState<TPerfLogger>,
    request: lsp_server::Request,
    sender: &Sender<Message>,
    perf_logger: &Arc<TPerfLogger>,
) -> Result<(), SendError<Message>> {
    let get_server_response_bound = |req| dispatch_request(req, lsp_state);
    let get_response = with_request_logging(perf_logger, get_server_response_bound);

    sender.send(Message::Response(get_response(request)))
}

fn dispatch_request<TPerfLogger: PerfLogger + 'static>(
    request: lsp_server::Request,
    lsp_state: &mut LSPState<TPerfLogger>,
) -> ServerResponse {
    let get_response = || -> Result<_, ServerResponse> {
        let request = LSPRequestDispatch::new(request, lsp_state)
            .on_request_sync::<HoverRequest>(on_hover)?
            .on_request_sync::<GotoDefinition>(on_goto_definition)?
            .on_request_sync::<References>(on_references)?
            .on_request_sync::<Completion>(on_completion)?
            .on_request_sync::<CodeActionRequest>(on_code_action)?
            .on_request_sync::<Shutdown>(on_shutdown)?
            .request();

        // If we have gotten here, we have not handled the request
        Ok(ServerResponse {
            id: request.id,
            result: None,
            error: Some(ResponseError {
                code: ErrorCode::MethodNotFound as i32,
                data: None,
                message: format!("No handler registered for method '{}'", request.method),
            }),
        })
    };
    get_response().unwrap_or_else(|response| response)
}

fn with_request_logging<'a, TPerfLogger: PerfLogger + 'static>(
    perf_logger: &'a Arc<TPerfLogger>,
    get_response: impl FnOnce(lsp_server::Request) -> ServerResponse + 'a,
) -> impl FnOnce(lsp_server::Request) -> ServerResponse + 'a {
    move |request| {
        let lsp_request_event = perf_logger.create_event("lsp_message");
        lsp_request_event.string("lsp_method", request.method.clone());
        lsp_request_event.string("lsp_type", "request".to_string());
        let lsp_request_processing_time = lsp_request_event.start("lsp_message_processing_time");

        let response = get_response(request);

        if response.result.is_some() {
            lsp_request_event.string("lsp_outcome", "success".to_string());
        } else if let Some(error) = &response.error {
            lsp_request_event.string("lsp_outcome", "error".to_string());
            if let Some(data) = &error.data {
                lsp_request_event.string("lsp_error_data", data.to_string());
            }
        }
        // N.B. we don't handle the case where the ServerResponse has neither a result nor
        // an error, which is an invalid state.

        lsp_request_event.stop(lsp_request_processing_time);
        perf_logger.complete_event(lsp_request_event);

        response
    }
}

fn handle_notification<TPerfLogger: PerfLogger + 'static>(
    lsp_state: &mut LSPState<TPerfLogger>,
    notification: Notification,
    perf_logger: &Arc<TPerfLogger>,
) {
    let lsp_notification_event = perf_logger.create_event("lsp_message");
    lsp_notification_event.string("lsp_method", notification.method.clone());
    lsp_notification_event.string("lsp_type", "notification".to_string());
    let lsp_notification_processing_time =
        lsp_notification_event.start("lsp_message_processing_time");

    let notification_result = dispatch_notification(notification, lsp_state);

    // The only possible error (for now) is not handling the notification.
    // N.B. is_ok is correct here.
    if notification_result.is_ok() {
        lsp_notification_event.string("lsp_outcome", "error".to_string());
    }

    lsp_notification_event.stop(lsp_notification_processing_time);
    perf_logger.complete_event(lsp_notification_event);
}

fn dispatch_notification<TPerfLogger: PerfLogger + 'static>(
    notification: lsp_server::Notification,
    lsp_state: &mut LSPState<TPerfLogger>,
) -> Result<(), ()> {
    let notification = LSPNotificationDispatch::new(notification, lsp_state)
        .on_notification_sync::<DidOpenTextDocument>(on_did_open_text_document)?
        .on_notification_sync::<DidCloseTextDocument>(on_did_close_text_document)?
        .on_notification_sync::<DidChangeTextDocument>(on_did_change_text_document)?
        .on_notification_sync::<DidSaveTextDocument>(on_did_save_text_document)?
        .on_notification_sync::<Exit>(on_exit)?
        .notification();

    // If we have gotten here, we have not handled the notification
    debug!(
        "Error: no handler registered for notification '{}'",
        notification.method
    );
    Ok(())
}
<commit_msg>disable code action while fixing - T83753507<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{
    code_action::on_code_action,
    completion::on_completion,
    goto_definition::on_goto_definition,
    hover::on_hover,
    lsp::{
        set_actual_server_status, set_starting_status, CompletionOptions, Connection,
        GotoDefinition, HoverRequest, InitializeParams, Message, ServerCapabilities,
        ServerResponse, TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
    },
    lsp_process_error::{LSPProcessError, LSPProcessResult},
    references::on_references,
    shutdown::{on_exit, on_shutdown},
    status_reporting::LSPStatusReporter,
    text_documents::on_did_save_text_document,
    text_documents::{
        on_did_change_text_document, on_did_close_text_document, on_did_open_text_document,
    },
};
use common::{PerfLogEvent, PerfLogger};
use crossbeam::{SendError, Sender};
use log::debug;
use lsp_server::{ErrorCode, Notification, ResponseError};
use lsp_types::{
    notification::{
        DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, DidSaveTextDocument, Exit,
    },
    request::{CodeActionRequest, Completion, References, Shutdown},
    CodeActionProviderCapability,
};
use relay_compiler::config::Config;
use std::sync::{Arc, RwLock};
mod lsp_request_dispatch;
use lsp_request_dispatch::LSPRequestDispatch;
mod lsp_notification_dispatch;
use lsp_notification_dispatch::LSPNotificationDispatch;
mod lsp_state;
pub use lsp_state::LSPExtraDataProvider;
pub(crate) use lsp_state::{LSPState, LSPStateError};

/// Initializes an LSP connection, handling the `initialize` message and `initialized` notification
/// handshake.
pub fn initialize(connection: &Connection) -> LSPProcessResult<InitializeParams> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: Some(vec!["(".into(), "\n".into(), ",".into(), "@".into()]),
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });

    server_capabilities.hover_provider = Some(true);
    server_capabilities.definition_provider = Some(true);
    server_capabilities.references_provider = Some(true);
    let _code_action_provider = Some(CodeActionProviderCapability::Simple(true));
    server_capabilities.code_action_provider = None;

    let server_capabilities = serde_json::to_value(&server_capabilities)?;
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params)?;
    Ok(params)
}

/// Run the main server loop
pub async fn run<TPerfLogger: PerfLogger + 'static>(
    connection: Connection,
    mut config: Config,
    _params: InitializeParams,
    perf_logger: Arc<TPerfLogger>,
    extra_data_provider: Box<dyn LSPExtraDataProvider + Send + Sync>,
) -> LSPProcessResult<()>
where
    TPerfLogger: PerfLogger + 'static,
{
    debug!(
        "Running language server with config root {:?}",
        config.root_dir
    );
    set_starting_status(&connection.sender);

    let lsp_state_errors: Arc<RwLock<Vec<LSPStateError>>> = Default::default();

    config.status_reporter = Box::new(LSPStatusReporter::new(
        config.root_dir.clone(),
        connection.sender.clone(),
        Arc::clone(&lsp_state_errors),
    ));

    let mut lsp_state = LSPState::create_state(
        Arc::new(config),
        lsp_state_errors,
        extra_data_provider,
        Arc::clone(&perf_logger),
    )
    .await?;

    set_actual_server_status(&connection.sender, &lsp_state.get_errors());

    for msg in connection.receiver {
        debug!("LSP message received {:?}", msg);
        match msg {
            Message::Request(req) => {
                handle_request(&mut lsp_state, req, &connection.sender, &perf_logger)
                    .map_err(LSPProcessError::from)?;
            }
            Message::Notification(notification) => {
                handle_notification(&mut lsp_state, notification, &perf_logger);
            }
            _ => {
                // Ignore responses for now
            }
        }
    }

    Ok(())
}

fn handle_request<TPerfLogger: PerfLogger + 'static>(
    lsp_state: &mut LSPState<TPerfLogger>,
    request: lsp_server::Request,
    sender: &Sender<Message>,
    perf_logger: &Arc<TPerfLogger>,
) -> Result<(), SendError<Message>> {
    let get_server_response_bound = |req| dispatch_request(req, lsp_state);
    let get_response = with_request_logging(perf_logger, get_server_response_bound);

    sender.send(Message::Response(get_response(request)))
}

fn dispatch_request<TPerfLogger: PerfLogger + 'static>(
    request: lsp_server::Request,
    lsp_state: &mut LSPState<TPerfLogger>,
) -> ServerResponse {
    let get_response = || -> Result<_, ServerResponse> {
        let request = LSPRequestDispatch::new(request, lsp_state)
            .on_request_sync::<HoverRequest>(on_hover)?
            .on_request_sync::<GotoDefinition>(on_goto_definition)?
            .on_request_sync::<References>(on_references)?
            .on_request_sync::<Completion>(on_completion)?
            .on_request_sync::<CodeActionRequest>(on_code_action)?
            .on_request_sync::<Shutdown>(on_shutdown)?
            .request();

        // If we have gotten here, we have not handled the request
        Ok(ServerResponse {
            id: request.id,
            result: None,
            error: Some(ResponseError {
                code: ErrorCode::MethodNotFound as i32,
                data: None,
                message: format!("No handler registered for method '{}'", request.method),
            }),
        })
    };
    get_response().unwrap_or_else(|response| response)
}

fn with_request_logging<'a, TPerfLogger: PerfLogger + 'static>(
    perf_logger: &'a Arc<TPerfLogger>,
    get_response: impl FnOnce(lsp_server::Request) -> ServerResponse + 'a,
) -> impl FnOnce(lsp_server::Request) -> ServerResponse + 'a {
    move |request| {
        let lsp_request_event = perf_logger.create_event("lsp_message");
        lsp_request_event.string("lsp_method", request.method.clone());
        lsp_request_event.string("lsp_type", "request".to_string());
        let lsp_request_processing_time = lsp_request_event.start("lsp_message_processing_time");

        let response = get_response(request);

        if response.result.is_some() {
            lsp_request_event.string("lsp_outcome", "success".to_string());
        } else if let Some(error) = &response.error {
            lsp_request_event.string("lsp_outcome", "error".to_string());
            if let Some(data) = &error.data {
                lsp_request_event.string("lsp_error_data", data.to_string());
            }
        }
        // N.B. we don't handle the case where the ServerResponse has neither a result nor
        // an error, which is an invalid state.

        lsp_request_event.stop(lsp_request_processing_time);
        perf_logger.complete_event(lsp_request_event);

        response
    }
}

fn handle_notification<TPerfLogger: PerfLogger + 'static>(
    lsp_state: &mut LSPState<TPerfLogger>,
    notification: Notification,
    perf_logger: &Arc<TPerfLogger>,
) {
    let lsp_notification_event = perf_logger.create_event("lsp_message");
    lsp_notification_event.string("lsp_method", notification.method.clone());
    lsp_notification_event.string("lsp_type", "notification".to_string());
    let lsp_notification_processing_time =
        lsp_notification_event.start("lsp_message_processing_time");

    let notification_result = dispatch_notification(notification, lsp_state);

    // The only possible error (for now) is not handling the notification.
    // N.B. is_ok is correct here.
    if notification_result.is_ok() {
        lsp_notification_event.string("lsp_outcome", "error".to_string());
    }

    lsp_notification_event.stop(lsp_notification_processing_time);
    perf_logger.complete_event(lsp_notification_event);
}

fn dispatch_notification<TPerfLogger: PerfLogger + 'static>(
    notification: lsp_server::Notification,
    lsp_state: &mut LSPState<TPerfLogger>,
) -> Result<(), ()> {
    let notification = LSPNotificationDispatch::new(notification, lsp_state)
        .on_notification_sync::<DidOpenTextDocument>(on_did_open_text_document)?
        .on_notification_sync::<DidCloseTextDocument>(on_did_close_text_document)?
        .on_notification_sync::<DidChangeTextDocument>(on_did_change_text_document)?
        .on_notification_sync::<DidSaveTextDocument>(on_did_save_text_document)?
        .on_notification_sync::<Exit>(on_exit)?
        .notification();

    // If we have gotten here, we have not handled the notification
    debug!(
        "Error: no handler registered for notification '{}'",
        notification.method
    );
    Ok(())
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/apply-operations-to-an-array/
pub fn apply_operations(nums: Vec<i32>) -> Vec<i32> {
    todo!()
}

fn main() {
    println!("{:?}", apply_operations(vec![1, 2, 2, 1, 1, 0])); // [1,4,2,0,0,0]
    println!("{:?}", apply_operations(vec![0, 1])); // [1,0]
}
<commit_msg>Solve problem 2460<commit_after>// https://leetcode.com/problems/apply-operations-to-an-array/
pub fn apply_operations(mut nums: Vec<i32>) -> Vec<i32> {
    let mut answer = vec![0; nums.len()];
    let mut j = 0;
    for i in 0..nums.len() {
        if i + 1 < nums.len() && nums[i] == nums[i + 1] {
            nums[i] = nums[i] * 2;
            nums[i + 1] = 0;
            if nums[i] > 0 {
                answer[j] = nums[i];
                j += 1;
            }
        } else {
            if nums[i] > 0 {
                answer[j] = nums[i];
                j += 1;
            }
        }
    }
    answer
}

fn main() {
    println!("{:?}", apply_operations(vec![1, 2, 2, 1, 1, 0])); // [1,4,2,0,0,0]
    println!("{:?}", apply_operations(vec![0, 1])); // [1,0]
}
<|endoftext|>


<commit_before>#[cfg(target_arch="x86")]
const B: [usize; 5] = [ 0x2, 0xC, 0xF0
                      , 0xFF00
                      , 0xFFFF0000];
#[cfg(target_arch="x86")]
const S: [usize; 5] = [ 1, 2, 4, 8, 16 ];

#[cfg(target_arch="x86_64")]
const B: [usize; 6] = [ 0x2, 0xC, 0xF0
                      , 0xFF00, 0xFFFF0000
                      , 0xFFFFFFFF00000000];
#[cfg(target_arch="x86_64")]
const S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];

pub trait PowersOf2 {
    fn is_pow2(&self) -> bool;
    fn next_pow2(&self) -> Self;
    fn log2(&self) -> Self;
}

impl PowersOf2 for usize {
    fn is_pow2(&self) -> bool {
        *self != 0 && (self & (self - 1)) == 0
    }

    /// Returns the next power of 2
    fn next_pow2(&self) -> usize {
        let mut v = *self;
        if v == 0 {
            1
        } else {
            v -= 1;
            v = v | (v >> 1);
            v = v | (v >> 2);
            v = v | (v >> 4);
            v = v | (v >> 8);
            v = v | (v >> 16);
            v + 1
        }
    }

    #[cfg(not(any(target_arch="x86_64", target_arch="x86")))]
    fn log2(&self) -> usize {
        // This is the "obvious" log base 2 implementation. The lookup table
        // -based approach would be much faster, but we can't use it for
        // `usize` since we aren't sure what size a usize is without conditional
        // compilation.
        unimplemented!()
    }

    #[cfg(any(target_arch="x86_64", target_arch="x86"))]
    fn log2(&self) -> usize {
        // // let mut r: usize = 0;
        // // let mut v = *self;
        // S.iter()
        //  .zip(B.iter()) // this purely-functional implementation may be slower
        //  .fold((0, *self), // but it's cute and I had fun figuring it out
        //     |(r, v), (s, b)| if v & b != 0 { (r | s, v >> s) }
        //                      else { (r, v) })
        //   .0
        // // for in 0..S.len() {
        // //     if v & B[i] != 0 {
        // //         v = v >> S[i];
        // //         r = r | S[i];
        // //     }
        // // }
        // // r
        //
        let mut res = 0;
        let mut num = *self;
        loop {
            num >>= 1;

            if num == 0 {
                break;
            }

            res += 1;
        }

        res
    }
}

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

    #[test]
    fn test_next_pow2() {
        assert_eq!(2usize.next_pow2(), 2);
        assert_eq!(0usize.next_pow2(), 1);
        assert_eq!(3usize.next_pow2(), 4);
        assert_eq!(5678usize.next_pow2(), 8192);
    }
}
<commit_msg>[alloc] Made log2 implementation much more structured programming<commit_after>#[cfg(target_arch="x86")]
const B: [usize; 5] = [ 0x2, 0xC, 0xF0
                      , 0xFF00
                      , 0xFFFF0000];
#[cfg(target_arch="x86")]
const S: [usize; 5] = [ 1, 2, 4, 8, 16 ];

#[cfg(target_arch="x86_64")]
const B: [usize; 6] = [ 0x2, 0xC, 0xF0
                      , 0xFF00, 0xFFFF0000
                      , 0xFFFFFFFF00000000];
#[cfg(target_arch="x86_64")]
const S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];

pub trait PowersOf2 {
    fn is_pow2(&self) -> bool;
    fn next_pow2(&self) -> Self;
    fn log2(&self) -> Self;
}

impl PowersOf2 for usize {
    fn is_pow2(&self) -> bool {
        *self != 0 && (self & (self - 1)) == 0
    }

    /// Returns the next power of 2
    fn next_pow2(&self) -> usize {
        let mut v = *self;
        if v == 0 {
            1
        } else {
            v -= 1;
            v = v | (v >> 1);
            v = v | (v >> 2);
            v = v | (v >> 4);
            v = v | (v >> 8);
            v = v | (v >> 16);
            v + 1
        }
    }

    #[cfg(not(any(target_arch="x86_64", target_arch="x86")))]
    fn log2(&self) -> usize {
        // This is the "obvious" log base 2 implementation. The lookup table
        // -based approach would be much faster, but we can't use it for
        // `usize` since we aren't sure what size a usize is without conditional
        // compilation.
        unimplemented!()
    }

    #[cfg(any(target_arch="x86_64", target_arch="x86"))]
    fn log2(&self) -> usize {
        // let mut r: usize = 0;
        // let mut v = *self;
        // S.iter()
        //  .zip(B.iter()) // this purely-functional implementation may be slower
        //  .fold((0, *self), // but it's cute and I had fun figuring it out
        //     |(r, v), (s, b)| if v & b != 0 { (r | s, v >> s) }
        //                      else { (r, v) })
        //   .0
        // for i in 0..S.len() {
        //     if v & B[i] != 0 {
        //         v >>= S[i];
        //         r |=  S[i];
        //     }
        // }
        // r
        //
        let mut res = 0;
        let mut num = *self >> 1;
        while num != 0 {
            res += 1;
            num >>= 1;
        }
        res
    }
}

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

    #[test]
    fn test_next_pow2() {
        assert_eq!(2usize.next_pow2(), 2);
        assert_eq!(0usize.next_pow2(), 1);
        assert_eq!(3usize.next_pow2(), 4);
        assert_eq!(5678usize.next_pow2(), 8192);
    }
}
<|endoftext|>


<commit_before>/* kernel::sgash.rs */

use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use core::vec::Vec;
use core::mem::Allocator;
use kernel::*;
use super::super::platform::*;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };
pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

#[lang = "exchange_free"]
fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	putchar(*c as char);
    }
}

pub unsafe fn output(s: cstr)
{
    let mut x = 0;
    while *(((s.p as uint)+x) as *char) != '\0'
    {
	putchar(*(((s.p as uint)+x) as *char));
	x += 1;
    }
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard
    if (true) {
	match x {
	    13		=>	{ prompt(); }
	    127		=>	{
		if (buffer.delete_char()) {
		    putchar('');
		    putchar(' ');
		    putchar('');
		}
	    }
	    _		=>	{
		if (buffer.add_char(x)) { putchar(x as char); }
	    }
	}
    }
    else {
	keycode(x);
    }
}

fn keycode(x: u8) {
    let mut x = x;
    while ( x != 0 ) {
	putchar((x%10+ ('0' as u8) ) as char);
	x = x/10;
    }
    putchar(' ');
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    prompt();
}

unsafe fn prompt() {
    putstr(&"\nsgash > ");
    output(buffer);
}

/* BUFFER MODIFICATION FUNCTIONS */

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
	let (x, y) = memory::allocator.alloc(size);
	let this = cstr {
	    p: x,
	    p_cstr_i: 0,
	    max: y
	};
	this
    }

    unsafe fn add_char(&mut self, x: u8) -> bool{
	if (self.p_cstr_i == self.max) { return false; }
	*(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
	self.p_cstr_i += 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn delete_char(&mut self) -> bool {
	if (self.p_cstr_i == 0) { return false; }
	self.p_cstr_i -= 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn reset(&mut self) {
	self.p_cstr_i = 0;
	*(self.p as *mut char) = '\0';
    }
}

/* Utility functions! */
/*
fn eq(a: *mut u8, b: *mut u8) {
    ind = 0;
    while (a[i] !=
}
*/
<commit_msg>Got basic commands and a hacky filesystem working, but it randomly freezes sometimes...?<commit_after>/* kernel::sgash.rs */

use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use core::vec::Vec;
use core::mem::Allocator;
use kernel::*;
use super::super::platform::*;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };
pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

#[lang = "exchange_free"]
fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	putchar(*c as char);
    }
}

pub unsafe fn output(s: cstr)
{
    let mut x = 0;
    while *(((s.p as uint)+x) as *char) != '\0'
    {
	putchar(*(((s.p as uint)+x) as *char));
	x += 1;
    }
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard
    if (true) {
	match x {
	    13		=>	{ prompt(); }
	    127		=>	{
		if (buffer.delete_char()) {
		    putchar('');
		    putchar(' ');
		    putchar('');
		}
	    }
	    _		=>	{
		if (buffer.add_char(x)) { putchar(x as char); }
	    }
	}
    }
    else {
	keycode(x);
    }
}

fn keycode(x: u8) {
    let mut x = x;
    while ( x != 0 ) {
	putchar((x%10+ ('0' as u8) ) as char);
	x = x/10;
    }
    putchar(' ');
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    prompt();
}

unsafe fn prompt() {
    if (buffer.eq(&cstr::from_str(&"ls"))) { putstr( &"\na\tb") };
    match buffer.getarg(' ', 0) {
	Some(y)	=> {
	    if(y.eq(&cstr::from_str(&"cat"))) {
		match buffer.getarg(' ', 1) {
		    Some(x)	=> {
			if(x.eq(&cstr::from_str(&"a"))) { putstr( &"\nHello"); }
			if(x.eq(&cstr::from_str(&"b"))) { putstr( &"\nworld!"); }
		    }
		    None	=> { }
		};
	    }
	}
	None	=> { }
    };

    putstr(&"\nsgash > ");
    buffer.reset();
}

/* BUFFER MODIFICATION FUNCTIONS */

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
	let (x, y) = memory::allocator.alloc(size);
	let this = cstr {
	    p: x,
	    p_cstr_i: 0,
	    max: y
	};
	this
    }

    unsafe fn from_str(s: &str) -> cstr {
	let mut this = cstr::new(256);
	for c in slice::iter(as_bytes(s)) {
	    this.add_char(*c);
	};
	this
    }

    unsafe fn add_char(&mut self, x: u8) -> bool{
	if (self.p_cstr_i == self.max) { return false; }
	*(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
	self.p_cstr_i += 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn delete_char(&mut self) -> bool {
	if (self.p_cstr_i == 0) { return false; }
	self.p_cstr_i -= 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn reset(&mut self) {
	self.p_cstr_i = 0;
	*(self.p as *mut char) = '\0';
    }

    unsafe fn eq(&self, other: &cstr) -> bool {
	if (self.p_cstr_i != other.p_cstr_i) { return false; }
	else {
	    let mut x = 0;
	    let mut selfp: uint = self.p as uint;
	    let mut otherp: uint = other.p as uint;
	    while (x < self.p_cstr_i) {
		if (*(selfp as *char) != *(otherp as *char)) { return false; }
		selfp += 1;
		otherp += 1;
		x += 1;
	    }
	    true
	}
    }

    unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
	let mut ind: uint = 0;
	let mut found = k == 0;
	let mut selfp: uint = self.p as uint;
	let mut s = cstr::new(256);
	loop {
	    if (*(selfp as *char) == '\0') {
		// End of string
		if (found) { return Some(s); }
		else { return None; }

	    };
	    if (*(selfp as *u8) == delim as u8) {
		if (found) { return Some(s); }
		k -= 1;
	    };
	    if (found) {
		s.add_char(*(selfp as *u8));
	    };
	    found = k == 0;
	    selfp += 1;
	    ind += 1;
	    if (ind == self.max) {
		putstr(&"\nSometing broke!");
		return None;
	    }
	}
    }

}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::cmp::{max, min};
use std::convert::AsRef;
use std::io;
use std::fs;
use std::path::Path;

use bio::io::gff::{self, GffType};
use itertools::{GroupBy, Group, Itertools};
use linked_hash_map::LinkedHashMap;

use {Coord, Exon, ExonFeatureKind as EFK, Gene, GBuilder, Strand, Transcript, Error};

// Various commonly-used feature column values
const GENE_STR: &'static str = "gene";
const TRANSCRIPT_STR: &'static str = "transcript";
const EXON_STR: &'static str = "exon";
const UTR_STR: &'static str = "UTR";
const UTR5_STR: &'static str = "UTR5";
const UTR3_STR: &'static str = "UTR3";
const CDS_STR: &'static str = "CDS";
const START_CODON_STR: &'static str = "start_codon";
const STOP_CODON_STR: &'static str = "stop_codon";

// Value for unknown columns.
const UNK_STR: &'static str = ".";

// Commonly-used attribute keys.
const GENE_ID_STR: &'static str = "gene_id";
const TRANSCRIPT_ID_STR: &'static str = "transcript_id";

// Initial coordinate for features.
const INIT_COORD: (u64, u64) = (::std::u64::MAX, ::std::u64::MIN);

pub struct Reader<R: io::Read> {
    inner: gff::Reader<R>,
}

impl<R: io::Read> Reader<R> {

    pub fn from_reader(in_reader: R, gff_type: GffType) -> Reader<R> {
        Reader {
            inner: gff::Reader::new(in_reader, gff_type),
        }
    }

    pub fn genes(&mut self) -> GffGenes<R> {
        GffGenes {
            inner: self.records().group_by(GffGenes::<R>::gene_groupf),
        }
    }

    fn records(&mut self) -> GffRecords<R> {
        GffRecords {
            inner: self.inner.records()
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<Path>>(path: P, gff_type: GffType) -> io::Result<Self> {
        fs::File::open(path).map(|file| Reader::from_reader(file, gff_type))
    }
}

struct GffRecords<'a, R: 'a> where R: io::Read {
    inner: gff::Records<'a, R>,
}

impl<'a, R> Iterator for GffRecords<'a, R> where R: io::Read {

    type Item = Result<gff::Record, Error>;

    fn next(&mut self) -> Option<Result<gff::Record, Error>> {
        self.inner.next()
            .map(|row| {
                row.or_else(|err| Err(Error::from(err)))
            })
    }
}

pub struct GffGenes<'a, R: 'a> where R: io::Read, {
    inner: GroupBy<GxGroupKey, GffRecords<'a, R>, GxGroupFunc>,
}

type GxGroupKey = Option<(String, String, Strand)>;

type GxGroupFunc = fn(&Result<gff::Record, Error>) -> GxGroupKey;

type GxGroupedRecs<'a, 'b, R> = Group<'b, GxGroupKey, GffRecords<'a, R>, GxGroupFunc>;

type RawTrxCoord = (Coord<u64>, Vec<Coord<u64>>, Option<Coord<u64>>);

impl<'a, R> GffGenes<'a, R> where R: io::Read {

    fn gene_groupf(result: &Result<gff::Record, Error>) -> GxGroupKey {
        result.as_ref().ok()
            .map(|res| {
                let gene_id = res.attributes().get(GENE_ID_STR)
                    .map(|gid| gid.as_str())
                    .unwrap_or("");
                let seq_name = String::from(res.seqname());
                let strand = res.strand().unwrap_or(Strand::Unknown);

                (String::from(gene_id), seq_name, strand)
            })
    }

    fn group_to_gene<'b>(group: (GxGroupKey, GxGroupedRecs<'a, 'b, R>)) -> Result<Gene, Error> {
        let (group_key, records) = group;
        match group_key {

            None => Err(records.filter_map(|x| x.err()).next().unwrap()),

            Some((gid, seq_name, strand)) => {

                let mut gene_coord = INIT_COORD;
                let mut trx_coords: LinkedHashMap<String, RawTrxCoord> = LinkedHashMap::new();

                for record in records {

                    let mut rec = record?;
                    rec.attributes_mut().remove(GENE_ID_STR);

                    let rtrx_entry = rec.attributes_mut()
                        .remove(TRANSCRIPT_ID_STR)
                        .ok_or(Error::Gff("required 'transcript_id' attribute not found"))
                        .map(|id| trx_coords.entry(id).or_insert((INIT_COORD, vec![], None)));

                    match rec.feature_type() {
                        GENE_STR => {
                            gene_coord = adjust_coord(gene_coord, &rec);
                        },
                        TRANSCRIPT_STR => {
                            let trx_entry = rtrx_entry?;
                            trx_entry.0 = adjust_coord(trx_entry.0, &rec);
                        },
                        EXON_STR => {
                            let trx_entry = rtrx_entry?;
                            (trx_entry.1).push((*rec.start() - 1, *rec.end()));
                        },
                        CDS_STR => {
                            let trx_entry = rtrx_entry?;
                            trx_entry.2 = (trx_entry.2).or(Some(INIT_COORD))
                                .map(|coord| adjust_coord(coord, &rec));
                        },
                        // TODO: How to best handle nested features? They may be out of order ...
                        _ => {},
                    }
                }

                GBuilder::new(seq_name, gene_coord.0, gene_coord.1)
                    .id(gid)
                    .strand(strand)
                    .transcript_coords(trx_coords)
                    .build()
            },
        }
    }
}

impl<'a, R> Iterator for GffGenes<'a, R> where R: io::Read {

    type Item = Result<Gene, Error>;

    fn next(&mut self) -> Option<Result<Gene, Error>> {
        self.inner.into_iter().map(Self::group_to_gene).next()
    }
}

struct GffRow(String, String, String, u64, u64, String, String, String, HashMap<String, String>);

impl From<GffRow> for gff::Record {
    fn from(row: GffRow) -> Self {
        let mut rec = gff::Record::default();
        *rec.seqname_mut() = row.0;
        *rec.source_mut() = row.1;
        *rec.feature_type_mut() = row.2;
        *rec.start_mut() = row.3 + 1;
        *rec.end_mut() = row.4;
        *rec.score_mut() = row.5;
        *rec.strand_mut() = row.6;
        *rec.frame_mut() = row.7;
        *rec.attributes_mut() = row.8;
        rec
    }
}

impl Gene {

    #[inline(always)]
    fn num_records(&self) -> usize {
        1 + self.transcripts().values()
            .map(|ref trx| trx.num_records())
            .fold(0, |acc, x| acc + x)
    }

    // TODO: also handle gene-level features
    fn to_gff_records(mut self) -> Result<Vec<gff::Record>, Error> {

        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());
        let gene_id = match self.id.take() {
            Some(gid) => {
                self.attributes.insert(GENE_ID_STR.to_owned(), gid.clone());
                gid
            },
            None =>  {
                self.attributes.get(GENE_ID_STR)
                    .ok_or(Error::Gff("required 'gene_id' attribute not found"))
                    .map(|gid| gid.clone())?
            },
        };

        let mut recs = Vec::with_capacity(self.num_records());

        let row = GffRow(
            self.seq_name().to_owned(), source, GENE_STR.to_owned(),
            self.interval().start, self.interval().end, score, strand.to_owned(),
            UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(row));

        for (_, mut transcript) in self.into_transcripts() {
            let mut trx_recs = transcript.to_gff_records(gene_id.as_str())?;
            recs.append(&mut trx_recs);
        }

        Ok(recs)
    }
}

impl Transcript {

    #[inline(always)]
    fn num_records(&self) -> usize {
        1 + self.exons().iter()
            .map(|ref exn| 1 + exn.features.len())
            .fold(0, |acc, x| acc + x)
    }

    // TODO: also handle transcript-level features
    fn to_gff_records(mut self, gene_id: &str) -> Result<Vec<gff::Record>, Error> {

        self.attributes.insert(GENE_ID_STR.to_owned(), gene_id.to_owned());
        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());
        let transcript_id = match self.id.take() {
            Some(tid) => {
                self.attributes.insert(TRANSCRIPT_ID_STR.to_owned(), tid.clone());
                tid
            },
            None =>  {
                self.attributes.get(TRANSCRIPT_ID_STR)
                    .ok_or(Error::Gff("required 'transcript_id' attribute not found"))
                    .map(|tid| tid.clone())?
            },
        };

        let mut recs = Vec::with_capacity(self.num_records());

        let trx_row =
            GffRow(self.seq_name().to_owned(), source, TRANSCRIPT_STR.to_owned(),
                   self.interval().start, self.interval().end, score,
                   strand.to_owned(), UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(trx_row));

        for exon in self.into_exons() {
            let mut exon_recs = exon.to_gff_records(gene_id, transcript_id.as_str())?;
            recs.append(&mut exon_recs);
        }

        Ok(recs)
    }
}

impl EFK {

    #[inline(always)]
    fn get_feature_frame(&self) -> (String, String) {
        let (feature, frame) = match self {
            &EFK::UTR => (UTR_STR, UNK_STR),
            &EFK::UTR5 => (UTR5_STR, UNK_STR),
            &EFK::UTR3 => (UTR3_STR, UNK_STR),
            &EFK::CDS { frame: ref f } => (CDS_STR, frame_to_str(f)),
            &EFK::StopCodon { frame: ref f } => (STOP_CODON_STR, frame_to_str(f)),
            &EFK::StartCodon { frame: ref f } => (START_CODON_STR, frame_to_str(f)),
            &EFK::Any(ref s) => (s.as_str(), UNK_STR),
        };
        (feature.to_owned(), frame.to_owned())
    }
}

impl Exon {

    fn to_gff_records(mut self, gene_id: &str, transcript_id: &str
    ) -> Result<Vec<gff::Record>, Error> {

        self.attributes.insert(GENE_ID_STR.to_owned(), gene_id.to_owned());
        self.attributes.insert(TRANSCRIPT_ID_STR.to_owned(), transcript_id.to_owned());
        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());

        let mut recs = Vec::with_capacity(1 + self.features.len());

        let exon_row =
            GffRow(self.seq_name().to_owned(), source.clone(), EXON_STR.to_owned(),
                   self.interval().start, self.interval().end, score, strand.to_owned(),
                   UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(exon_row));

        for fx in self.features.iter() {
            let (feature, frame) = fx.kind.get_feature_frame();
            let fx_row =
                GffRow(self.seq_name().to_owned(), source.clone(), feature,
                       self.interval().start, self.interval().end, UNK_STR.to_owned(),
                       strand.to_owned(), UNK_STR.to_owned(), self.attributes.clone());
            recs.push(gff::Record::from(fx_row));
        }

        Ok(recs)
    }
}

pub struct Writer<W: io::Write> {
    inner: gff::Writer<W>,
}

impl<W: io::Write> Writer<W> {

    pub fn from_writer(in_writer: W, gff_type: GffType) -> Writer<W> {
        Writer {
            inner: gff::Writer::new(in_writer, gff_type),
        }
    }

    pub fn write_gene(&mut self, mut gene: Gene) -> Result<(), Error> {
        for record in gene.to_gff_records()?.iter() {
            self.inner.write(&record)?;
        }
        Ok(())
    }

#[inline(always)]
fn adjust_coord(cur_coord: Coord<u64>, record: &gff::Record) -> Coord<u64> {
    (min(cur_coord.0, *record.start() - 1),
     max(cur_coord.1, *record.end()))
}

#[inline(always)]
fn extract_source_score(attributes: &mut HashMap<String, String>) -> (String, String) {
    let source = attributes.remove("source").unwrap_or(UNK_STR.to_owned());
    let score = attributes.remove("score").unwrap_or(UNK_STR.to_owned());
    (source, score)
}

#[inline(always)]
fn strand_to_string(strand: &Strand) -> String {
    let value = match strand {
        &Strand::Forward => "+",
        &Strand::Reverse => "-",
        &Strand::Unknown => UNK_STR,
    };
    value.to_owned()
}

#[inline(always)]
fn frame_to_str(frame: &Option<u8>) -> &str {
    match frame {
        &Some(0) => "0",
        &Some(1) => "1",
        &Some(2) => "2",
        _ => UNK_STR,
    }
}
<commit_msg>Fix missing bracket<commit_after>use std::collections::HashMap;
use std::cmp::{max, min};
use std::convert::AsRef;
use std::io;
use std::fs;
use std::path::Path;

use bio::io::gff::{self, GffType};
use itertools::{GroupBy, Group, Itertools};
use linked_hash_map::LinkedHashMap;

use {Coord, Exon, ExonFeatureKind as EFK, Gene, GBuilder, Strand, Transcript, Error};

// Various commonly-used feature column values
const GENE_STR: &'static str = "gene";
const TRANSCRIPT_STR: &'static str = "transcript";
const EXON_STR: &'static str = "exon";
const UTR_STR: &'static str = "UTR";
const UTR5_STR: &'static str = "UTR5";
const UTR3_STR: &'static str = "UTR3";
const CDS_STR: &'static str = "CDS";
const START_CODON_STR: &'static str = "start_codon";
const STOP_CODON_STR: &'static str = "stop_codon";

// Value for unknown columns.
const UNK_STR: &'static str = ".";

// Commonly-used attribute keys.
const GENE_ID_STR: &'static str = "gene_id";
const TRANSCRIPT_ID_STR: &'static str = "transcript_id";

// Initial coordinate for features.
const INIT_COORD: (u64, u64) = (::std::u64::MAX, ::std::u64::MIN);

pub struct Reader<R: io::Read> {
    inner: gff::Reader<R>,
}

impl<R: io::Read> Reader<R> {

    pub fn from_reader(in_reader: R, gff_type: GffType) -> Reader<R> {
        Reader {
            inner: gff::Reader::new(in_reader, gff_type),
        }
    }

    pub fn genes(&mut self) -> GffGenes<R> {
        GffGenes {
            inner: self.records().group_by(GffGenes::<R>::gene_groupf),
        }
    }

    fn records(&mut self) -> GffRecords<R> {
        GffRecords {
            inner: self.inner.records()
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<Path>>(path: P, gff_type: GffType) -> io::Result<Self> {
        fs::File::open(path).map(|file| Reader::from_reader(file, gff_type))
    }
}

struct GffRecords<'a, R: 'a> where R: io::Read {
    inner: gff::Records<'a, R>,
}

impl<'a, R> Iterator for GffRecords<'a, R> where R: io::Read {

    type Item = Result<gff::Record, Error>;

    fn next(&mut self) -> Option<Result<gff::Record, Error>> {
        self.inner.next()
            .map(|row| {
                row.or_else(|err| Err(Error::from(err)))
            })
    }
}

pub struct GffGenes<'a, R: 'a> where R: io::Read, {
    inner: GroupBy<GxGroupKey, GffRecords<'a, R>, GxGroupFunc>,
}

type GxGroupKey = Option<(String, String, Strand)>;

type GxGroupFunc = fn(&Result<gff::Record, Error>) -> GxGroupKey;

type GxGroupedRecs<'a, 'b, R> = Group<'b, GxGroupKey, GffRecords<'a, R>, GxGroupFunc>;

type RawTrxCoord = (Coord<u64>, Vec<Coord<u64>>, Option<Coord<u64>>);

impl<'a, R> GffGenes<'a, R> where R: io::Read {

    fn gene_groupf(result: &Result<gff::Record, Error>) -> GxGroupKey {
        result.as_ref().ok()
            .map(|res| {
                let gene_id = res.attributes().get(GENE_ID_STR)
                    .map(|gid| gid.as_str())
                    .unwrap_or("");
                let seq_name = String::from(res.seqname());
                let strand = res.strand().unwrap_or(Strand::Unknown);

                (String::from(gene_id), seq_name, strand)
            })
    }

    fn group_to_gene<'b>(group: (GxGroupKey, GxGroupedRecs<'a, 'b, R>)) -> Result<Gene, Error> {
        let (group_key, records) = group;
        match group_key {

            None => Err(records.filter_map(|x| x.err()).next().unwrap()),

            Some((gid, seq_name, strand)) => {

                let mut gene_coord = INIT_COORD;
                let mut trx_coords: LinkedHashMap<String, RawTrxCoord> = LinkedHashMap::new();

                for record in records {

                    let mut rec = record?;
                    rec.attributes_mut().remove(GENE_ID_STR);

                    let rtrx_entry = rec.attributes_mut()
                        .remove(TRANSCRIPT_ID_STR)
                        .ok_or(Error::Gff("required 'transcript_id' attribute not found"))
                        .map(|id| trx_coords.entry(id).or_insert((INIT_COORD, vec![], None)));

                    match rec.feature_type() {
                        GENE_STR => {
                            gene_coord = adjust_coord(gene_coord, &rec);
                        },
                        TRANSCRIPT_STR => {
                            let trx_entry = rtrx_entry?;
                            trx_entry.0 = adjust_coord(trx_entry.0, &rec);
                        },
                        EXON_STR => {
                            let trx_entry = rtrx_entry?;
                            (trx_entry.1).push((*rec.start() - 1, *rec.end()));
                        },
                        CDS_STR => {
                            let trx_entry = rtrx_entry?;
                            trx_entry.2 = (trx_entry.2).or(Some(INIT_COORD))
                                .map(|coord| adjust_coord(coord, &rec));
                        },
                        // TODO: How to best handle nested features? They may be out of order ...
                        _ => {},
                    }
                }

                GBuilder::new(seq_name, gene_coord.0, gene_coord.1)
                    .id(gid)
                    .strand(strand)
                    .transcript_coords(trx_coords)
                    .build()
            },
        }
    }
}

impl<'a, R> Iterator for GffGenes<'a, R> where R: io::Read {

    type Item = Result<Gene, Error>;

    fn next(&mut self) -> Option<Result<Gene, Error>> {
        self.inner.into_iter().map(Self::group_to_gene).next()
    }
}

struct GffRow(String, String, String, u64, u64, String, String, String, HashMap<String, String>);

impl From<GffRow> for gff::Record {
    fn from(row: GffRow) -> Self {
        let mut rec = gff::Record::default();
        *rec.seqname_mut() = row.0;
        *rec.source_mut() = row.1;
        *rec.feature_type_mut() = row.2;
        *rec.start_mut() = row.3 + 1;
        *rec.end_mut() = row.4;
        *rec.score_mut() = row.5;
        *rec.strand_mut() = row.6;
        *rec.frame_mut() = row.7;
        *rec.attributes_mut() = row.8;
        rec
    }
}

impl Gene {

    #[inline(always)]
    fn num_records(&self) -> usize {
        1 + self.transcripts().values()
            .map(|ref trx| trx.num_records())
            .fold(0, |acc, x| acc + x)
    }

    // TODO: also handle gene-level features
    fn to_gff_records(mut self) -> Result<Vec<gff::Record>, Error> {

        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());
        let gene_id = match self.id.take() {
            Some(gid) => {
                self.attributes.insert(GENE_ID_STR.to_owned(), gid.clone());
                gid
            },
            None =>  {
                self.attributes.get(GENE_ID_STR)
                    .ok_or(Error::Gff("required 'gene_id' attribute not found"))
                    .map(|gid| gid.clone())?
            },
        };

        let mut recs = Vec::with_capacity(self.num_records());

        let row = GffRow(
            self.seq_name().to_owned(), source, GENE_STR.to_owned(),
            self.interval().start, self.interval().end, score, strand.to_owned(),
            UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(row));

        for (_, mut transcript) in self.into_transcripts() {
            let mut trx_recs = transcript.to_gff_records(gene_id.as_str())?;
            recs.append(&mut trx_recs);
        }

        Ok(recs)
    }
}

impl Transcript {

    #[inline(always)]
    fn num_records(&self) -> usize {
        1 + self.exons().iter()
            .map(|ref exn| 1 + exn.features.len())
            .fold(0, |acc, x| acc + x)
    }

    // TODO: also handle transcript-level features
    fn to_gff_records(mut self, gene_id: &str) -> Result<Vec<gff::Record>, Error> {

        self.attributes.insert(GENE_ID_STR.to_owned(), gene_id.to_owned());
        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());
        let transcript_id = match self.id.take() {
            Some(tid) => {
                self.attributes.insert(TRANSCRIPT_ID_STR.to_owned(), tid.clone());
                tid
            },
            None =>  {
                self.attributes.get(TRANSCRIPT_ID_STR)
                    .ok_or(Error::Gff("required 'transcript_id' attribute not found"))
                    .map(|tid| tid.clone())?
            },
        };

        let mut recs = Vec::with_capacity(self.num_records());

        let trx_row =
            GffRow(self.seq_name().to_owned(), source, TRANSCRIPT_STR.to_owned(),
                   self.interval().start, self.interval().end, score,
                   strand.to_owned(), UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(trx_row));

        for exon in self.into_exons() {
            let mut exon_recs = exon.to_gff_records(gene_id, transcript_id.as_str())?;
            recs.append(&mut exon_recs);
        }

        Ok(recs)
    }
}

impl EFK {

    #[inline(always)]
    fn get_feature_frame(&self) -> (String, String) {
        let (feature, frame) = match self {
            &EFK::UTR => (UTR_STR, UNK_STR),
            &EFK::UTR5 => (UTR5_STR, UNK_STR),
            &EFK::UTR3 => (UTR3_STR, UNK_STR),
            &EFK::CDS { frame: ref f } => (CDS_STR, frame_to_str(f)),
            &EFK::StopCodon { frame: ref f } => (STOP_CODON_STR, frame_to_str(f)),
            &EFK::StartCodon { frame: ref f } => (START_CODON_STR, frame_to_str(f)),
            &EFK::Any(ref s) => (s.as_str(), UNK_STR),
        };
        (feature.to_owned(), frame.to_owned())
    }
}

impl Exon {

    fn to_gff_records(mut self, gene_id: &str, transcript_id: &str
    ) -> Result<Vec<gff::Record>, Error> {

        self.attributes.insert(GENE_ID_STR.to_owned(), gene_id.to_owned());
        self.attributes.insert(TRANSCRIPT_ID_STR.to_owned(), transcript_id.to_owned());
        let (source, score) = extract_source_score(&mut self.attributes);
        let strand = strand_to_string(self.strand());

        let mut recs = Vec::with_capacity(1 + self.features.len());

        let exon_row =
            GffRow(self.seq_name().to_owned(), source.clone(), EXON_STR.to_owned(),
                   self.interval().start, self.interval().end, score, strand.to_owned(),
                   UNK_STR.to_owned(), self.attributes.clone());
        recs.push(gff::Record::from(exon_row));

        for fx in self.features.iter() {
            let (feature, frame) = fx.kind.get_feature_frame();
            let fx_row =
                GffRow(self.seq_name().to_owned(), source.clone(), feature,
                       self.interval().start, self.interval().end, UNK_STR.to_owned(),
                       strand.to_owned(), UNK_STR.to_owned(), self.attributes.clone());
            recs.push(gff::Record::from(fx_row));
        }

        Ok(recs)
    }
}

pub struct Writer<W: io::Write> {
    inner: gff::Writer<W>,
}

impl<W: io::Write> Writer<W> {

    pub fn from_writer(in_writer: W, gff_type: GffType) -> Writer<W> {
        Writer {
            inner: gff::Writer::new(in_writer, gff_type),
        }
    }

    pub fn write_gene(&mut self, mut gene: Gene) -> Result<(), Error> {
        for record in gene.to_gff_records()?.iter() {
            self.inner.write(&record)?;
        }
        Ok(())
    }
}

#[inline(always)]
fn adjust_coord(cur_coord: Coord<u64>, record: &gff::Record) -> Coord<u64> {
    (min(cur_coord.0, *record.start() - 1),
     max(cur_coord.1, *record.end()))
}

#[inline(always)]
fn extract_source_score(attributes: &mut HashMap<String, String>) -> (String, String) {
    let source = attributes.remove("source").unwrap_or(UNK_STR.to_owned());
    let score = attributes.remove("score").unwrap_or(UNK_STR.to_owned());
    (source, score)
}

#[inline(always)]
fn strand_to_string(strand: &Strand) -> String {
    let value = match strand {
        &Strand::Forward => "+",
        &Strand::Reverse => "-",
        &Strand::Unknown => UNK_STR,
    };
    value.to_owned()
}

#[inline(always)]
fn frame_to_str(frame: &Option<u8>) -> &str {
    match frame {
        &Some(0) => "0",
        &Some(1) => "1",
        &Some(2) => "2",
        _ => UNK_STR,
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);
        let mut read_fds: fd_set = unsafe { mem::uninitialized() };
        let mut write_fds: fd_set = unsafe { mem::uninitialized() };

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            read_fds.fd_count = 0;
            write_fds.fd_count = 0;
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            // Wait for something to happen.
            let results = unsafe {
                if count == 0 {
                    thread::sleep(duration);
                    0
                } else {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &timeout
                    )
                }
            };

            // Process whatever happened.
            match results {
                SOCKET_ERROR => panic!("Socket error"),
                _ => self.ares_channel.lock().unwrap()
                    .process(&mut read_fds, &mut write_fds),
            }

            // Check whether we're asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<commit_msg>Don't tell c-ares anything if it doesn't care<commit_after>use std::mem;
use std::ptr;
use std::sync::{
    Arc,
    Mutex,
};
use std::thread;
use std::time::Duration;

use winapi::winsock2::{
    fd_set,
    SOCKET_ERROR,
    timeval,
    WSADATA,
};
use ws2_32::{
    select,
    WSACleanup,
    WSAStartup,
};

use c_ares;
use mio;

use error::ResolverError;
use eventloop::EventLoopHandle;

// The EventLoop will use select() to check on the status of file descriptors
// that c-ares cares about.
//
// It also waits for a message telling it to shut down.  We use a mio channel
// here only for consistency with the unix interface.
pub struct EventLoop {
    tx_msg_channel: mio::channel::Sender<Message>,
    rx_msg_channel: mio::channel::Receiver<Message>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: bool,
}

// Messages for the event loop.
#[derive(Debug)]
pub enum Message {
    // 'Shut down'.
    ShutDown,
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(options: c_ares::Options) -> Result<EventLoop, ResolverError> {
        // Initialize sockets.
        unsafe {
            let mut wsadata: WSADATA = mem::uninitialized();
            WSAStartup(0x101, &mut wsadata);
        }

        // Create the message channel.
        let (tx, rx) = mio::channel::channel();

        // Create the c-ares channel.
        let ares_channel = try!(c_ares::Channel::new(options));
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            tx_msg_channel: tx,
            rx_msg_channel: rx,
            ares_channel: locked_channel,
            quit: false,
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopHandle {
        let tx_clone = self.tx_msg_channel.clone();
        let join_handle = thread::spawn(|| self.event_loop_thread());
        EventLoopHandle::new(join_handle, tx_clone)
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 200000,
        };
        let duration = Duration::from_millis(200);
        let mut read_fds: fd_set = unsafe { mem::uninitialized() };
        let mut write_fds: fd_set = unsafe { mem::uninitialized() };

        // Loop round, asking c-ares what it cares about and doing as asked.
        loop {
            read_fds.fd_count = 0;
            write_fds.fd_count = 0;
            let count = self.ares_channel.lock().unwrap()
                .fds(&mut read_fds, &mut write_fds);

            if count == 0 {
                thread::sleep(duration);
            } else {
                let results = unsafe {
                    select(
                        0,
                        &mut read_fds,
                        &mut write_fds,
                        ptr::null_mut(),
                        &timeout
                    )
                };

                // Process whatever happened.
                match results {
                    SOCKET_ERROR => panic!("Socket error"),
                    _ => self.ares_channel.lock().unwrap()
                        .process(&mut read_fds, &mut write_fds),
                }
            }

            // Check whether we've been asked to quit.
            self.handle_messages();
            if self.quit { break }
        }
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        // The only possible message is an instruction to shut down.
        if let Ok(Message::ShutDown) = self.rx_msg_channel.try_recv() {
            self.quit = true;
        }
    }
}

impl Drop for EventLoop {
    fn drop(&mut self) {
        unsafe { WSACleanup(); }
    }
}
<|endoftext|>