<commit_before>// Copyright 2016 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>.
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;

use util::core::*;

use jsonrpc;
use jsonrpc::*;
use jsonrpc::service_util::MessageReader;
use jsonrpc::service_util::MessageWriter;
use jsonrpc::service_util::ServiceError;

use jsonrpc::output_agent::OutputAgent;

use jsonrpc::jsonrpc_objects::RequestParams;

use lsp_transport;
use ls_types::*;
use serde_json::Value;

/* -----------------  ----------------- */

pub struct LSPMessageReader<'a>(pub &'a mut io::BufRead);

impl<'a> MessageReader for LSPMessageReader<'a> {
	fn read_next(&mut self) -> GResult<String> {
		lsp_transport::parse_transport_message(&mut self.0)
	}
}

pub struct LSPMessageWriter<T: io::Write>(pub T);

impl<T: io::Write> MessageWriter for LSPMessageWriter<T> {
	fn write_message(&mut self, msg: &str) -> Result<(), GError> {
		lsp_transport::write_transport_message(msg, &mut self.0)
	}
}

/* -----------------  ----------------- */

pub struct LSPEndpoint {

}

impl LSPEndpoint {

	pub fn new_with_output_stream<OUT, OUT_P>(output_stream_provider: OUT_P)
		-> EndpointHandle
	where
		OUT: io::Write + 'static,
		OUT_P : FnOnce() -> OUT + Send + 'static
	{
		Self::new(|| {
			LSPMessageWriter(output_stream_provider())
		})
	}

	pub fn new<OUT, OUT_P>(msg_writer_provider: OUT_P)
		-> EndpointHandle
	where
		OUT : MessageWriter + 'static,
		OUT_P : FnOnce() -> OUT + Send + 'static
	{
		let output_agent = OutputAgent::start_with_provider(msg_writer_provider);
		let endpoint = Endpoint::start_with_output_agent(output_agent, new(MapRequestHandler::new()));
		newArcMutex(endpoint)
	}

	pub fn run_server_from_input<LS>(ls: LS, input: &mut io::BufRead, endpoint: EndpointHandle)
	where
		LS: LanguageServer + 'static,
	{
	    Self::run_server(ls, &mut LSPMessageReader(input), endpoint)
	}

	pub fn run_server<LS, MSG_READER: ?Sized>(ls: LS, msg_reader: &mut MSG_READER, endpoint: EndpointHandle)
	where
		LS: LanguageServer + 'static,
		MSG_READER : MessageReader,
	{
       	info!("Starting LSP server");

		let req_handler : Box<RequestHandler> = Box::new(LSRequestHandler(ls));
		endpoint.lock().unwrap().request_handler = req_handler;

		let result = jsonrpc::run_message_read_loop(endpoint, msg_reader);

		if let Err(error) = result {
			error!("Error handling the incoming stream: {}", error);
		}
	}

}

pub type LSResult<RET, ERR_DATA> = Result<RET, ServiceError<ERR_DATA>>;

pub trait LanguageServer {

	fn initialize(&self, params: InitializeParams) -> LSResult<InitializeResult, InitializeError>;
	fn shutdown(&self, params: ()) -> LSResult<(), ()>;
	fn exit(&self, params: ());
	fn workspaceChangeConfiguration(&self, params: DidChangeConfigurationParams);
	fn didOpenTextDocument(&self, params: DidOpenTextDocumentParams);
	fn didChangeTextDocument(&self, params: DidChangeTextDocumentParams);
	fn didCloseTextDocument(&self, params: DidCloseTextDocumentParams);
	fn didSaveTextDocument(&self, params: DidSaveTextDocumentParams);
	fn didChangeWatchedFiles(&self, params: DidChangeWatchedFilesParams);

	fn completion(&self, params: TextDocumentPositionParams) -> LSResult<CompletionList, ()>;
	fn resolveCompletionItem(&self, params: CompletionItem) -> LSResult<CompletionItem, ()>;
	fn hover(&self, params: TextDocumentPositionParams) -> LSResult<Hover, ()>;
	fn signatureHelp(&self, params: TextDocumentPositionParams) -> LSResult<SignatureHelp, ()>;
	fn gotoDefinition(&self, params: TextDocumentPositionParams) -> LSResult<Vec<Location>, ()>;
	fn references(&self, params: ReferenceParams) -> LSResult<Vec<Location>, ()>;
	fn documentHighlight(&self, params: TextDocumentPositionParams) -> LSResult<DocumentHighlight, ()>;
	fn documentSymbols(&self, params: DocumentSymbolParams) -> LSResult<Vec<SymbolInformation>, ()>;
	fn workspaceSymbols(&self, params: WorkspaceSymbolParams) -> LSResult<Vec<SymbolInformation>, ()>;
	fn codeAction(&self, params: CodeActionParams) -> LSResult<Vec<Command>, ()>;
	fn codeLens(&self, params: CodeLensParams) -> LSResult<Vec<CodeLens>, ()>;
	fn codeLensResolve(&self, params: CodeLens) -> LSResult<CodeLens, ()>;
	fn formatting(&self, params: DocumentFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn rangeFormatting(&self, params: DocumentRangeFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn onTypeFormatting(&self, params: DocumentOnTypeFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn rename(&self, params: RenameParams) -> LSResult<WorkspaceEdit, ()>;

}

pub trait LanguageClientEndpoint {

	fn showMessage(&self, params: ShowMessageParams) -> GResult<()>;
	fn showMessageRequest(&self, params: ShowMessageRequestParams) -> GResult<LSResult<MessageActionItem, ()>>;
	fn logMessage(&self, params: LogMessageParams) -> GResult<()>;
	fn telemetryEvent(&self, params: Value) -> GResult<()>;

	fn publishDiagnostics(&self, params: PublishDiagnosticsParams) -> GResult<()>;

}

pub struct LSRequestHandler<LS : LanguageServer>(LS);

impl<LS : LanguageServer> RequestHandler for LSRequestHandler<LS> {

	fn handle_request(&mut self, method_name: &str, params: RequestParams,
		completable: ResponseCompletable)
	{
		match method_name {
			REQUEST__Initialize => { completable.sync_handle_request(params,
				|params| self.0.initialize(params))
			}
			REQUEST__Shutdown => { completable.sync_handle_request(params,
				|params| self.0.shutdown(params))
			}
			NOTIFICATION__Exit => { completable.sync_handle_notification(params,
				|params| self.0.exit(params))
			}
			NOTIFICATION__WorkspaceChangeConfiguration => { completable.sync_handle_notification(params,
				|params| self.0.workspaceChangeConfiguration(params))
			}
			NOTIFICATION__DidOpenTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.didOpenTextDocument(params))
			}
			NOTIFICATION__DidChangeTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.didChangeTextDocument(params))
			}
			NOTIFICATION__DidCloseTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.didCloseTextDocument(params))
			}
			NOTIFICATION__DidSaveTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.didSaveTextDocument(params))
			}
			NOTIFICATION__DidChangeWatchedFiles => { completable.sync_handle_notification(params,
				|params| self.0.didChangeWatchedFiles(params))
			}
			REQUEST__Completion => { completable.sync_handle_request(params,
				|params| self.0.completion(params))
			}
			REQUEST__ResolveCompletionItem => { completable.sync_handle_request(params,
				|params| self.0.resolveCompletionItem(params))
			}
			REQUEST__Hover => { completable.sync_handle_request(params,
				|params| self.0.hover(params))
			}
			REQUEST__SignatureHelp => { completable.sync_handle_request(params,
				|params| self.0.signatureHelp(params))
			}
			REQUEST__GotoDefinition => { completable.sync_handle_request(params,
				|params| self.0.gotoDefinition(params))
			}
			REQUEST__References => { completable.sync_handle_request(params,
				|params| self.0.references(params))
			}
			REQUEST__DocumentHighlight => { completable.sync_handle_request(params,
				|params| self.0.documentHighlight(params))
			}
			REQUEST__DocumentSymbols => { completable.sync_handle_request(params,
				|params| self.0.documentSymbols(params))
			}
			REQUEST__WorkspaceSymbols => { completable.sync_handle_request(params,
				|params| self.0.workspaceSymbols(params))
			}
			REQUEST__CodeAction => { completable.sync_handle_request(params,
				|params| self.0.codeAction(params))
			}
			REQUEST__CodeLens => { completable.sync_handle_request(params,
				|params| self.0.codeLens(params))
			}
			REQUEST__CodeLensResolve => { completable.sync_handle_request(params,
				|params| self.0.codeLensResolve(params))
			}
			REQUEST__Formatting => { completable.sync_handle_request(params,
				|params| self.0.formatting(params))
			}
			REQUEST__RangeFormatting => { completable.sync_handle_request(params,
				|params| self.0.rangeFormatting(params))
			}
			REQUEST__OnTypeFormatting => { completable.sync_handle_request(params,
				|params| self.0.onTypeFormatting(params))
			}
			REQUEST__Rename => { completable.sync_handle_request(params,
				|params| self.0.rename(params))
			}
			_ => {
				completable.complete_with_error(jsonrpc_objects::error_JSON_RPC_MethodNotFound());
			}
		};

	}

}

impl LanguageClientEndpoint for EndpointHandle {

    fn showMessage(&self, params: ShowMessageParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__ShowMessage, params));
    	Ok(())
    }

    fn showMessageRequest(&self, _params: ShowMessageRequestParams) -> GResult<LSResult<MessageActionItem, ()>> {
    	let endpoint = self.lock().unwrap();
//    	endpoint.send_request(NOTIFICATION__ShowMessageRequest, params);
    	panic!("not implemented")
    }

    fn logMessage(&self, params: LogMessageParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__LogMessage, params));
    	Ok(())
    }

    fn telemetryEvent(&self, params: Value) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__TelemetryEvent, params));
    	Ok(())
    }

    fn publishDiagnostics(&self, params: PublishDiagnosticsParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__PublishDiagnostics, params));
    	Ok(())
    }

}

/* ----------------- Tests ----------------- */

#[cfg(test)]
mod tests {

	use super::*;
    use jsonrpc::service_util::ServiceError;
    use ls_types::*;
    use std::io::BufReader;

    pub struct TestsLanguageServer;

    impl TestsLanguageServer {

    	pub fn error_not_available<DATA>(data : DATA) -> ServiceError<DATA> {
    		let msg = "Functionality not implemented.".to_string();
    		ServiceError::<DATA> { code : 1, message : msg, data : data }
    	}

    }

    impl LanguageServer for TestsLanguageServer {

    	fn initialize(&self, _: InitializeParams) -> LSResult<InitializeResult, InitializeError> {
    		let capabilities = ServerCapabilities::default();
    		Ok(InitializeResult { capabilities : capabilities })
    	}
    	fn shutdown(&self, _: ()) -> LSResult<(), ()> {
    		Ok(())
    	}
    	fn exit(&self, _: ()) {
    	}

    	fn workspaceChangeConfiguration(&self, _: DidChangeConfigurationParams) {}
    	fn didOpenTextDocument(&self, _: DidOpenTextDocumentParams) {}
    	fn didChangeTextDocument(&self, _: DidChangeTextDocumentParams) {}
    	fn didCloseTextDocument(&self, _: DidCloseTextDocumentParams) {}
    	fn didSaveTextDocument(&self, _: DidSaveTextDocumentParams) {}
    	fn didChangeWatchedFiles(&self, _: DidChangeWatchedFilesParams) {}

    	fn completion(&self, _: TextDocumentPositionParams) -> LSResult<CompletionList, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn resolveCompletionItem(&self, _: CompletionItem) -> LSResult<CompletionItem, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn hover(&self, _: TextDocumentPositionParams) -> LSResult<Hover, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn signatureHelp(&self, _: TextDocumentPositionParams) -> LSResult<SignatureHelp, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn gotoDefinition(&self, _: TextDocumentPositionParams) -> LSResult<Vec<Location>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn references(&self, _: ReferenceParams) -> LSResult<Vec<Location>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn documentHighlight(&self, _: TextDocumentPositionParams) -> LSResult<DocumentHighlight, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn documentSymbols(&self, _: DocumentSymbolParams) -> LSResult<Vec<SymbolInformation>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn workspaceSymbols(&self, _: WorkspaceSymbolParams) -> LSResult<Vec<SymbolInformation>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn codeAction(&self, _: CodeActionParams) -> LSResult<Vec<Command>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn codeLens(&self, _: CodeLensParams) -> LSResult<Vec<CodeLens>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn codeLensResolve(&self, _: CodeLens) -> LSResult<CodeLens, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn formatting(&self, _: DocumentFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn rangeFormatting(&self, _: DocumentRangeFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn onTypeFormatting(&self, _: DocumentOnTypeFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn rename(&self, _: RenameParams) -> LSResult<WorkspaceEdit, ()> {
    		Err(Self::error_not_available(()))
    	}
    }

    #[test]
    pub fn test_run_lsp_server() {
        let out_stream_provider = || { Vec::<u8>::new() };

        let endpoint = LSPEndpoint::new_with_output_stream(out_stream_provider);

       	let ls = TestsLanguageServer{ };

    	let mut input = BufReader::new("".as_bytes());
    	LSPEndpoint::run_server_from_input(ls, &mut input, endpoint);
    }

}<commit_msg>trait methods acording to standard Rust style.<commit_after>// Copyright 2016 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>.
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;

use util::core::*;

use jsonrpc;
use jsonrpc::*;
use jsonrpc::service_util::MessageReader;
use jsonrpc::service_util::MessageWriter;
use jsonrpc::service_util::ServiceError;

use jsonrpc::output_agent::OutputAgent;

use jsonrpc::jsonrpc_objects::RequestParams;

use lsp_transport;
use ls_types::*;
use serde_json::Value;

/* -----------------  ----------------- */

pub struct LSPMessageReader<'a>(pub &'a mut io::BufRead);

impl<'a> MessageReader for LSPMessageReader<'a> {
	fn read_next(&mut self) -> GResult<String> {
		lsp_transport::parse_transport_message(&mut self.0)
	}
}

pub struct LSPMessageWriter<T: io::Write>(pub T);

impl<T: io::Write> MessageWriter for LSPMessageWriter<T> {
	fn write_message(&mut self, msg: &str) -> Result<(), GError> {
		lsp_transport::write_transport_message(msg, &mut self.0)
	}
}

/* -----------------  ----------------- */

pub struct LSPEndpoint {

}

impl LSPEndpoint {

	pub fn new_with_output_stream<OUT, OUT_P>(output_stream_provider: OUT_P)
		-> EndpointHandle
	where
		OUT: io::Write + 'static,
		OUT_P : FnOnce() -> OUT + Send + 'static
	{
		Self::new(|| {
			LSPMessageWriter(output_stream_provider())
		})
	}

	pub fn new<OUT, OUT_P>(msg_writer_provider: OUT_P)
		-> EndpointHandle
	where
		OUT : MessageWriter + 'static,
		OUT_P : FnOnce() -> OUT + Send + 'static
	{
		let output_agent = OutputAgent::start_with_provider(msg_writer_provider);
		let endpoint = Endpoint::start_with_output_agent(output_agent, new(MapRequestHandler::new()));
		newArcMutex(endpoint)
	}

	pub fn run_server_from_input<LS>(ls: LS, input: &mut io::BufRead, endpoint: EndpointHandle)
	where
		LS: LanguageServer + 'static,
	{
	    Self::run_server(ls, &mut LSPMessageReader(input), endpoint)
	}

	pub fn run_server<LS, MSG_READER: ?Sized>(ls: LS, msg_reader: &mut MSG_READER, endpoint: EndpointHandle)
	where
		LS: LanguageServer + 'static,
		MSG_READER : MessageReader,
	{
       	info!("Starting LSP server");

		let req_handler : Box<RequestHandler> = Box::new(LSRequestHandler(ls));
		endpoint.lock().unwrap().request_handler = req_handler;

		let result = jsonrpc::run_message_read_loop(endpoint, msg_reader);

		if let Err(error) = result {
			error!("Error handling the incoming stream: {}", error);
		}
	}

}

pub type LSResult<RET, ERR_DATA> = Result<RET, ServiceError<ERR_DATA>>;

pub trait LanguageServer {

	fn initialize(&self, params: InitializeParams) -> LSResult<InitializeResult, InitializeError>;
	fn shutdown(&self, params: ()) -> LSResult<(), ()>;
	fn exit(&self, params: ());
	fn workspace_change_configuration(&self, params: DidChangeConfigurationParams);
	fn did_open_text_document(&self, params: DidOpenTextDocumentParams);
	fn did_change_text_document(&self, params: DidChangeTextDocumentParams);
	fn did_close_text_document(&self, params: DidCloseTextDocumentParams);
	fn did_save_text_document(&self, params: DidSaveTextDocumentParams);
	fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams);

	fn completion(&self, params: TextDocumentPositionParams) -> LSResult<CompletionList, ()>;
	fn resolve_completion_item(&self, params: CompletionItem) -> LSResult<CompletionItem, ()>;
	fn hover(&self, params: TextDocumentPositionParams) -> LSResult<Hover, ()>;
	fn signature_help(&self, params: TextDocumentPositionParams) -> LSResult<SignatureHelp, ()>;
	fn goto_definition(&self, params: TextDocumentPositionParams) -> LSResult<Vec<Location>, ()>;
	fn references(&self, params: ReferenceParams) -> LSResult<Vec<Location>, ()>;
	fn document_highlight(&self, params: TextDocumentPositionParams) -> LSResult<DocumentHighlight, ()>;
	fn document_symbols(&self, params: DocumentSymbolParams) -> LSResult<Vec<SymbolInformation>, ()>;
	fn workspace_symbols(&self, params: WorkspaceSymbolParams) -> LSResult<Vec<SymbolInformation>, ()>;
	fn code_action(&self, params: CodeActionParams) -> LSResult<Vec<Command>, ()>;
	fn code_lens(&self, params: CodeLensParams) -> LSResult<Vec<CodeLens>, ()>;
	fn code_lens_resolve(&self, params: CodeLens) -> LSResult<CodeLens, ()>;
	fn formatting(&self, params: DocumentFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn range_formatting(&self, params: DocumentRangeFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn on_type_formatting(&self, params: DocumentOnTypeFormattingParams) -> LSResult<Vec<TextEdit>, ()>;
	fn rename(&self, params: RenameParams) -> LSResult<WorkspaceEdit, ()>;

}

pub trait LanguageClientEndpoint {

	fn show_message(&self, params: ShowMessageParams) -> GResult<()>;
	fn show_message_request(&self, params: ShowMessageRequestParams) -> GResult<LSResult<MessageActionItem, ()>>;
	fn log_message(&self, params: LogMessageParams) -> GResult<()>;
	fn telemetry_event(&self, params: Value) -> GResult<()>;

	fn publish_diagnostics(&self, params: PublishDiagnosticsParams) -> GResult<()>;

}

pub struct LSRequestHandler<LS : LanguageServer>(LS);

impl<LS : LanguageServer> RequestHandler for LSRequestHandler<LS> {

	fn handle_request(&mut self, method_name: &str, params: RequestParams,
		completable: ResponseCompletable)
	{
		match method_name {
			REQUEST__Initialize => { completable.sync_handle_request(params,
				|params| self.0.initialize(params))
			}
			REQUEST__Shutdown => { completable.sync_handle_request(params,
				|params| self.0.shutdown(params))
			}
			NOTIFICATION__Exit => { completable.sync_handle_notification(params,
				|params| self.0.exit(params))
			}
			NOTIFICATION__WorkspaceChangeConfiguration => { completable.sync_handle_notification(params,
				|params| self.0.workspace_change_configuration(params))
			}
			NOTIFICATION__DidOpenTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.did_open_text_document(params))
			}
			NOTIFICATION__DidChangeTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.did_change_text_document(params))
			}
			NOTIFICATION__DidCloseTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.did_close_text_document(params))
			}
			NOTIFICATION__DidSaveTextDocument => { completable.sync_handle_notification(params,
				|params| self.0.did_save_text_document(params))
			}
			NOTIFICATION__DidChangeWatchedFiles => { completable.sync_handle_notification(params,
				|params| self.0.did_change_watched_files(params))
			}
			REQUEST__Completion => { completable.sync_handle_request(params,
				|params| self.0.completion(params))
			}
			REQUEST__ResolveCompletionItem => { completable.sync_handle_request(params,
				|params| self.0.resolve_completion_item(params))
			}
			REQUEST__Hover => { completable.sync_handle_request(params,
				|params| self.0.hover(params))
			}
			REQUEST__SignatureHelp => { completable.sync_handle_request(params,
				|params| self.0.signature_help(params))
			}
			REQUEST__GotoDefinition => { completable.sync_handle_request(params,
				|params| self.0.goto_definition(params))
			}
			REQUEST__References => { completable.sync_handle_request(params,
				|params| self.0.references(params))
			}
			REQUEST__DocumentHighlight => { completable.sync_handle_request(params,
				|params| self.0.document_highlight(params))
			}
			REQUEST__DocumentSymbols => { completable.sync_handle_request(params,
				|params| self.0.document_symbols(params))
			}
			REQUEST__WorkspaceSymbols => { completable.sync_handle_request(params,
				|params| self.0.workspace_symbols(params))
			}
			REQUEST__CodeAction => { completable.sync_handle_request(params,
				|params| self.0.code_action(params))
			}
			REQUEST__CodeLens => { completable.sync_handle_request(params,
				|params| self.0.code_lens(params))
			}
			REQUEST__CodeLensResolve => { completable.sync_handle_request(params,
				|params| self.0.code_lens_resolve(params))
			}
			REQUEST__Formatting => { completable.sync_handle_request(params,
				|params| self.0.formatting(params))
			}
			REQUEST__RangeFormatting => { completable.sync_handle_request(params,
				|params| self.0.range_formatting(params))
			}
			REQUEST__OnTypeFormatting => { completable.sync_handle_request(params,
				|params| self.0.on_type_formatting(params))
			}
			REQUEST__Rename => { completable.sync_handle_request(params,
				|params| self.0.rename(params))
			}
			_ => {
				completable.complete_with_error(jsonrpc_objects::error_JSON_RPC_MethodNotFound());
			}
		};

	}

}

impl LanguageClientEndpoint for EndpointHandle {

    fn show_message(&self, params: ShowMessageParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__ShowMessage, params));
    	Ok(())
    }

    fn show_message_request(&self, _params: ShowMessageRequestParams) -> GResult<LSResult<MessageActionItem, ()>> {
    	let endpoint = self.lock().unwrap();
//    	endpoint.send_request(NOTIFICATION__ShowMessageRequest, params);
    	panic!("not implemented")
    }

    fn log_message(&self, params: LogMessageParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__LogMessage, params));
    	Ok(())
    }

    fn telemetry_event(&self, params: Value) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__TelemetryEvent, params));
    	Ok(())
    }

    fn publish_diagnostics(&self, params: PublishDiagnosticsParams) -> GResult<()> {
    	let mut endpoint = self.lock().unwrap();
    	try!(endpoint.send_notification(NOTIFICATION__PublishDiagnostics, params));
    	Ok(())
    }

}

/* ----------------- Tests ----------------- */

#[cfg(test)]
mod tests {

	use super::*;
    use jsonrpc::service_util::ServiceError;
    use ls_types::*;
    use std::io::BufReader;

    pub struct TestsLanguageServer;

    impl TestsLanguageServer {

    	pub fn error_not_available<DATA>(data : DATA) -> ServiceError<DATA> {
    		let msg = "Functionality not implemented.".to_string();
    		ServiceError::<DATA> { code : 1, message : msg, data : data }
    	}

    }

    impl LanguageServer for TestsLanguageServer {

    	fn initialize(&self, _: InitializeParams) -> LSResult<InitializeResult, InitializeError> {
    		let capabilities = ServerCapabilities::default();
    		Ok(InitializeResult { capabilities : capabilities })
    	}
    	fn shutdown(&self, _: ()) -> LSResult<(), ()> {
    		Ok(())
    	}
    	fn exit(&self, _: ()) {
    	}

    	fn workspace_change_configuration(&self, _: DidChangeConfigurationParams) {}
    	fn did_open_text_document(&self, _: DidOpenTextDocumentParams) {}
    	fn did_change_text_document(&self, _: DidChangeTextDocumentParams) {}
    	fn did_close_text_document(&self, _: DidCloseTextDocumentParams) {}
    	fn did_save_text_document(&self, _: DidSaveTextDocumentParams) {}
    	fn did_change_watched_files(&self, _: DidChangeWatchedFilesParams) {}

    	fn completion(&self, _: TextDocumentPositionParams) -> LSResult<CompletionList, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn resolve_completion_item(&self, _: CompletionItem) -> LSResult<CompletionItem, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn hover(&self, _: TextDocumentPositionParams) -> LSResult<Hover, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn signature_help(&self, _: TextDocumentPositionParams) -> LSResult<SignatureHelp, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn goto_definition(&self, _: TextDocumentPositionParams) -> LSResult<Vec<Location>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn references(&self, _: ReferenceParams) -> LSResult<Vec<Location>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn document_highlight(&self, _: TextDocumentPositionParams) -> LSResult<DocumentHighlight, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn document_symbols(&self, _: DocumentSymbolParams) -> LSResult<Vec<SymbolInformation>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn workspace_symbols(&self, _: WorkspaceSymbolParams) -> LSResult<Vec<SymbolInformation>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn code_action(&self, _: CodeActionParams) -> LSResult<Vec<Command>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn code_lens(&self, _: CodeLensParams) -> LSResult<Vec<CodeLens>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn code_lens_resolve(&self, _: CodeLens) -> LSResult<CodeLens, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn formatting(&self, _: DocumentFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn range_formatting(&self, _: DocumentRangeFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn on_type_formatting(&self, _: DocumentOnTypeFormattingParams) -> LSResult<Vec<TextEdit>, ()> {
    		Err(Self::error_not_available(()))
    	}
    	fn rename(&self, _: RenameParams) -> LSResult<WorkspaceEdit, ()> {
    		Err(Self::error_not_available(()))
    	}
    }

    #[test]
    pub fn test_run_lsp_server() {
        let out_stream_provider = || { Vec::<u8>::new() };

        let endpoint = LSPEndpoint::new_with_output_stream(out_stream_provider);

       	let ls = TestsLanguageServer{ };

    	let mut input = BufReader::new("".as_bytes());
    	LSPEndpoint::run_server_from_input(ls, &mut input, endpoint);
    }

}<|endoftext|>


<commit_before>macro_rules! expr { ($e:expr) => { $e } }

#[macro_use] pub mod newtype_impl;
<commit_msg>[kernel] allow macros to have missing docs<commit_after>#![allow(missing_docs)]

macro_rules! expr { ($e:expr) => { $e } }

#[macro_use] pub mod newtype_impl;
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use gj::{Promise, PromiseFulfiller};
use std::cell::{RefCell};
use std::rc::Rc;
use handle_table::{HandleTable, Handle};

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

impl Observer {
    pub fn when_read_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        promise
    }

    pub fn when_write_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        promise
    }
}

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                let token = status.token();
                let overlapped = status.overlapped();
                let bytes_transferred = status.bytes_transferred();
                let handle = Handle { val: token };
                if self.observers[handle].read_overlapped == overlapped {
                    match self.observers[handle].read_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }
                if self.observers[handle].write_overlapped == overlapped {
                    match self.observers[handle].write_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }

            }
        }
        Ok(())
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(self.reactor.clone(), stream))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        Ok(SocketListenerInner::new(self.reactor.clone(), listener, self.addr))
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: ::miow::Overlapped,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> SocketListenerInner
    {
        SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: ::miow::Overlapped::zero(),
            queue: None,
        }
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            reactor: ref reactor,
            listener: ref mut listener,
            read_overlapped: ref mut read_overlapped,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(reactor.clone(), stream))
        } else {
            let handle = pry!(reactor.borrow_mut().add_socket(listener,
                                                              read_overlapped,
                                                              ::std::ptr::null_mut()));

            let reactor2 = reactor.clone();
            reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
                println!("accepted!");
                Ok(SocketStreamInner::new(reactor2, stream))
            })
        }
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream) -> SocketStreamInner {
        SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_queue: None,
            write_queue: None,
        }
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.read_overlapped(buf.as_mut(), &mut overlapped))
        };
        unimplemented!()
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.write_overlapped(buf.as_ref(), &mut overlapped))
        };

        unimplemented!()
    }
}
<commit_msg>basic buggy read/write<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use gj::{Promise, PromiseFulfiller};
use std::cell::{RefCell};
use std::rc::Rc;
use handle_table::{HandleTable, Handle};

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

impl Observer {
    pub fn when_read_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        promise
    }

    pub fn when_write_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        promise
    }
}

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                let token = status.token();
                let overlapped = status.overlapped();
                let bytes_transferred = status.bytes_transferred();
                let handle = Handle { val: token };
                if self.observers[handle].read_overlapped == overlapped {
                    match self.observers[handle].read_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }
                if self.observers[handle].write_overlapped == overlapped {
                    match self.observers[handle].write_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }

            }
        }
        Ok(())
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(pry!(SocketStreamInner::new(self.reactor.clone(), stream)))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        Ok(SocketListenerInner::new(self.reactor.clone(), listener, self.addr))
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: ::miow::Overlapped,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> SocketListenerInner
    {
        SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: ::miow::Overlapped::zero(),
            queue: None,
        }
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            reactor: ref reactor,
            listener: ref mut listener,
            read_overlapped: ref mut read_overlapped,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, _ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        let handle = pry!(reactor.borrow_mut().add_socket(listener,
                                                          read_overlapped,
                                                          ::std::ptr::null_mut()));

        let reactor2 = reactor.clone();
        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
            println!("accepted!");
            SocketStreamInner::new(reactor2, stream)
        });

        result
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    read_overlapped: Box<::miow::Overlapped>,
    write_overlapped: Box<::miow::Overlapped>,
    handle: Handle,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream)
           -> Result<SocketStreamInner, ::std::io::Error>
    {
        let mut read_overlapped = Box::new(::miow::Overlapped::zero());
        let mut write_overlapped = Box::new(::miow::Overlapped::zero());
        let handle = try!(
            reactor.borrow_mut().add_socket(&stream, &mut *read_overlapped,
                                            &mut *write_overlapped));
        Ok(SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            handle: handle,
            read_queue: None,
            write_queue: None,
        })
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            reactor: ref reactor,
            stream: ref mut stream,
            read_overlapped: ref mut read_overlapped,
            handle: handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.read_overlapped(buf.as_mut(), read_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |n| {
            println!("read transferred this many bytes: {}", n);
            Ok((buf, n as usize))
        });

        result
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            reactor: ref reactor,
            stream: ref mut stream,
            write_overlapped: ref mut write_overlapped,
            handle: handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.write_overlapped(buf.as_ref(), write_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_write_done().map(move |n| {
            println!("write transferred this many bytes: {}", n);
            Ok(buf)
        });

        result
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
#[macro_use]
extern crate clap;
extern crate hostname;
#[macro_use]
extern crate log;
extern crate log4rs;
#[macro_use]
extern crate target_info;
extern crate xdg;

mod build_info;
mod command_line_arguments;
mod context;
mod datetime;
mod execution_timer;
mod program_info;
mod system_info;

use xdg::BaseDirectories;

use context::Context;
use execution_timer::ExecutionTimer;

fn main() {
    std::env::set_var("IN_QORK", "1");
    let context = Context::new();
    configure_logging(context.xdg());
    let _timer = ExecutionTimer::with_start_message("main.main");
    build_info::log_build_info();
    context.log_created_message();
    load_user_configuration(&context);
}

fn configure_logging(xdg: &BaseDirectories) {
    let path = xdg.place_config_file("logging.toml");

    match path {
        Ok(p) => {
            if p.exists() {
                log4rs::init_file(&p, Default::default()).unwrap();
                info!("Logging initialized using file at {:?}", &p);
            }
            else {
            }
        },
        Err(_) => {
            // Do nothing, not sure there is anything we can do.
        }
    }
}

fn load_user_configuration(context: &Context) {
    let _timer = ExecutionTimer::with_start_message("main.load_user_configuration");

    if !context.program_info().parsed_args().load_config() {
        info!("Loading of user configuration is disabled.");
        return
    }

    let dir = context.xdg().get_config_home();
    if !dir.exists() {
        warn!("The config_directory does not exist, no config will be loaded, config_directory={:?}", dir);
        return
    }

    if !dir.is_dir() {
        warn!("The config_directory is a file, not a directory, no config will be loaded, config_directory={:?}", dir);
        return
    }

    info!("Loading user configuration from {:?}", dir);
}
<commit_msg>Prepare for reading config.toml.<commit_after>extern crate chrono;
#[macro_use]
extern crate clap;
extern crate hostname;
#[macro_use]
extern crate log;
extern crate log4rs;
#[macro_use]
extern crate target_info;
extern crate xdg;

mod build_info;
mod command_line_arguments;
mod context;
mod datetime;
mod execution_timer;
mod program_info;
mod system_info;

use xdg::BaseDirectories;

use context::Context;
use execution_timer::ExecutionTimer;

fn main() {
    std::env::set_var("IN_QORK", "1");
    let context = Context::new();
    configure_logging(context.xdg());
    let _timer = ExecutionTimer::with_start_message("main.main");
    build_info::log_build_info();
    context.log_created_message();
    load_user_configuration(&context);
}

fn configure_logging(xdg: &BaseDirectories) {
    let path = xdg.place_config_file("logging.toml");

    match path {
        Ok(p) => {
            if p.exists() {
                log4rs::init_file(&p, Default::default()).unwrap();
                info!("Logging initialized using file at {:?}", &p);
            }
        },
        Err(_) => {
            // Do nothing, not sure there is anything we can do.
        }
    }
}

fn load_user_configuration(context: &Context) {
    let _timer = ExecutionTimer::with_start_message("main.load_user_configuration");

    if !context.program_info().parsed_args().load_config() {
        info!("Loading of user configuration is disabled.");
        return
    }

    let dir = context.xdg().get_config_home();
    if !dir.exists() {
        warn!("The config_directory does not exist, no config will be loaded, config_directory={:?}", dir);
        return
    }

    if !dir.is_dir() {
        warn!("The config_directory is a file, not a directory, no config will be loaded, config_directory={:?}", dir);
        return
    }

    info!("Loading user configuration from {:?}", dir);
    let path = context.xdg().place_config_file("config.toml");
    match path {
        Ok(p) => {
            if p.exists() {

            } else {
                info!("The config file {:?} does not exist", p);
            }
        }
        Err(e) => {
            warn!("Error while asking for config.toml: {}", e);
            return;
        }
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/LZW_compression

use std::hashmap::HashMap;
use std::vec;
use std::str;

fn compress(original_str: &str) -> ~[int] {
   let original = original_str.as_bytes();
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(~[i as u8], i);
   }

   let mut result = ~[];
   let mut w:~[u8] = ~[];
   for &c in original.iter() {
      let mut wc = w.clone();
      wc.push(c);

      match dictionary.find(&wc) {
         Some(_) => w = wc,
         None => {
            result.push(*dictionary.get(&w));
            dictionary.insert(wc, dict_size);
            dict_size += 1;
            w = ~[c];
         }
      }
   }

   if w.len() > 0 {
      result.push(*dictionary.get(&w));
   }

   result
}

fn decompress(compressed: &[int]) -> ~str {
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(i, ~[i as u8]);
   }

   let mut w = ~[compressed[0] as u8];
   let compressed = compressed.slice(1, compressed.len());
   let mut result = w.clone();
   for &k in compressed.iter() {
      let entry =
         match dictionary.find(&k) {
            Some(v) => v.clone(),
            None if k == dict_size => vec::append_one(w.clone(), w[0]),
            None => fail!("Invalid compressed string")
         };

      result = vec::append(result, entry);
      dictionary.insert(dict_size, vec::append_one(w, entry[0]));
      dict_size += 1;
      w = entry;
   }

   str::from_utf8_owned(result)
}

fn main() {
   let original = "TOBEORNOTTOBEORTOBEORNOT";

   let compressed = compress(original);
   println!("{:?}", compressed);

   let decompressed = decompress(compressed);
   println!("{:s}", decompressed);

   // Check if the decompressed string corresponds to the original string
   assert!(original == decompressed);
}
<commit_msg>Updated lzw to unwrap<commit_after>// Implements http://rosettacode.org/wiki/LZW_compression

use std::hashmap::HashMap;
use std::vec;
use std::str;

fn compress(original_str: &str) -> ~[int] {
   let original = original_str.as_bytes();
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(~[i as u8], i);
   }

   let mut result = ~[];
   let mut w:~[u8] = ~[];
   for &c in original.iter() {
      let mut wc = w.clone();
      wc.push(c);

      match dictionary.find(&wc) {
         Some(_) => w = wc,
         None => {
            result.push(*dictionary.get(&w));
            dictionary.insert(wc, dict_size);
            dict_size += 1;
            w = ~[c];
         }
      }
   }

   if w.len() > 0 {
      result.push(*dictionary.get(&w));
   }

   result
}

fn decompress(compressed: &[int]) -> ~str {
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(i, ~[i as u8]);
   }

   let mut w = ~[compressed[0] as u8];
   let compressed = compressed.slice(1, compressed.len());
   let mut result = w.clone();
   for &k in compressed.iter() {
      let entry =
         match dictionary.find(&k) {
            Some(v) => v.clone(),
            None if k == dict_size => vec::append_one(w.clone(), w[0]),
            None => fail!("Invalid compressed string")
         };

      result = vec::append(result, entry);
      dictionary.insert(dict_size, vec::append_one(w, entry[0]));
      dict_size += 1;
      w = entry;
   }

   str::from_utf8_owned(result).unwrap()
}

fn main() {
   let original = "TOBEORNOTTOBEORTOBEORNOT";

   let compressed = compress(original);
   println!("{:?}", compressed);

   let decompressed = decompress(compressed);
   println!("{:s}", decompressed);

   // Check if the decompressed string corresponds to the original string
   assert!(original == decompressed);
}
<|endoftext|>


<commit_before>use std::rand::distributions::{Sample, Range};
use std::cmp::{Less, Equal, Greater};
use std::rand;

use command_mapper::{
    RustBotPlugin,
    CommandMapperDispatch,
    IrcBotConfigurator,
    Format,
};
use irc::message::{
    IrcMessage
};

type RollResult = [u8, ..6];
type ScoreRec = (uint, RollResult, int);

pub static SCORING_TABLE: [ScoreRec, ..28] = [
    (6, [1, 2, 3, 4, 5, 6], 1200),
    (6, [2, 2, 3, 3, 4, 4],  800),
    (6, [1, 1, 1, 1, 1, 1], 8000),
    (5, [1, 1, 1, 1, 1, 0], 4000),
    (4, [1, 1, 1, 1, 0, 0], 2000),
    (3, [1, 1, 1, 0, 0, 0], 1000),
    (1, [1, 0, 0, 0, 0, 0],  100),
    (6, [2, 2, 2, 2, 2, 2], 1600),
    (5, [2, 2, 2, 2, 2, 0],  800),
    (4, [2, 2, 2, 2, 0, 0],  400),
    (3, [2, 2, 2, 0, 0, 0],  200),
    (6, [3, 3, 3, 3, 3, 3], 2400),
    (5, [3, 3, 3, 3, 3, 0], 1200),
    (4, [3, 3, 3, 3, 0, 0],  600),
    (3, [3, 3, 3, 0, 0, 0],  300),
    (6, [4, 4, 4, 4, 4, 4], 3200),
    (5, [4, 4, 4, 4, 4, 0], 1600),
    (4, [4, 4, 4, 4, 0, 0],  800),
    (3, [4, 4, 4, 0, 0, 0],  400),
    (6, [5, 5, 5, 5, 5, 5], 4000),
    (5, [5, 5, 5, 5, 5, 0], 2000),
    (4, [5, 5, 5, 5, 0, 0], 1000),
    (3, [5, 5, 5, 0, 0, 0],  500),
    (1, [5, 0, 0, 0, 0, 0],   50),
    (6, [6, 6, 6, 6, 6, 6], 4800),
    (5, [6, 6, 6, 6, 6, 0], 2400),
    (4, [6, 6, 6, 6, 0, 0], 1200),
    (3, [6, 6, 6, 0, 0, 0],  600),
];

struct GreedState {
    channel: String,
    last_played: Option<(String, RollResult, int)>
}

pub struct GreedPlugin {
    states: Vec<GreedState>,
}

enum GreedCommandType {
    Greed
}

fn parse_command<'a>(m: &CommandMapperDispatch) -> Option<GreedCommandType> {
    let command_phrase = match m.command() {
        Some(command_phrase) => command_phrase,
        None => return None
    };
    match command_phrase.command[] {
        "greed" => Some(Greed),
        _ => None
    }
}

#[inline]
fn is_prefix(rec: &ScoreRec, roll: &RollResult, start_idx: uint) -> bool {
    let (prefix_len, ref roll_target, _) = *rec;

    if roll.len() < start_idx + prefix_len {
        return false;
    }
    for idx in range(0, prefix_len) {
        if roll[idx + start_idx] != roll_target[idx] {
            return false;
        }
    }
    true
}

fn dice_roll() -> RollResult {
    let mut rng = rand::task_rng();
    let mut out: RollResult = [0u8, ..6];
    let mut between = Range::new(1u8, 7u8);
    for val in out.iter_mut() {
        *val = between.sample(&mut rng);
    }
    out.sort();
    out
}

fn get_prefix_len(rec: &ScoreRec) -> uint {
    let (prefix_len, _, _) = *rec;
    prefix_len
}

fn get_scores(roll: &RollResult) -> Vec<&'static ScoreRec> {
    let mut idx = 0;
    let mut score_comps = Vec::new();
    while idx < roll.len() {
        let mut idx_incr = 1;
        for score_rec in SCORING_TABLE.iter() {
            // println!("is_prefix({:?}, {:?}, {:?})", score_rec, roll, idx);
            if is_prefix(score_rec, roll, idx) {
                idx_incr = get_prefix_len(score_rec);
                // println!("pushing {:?}", score_rec);
                score_comps.push(score_rec);
                break;
            }
        }
        idx += idx_incr;
    }
    score_comps
}

fn total_score(scores: &Vec<&ScoreRec>) -> int {
    let mut sum = 0;
    for score in scores.iter() {
        let (_, _, score_val) = **score;
        sum += score_val;
    }
    sum
}

fn find_or_create_state<'a>(states: &'a mut Vec<GreedState>, channel: &str) -> &'a mut GreedState {
    let mut want_idx = None;
    for (i, state) in states.iter().enumerate() {
        if state.channel.as_slice() == channel {
            want_idx = Some(i);
        }
    }
    match want_idx {
        Some(idx) => {
            states.get_mut(idx)
        },
        None => {
            states.push(GreedState {
                channel: String::from_str(channel),
                last_played: None
            });
            states.last_mut().unwrap()
        }
    }
}

fn format_score_component_bare(roll_result: &RollResult) -> String {
    let mut rolls = String::new();
    for value in roll_result.iter() {
        if *value == 0 {
            break
        }
        rolls.push_str(format!("{}, ", value).as_slice());
    }
    rolls.pop(); rolls.pop();
    format!("{}", rolls.as_slice())
}

fn format_score_component(score_components: &ScoreRec) -> String {
    let (_, ref prefix_data, _) = *score_components;
    format_score_component_bare(prefix_data)
}

fn format_score(score_components: &Vec<&ScoreRec>) -> String {
    let mut output = String::new();
    for tuple in score_components.iter() {
        let (_, _, score) = **tuple;
        output.push_str(format!(
            "[{} => {}], ",
            format_score_component(*tuple).as_slice(),
            score
        ).as_slice());
    }
    output.pop(); output.pop();
    output
}

impl GreedPlugin {
    pub fn new() -> GreedPlugin {
        GreedPlugin {
            states: Vec::new()
        }
    }

    fn dispatch_cmd_greed(&mut self, m: &CommandMapperDispatch, message: &IrcMessage) {
        let channel = match message.channel() {
            Some(channel) => channel,
            None => return
        };

        let source_nick = match message.source_nick() {
            Some(nickname) => nickname,
            None => return
        };

        let state = find_or_create_state(&mut self.states, channel);

        let cur_user_roll: RollResult = dice_roll();
        let score_components: Vec<&'static ScoreRec> = get_scores(&cur_user_roll);
        let score = total_score(&score_components);

        match state.last_played {
            Some(ref last_played) => {
                let (ref prev_nick, _, _) = *last_played;
                if prev_nick.as_slice() == source_nick {
                    m.reply(format!("You can't go twice in a row, {}", source_nick));
                    return;
                }
            },
            None => ()
        }

        m.reply(format!("[{}] => [{}] for {} points",
            format_score_component_bare(&cur_user_roll),
            format_score(&score_components).as_slice(),
            score));

        state.last_played = match state.last_played.take() {
            Some(last_played) => {
                let (prev_nick, _, prev_score) = last_played;
                // let prev_score_components: Vec<&'static ScoreRec> = get_scores(&prev_roll);

                m.reply(match prev_score.cmp(&score) {
                    Less => format!("{} wins!", source_nick),
                    Equal => format!("{} and {} tie.", source_nick, prev_nick),
                    Greater => format!("{} wins!", prev_nick)
                });
                None
            },
            None => {
                Some((source_nick.to_string(), cur_user_roll, score))
            }
        }
    }
}

impl RustBotPlugin for GreedPlugin {
    fn configure(&mut self, conf: &mut IrcBotConfigurator) {
        conf.map_format(Format::from_str("greed").unwrap());
    }

    fn dispatch_cmd(&mut self, m: &CommandMapperDispatch, message: &IrcMessage) {
        match parse_command(m) {
            Some(Greed) => self.dispatch_cmd_greed(m, message),
            None => ()
        }
    }

    // fn save_instance_state(&mut self,
}
<commit_msg>Upgrade the greed<commit_after>use std::collections::hashmap::{
    HashMap,
    Vacant,
    Occupied,
};
use std::rand::distributions::{Sample, Range};
use std::cmp::{Less, Equal, Greater};
use std::fmt::{Formatter, FormatError, Show};
use std::rand::{task_rng, Rng, Rand};

use command_mapper::{
    RustBotPlugin,
    CommandMapperDispatch,
    IrcBotConfigurator,
    Format,
};
use state::{
    BotChannelId,
    BotUserId,
    KnownChannel,
    KnownUser,
};
use irc::message::{
    IrcMessage
};

type ScorePrefix = [u8, ..6];
type ScoreRec = (uint, ScorePrefix, int);

pub static SCORING_TABLE: [ScoreRec, ..28] = [
    (6, [1, 2, 3, 4, 5, 6], 1200),
    (6, [2, 2, 3, 3, 4, 4],  800),
    (6, [1, 1, 1, 1, 1, 1], 8000),
    (5, [1, 1, 1, 1, 1, 0], 4000),
    (4, [1, 1, 1, 1, 0, 0], 2000),
    (3, [1, 1, 1, 0, 0, 0], 1000),
    (1, [1, 0, 0, 0, 0, 0],  100),
    (6, [2, 2, 2, 2, 2, 2], 1600),
    (5, [2, 2, 2, 2, 2, 0],  800),
    (4, [2, 2, 2, 2, 0, 0],  400),
    (3, [2, 2, 2, 0, 0, 0],  200),
    (6, [3, 3, 3, 3, 3, 3], 2400),
    (5, [3, 3, 3, 3, 3, 0], 1200),
    (4, [3, 3, 3, 3, 0, 0],  600),
    (3, [3, 3, 3, 0, 0, 0],  300),
    (6, [4, 4, 4, 4, 4, 4], 3200),
    (5, [4, 4, 4, 4, 4, 0], 1600),
    (4, [4, 4, 4, 4, 0, 0],  800),
    (3, [4, 4, 4, 0, 0, 0],  400),
    (6, [5, 5, 5, 5, 5, 5], 4000),
    (5, [5, 5, 5, 5, 5, 0], 2000),
    (4, [5, 5, 5, 5, 0, 0], 1000),
    (3, [5, 5, 5, 0, 0, 0],  500),
    (1, [5, 0, 0, 0, 0, 0],   50),
    (6, [6, 6, 6, 6, 6, 6], 4800),
    (5, [6, 6, 6, 6, 6, 0], 2400),
    (4, [6, 6, 6, 6, 0, 0], 1200),
    (3, [6, 6, 6, 0, 0, 0],  600),
];

struct RollResult([u8, ..6]);

#[inline]
fn is_prefix(rec: &ScoreRec, roll_res: &RollResult, start_idx: uint) -> bool {
    let RollResult(ref roll_data) = *roll_res;
    let (prefix_len, ref roll_target, _) = *rec;

    if roll_data.len() < start_idx + prefix_len {
        return false;
    }
    for idx in range(0, prefix_len) {
        if roll_data[idx + start_idx] != roll_target[idx] {
            return false;
        }
    }
    true
}

impl RollResult {
    fn get_scores(&self) -> Vec<&'static ScoreRec> {
        let RollResult(ref roll) = *self;
        let mut idx = 0;
        let mut score_comps = Vec::new();
        while idx < roll.len() {
            let mut idx_incr = 1;
            for score_rec in SCORING_TABLE.iter() {
                if is_prefix(score_rec, self, idx) {
                    let (prefix_len, _, _) = *score_rec;
                    idx_incr = prefix_len;
                    score_comps.push(score_rec);
                    break;
                }
            }
            idx += idx_incr;
        }
        score_comps
    }

    fn total_score(&self) -> int {
        let mut sum = 0;
        for score in self.get_scores().iter() {
            let (_, _, score_val) = **score;
            sum += score_val;
        }
        sum
    }

    fn format_score_component_bare(score_pref: &ScorePrefix) -> String {
        let mut rolls = String::new();
        for value in score_pref.iter() {
            if *value == 0 {
                break
            }
            rolls.push_str(format!("{}, ", value).as_slice());
        }
        rolls.pop(); rolls.pop();
        format!("{}", rolls.as_slice())
    }

    fn format_score_component(score_components: &ScoreRec) -> String {
        let (_, ref prefix_data, _) = *score_components;
        RollResult::format_score_component_bare(prefix_data)
    }

    fn format_score(score_components: &Vec<&ScoreRec>) -> String {
        let mut output = String::new();
        for tuple in score_components.iter() {
            let (_, _, score) = **tuple;
            output.push_str(format!(
                "[{} => {}], ",
                RollResult::format_score_component(*tuple).as_slice(),
                score
            ).as_slice());
        }
        output.pop(); output.pop();
        output
    }
}

impl Rand for RollResult {
    fn rand<R: Rng>(rng: &mut R) -> RollResult {
        let mut out: ScorePrefix = [0u8, ..6];
        let mut between = Range::new(1u8, 7u8);
        for val in out.iter_mut() {
            *val = between.sample(rng);
        }
        out.sort();
        RollResult(out)
    }
}

impl Show for RollResult {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        let RollResult(ref roll) = *self;
        write!(f, "[{}] => [{}] for {} points",
            RollResult::format_score_component_bare(roll),
            RollResult::format_score(&self.get_scores()),
            self.total_score())
    }
}

pub struct GreedPlugin {
    games: HashMap<BotChannelId, GreedPlayResult>
}

enum GreedCommandType {
    Greed
}

struct GreedPlayResult {
    user_id: BotUserId,
    user_nick: String,
    roll: RollResult,
}

fn parse_command<'a>(m: &CommandMapperDispatch) -> Option<GreedCommandType> {
    let command_phrase = match m.command() {
        Some(command_phrase) => command_phrase,
        None => return None
    };
    match command_phrase.command[] {
        "greed" => Some(Greed),
        _ => None
    }
}

impl GreedPlugin {
    pub fn new() -> GreedPlugin {
        GreedPlugin {
            games: HashMap::new()
        }
    }

    fn dispatch_cmd_greed(&mut self, m: &CommandMapperDispatch, message: &IrcMessage) {
        let (user_id, channel_id) = match (m.source.clone(), m.target.clone()) {
            (Some(KnownUser(uid)), Some(KnownChannel(cid))) => (uid, cid),
            _ => return
        };

        let source_nick = match message.source_nick() {
            Some(nickname) => nickname,
            None => return
        };

        match self.games.entry(channel_id) {
            Vacant(entry) => {
                let roll = task_rng().gen::<RollResult>();
                m.reply(format!("{}: {}", source_nick, roll));
                entry.set(GreedPlayResult {
                    user_id: user_id,
                    user_nick: source_nick.to_string(),
                    roll: roll
                });
            },
            Occupied(entry) => {
                {
                    let prev_play = entry.get();
                    if prev_play.user_id == user_id {
                        m.reply(format!("You can't go twice in a row, {}", source_nick));
                        return;
                    }
                }
                let prev_play = entry.take();
                let roll = task_rng().gen::<RollResult>();
                m.reply(format!("{}: {}", source_nick, roll));

                m.reply(match prev_play.roll.total_score().cmp(&roll.total_score()) {
                     Less => format!("{} wins!", source_nick),
                     Equal => format!("{} and {} tie.", source_nick, prev_play.user_nick),
                     Greater => format!("{} wins!", prev_play.user_nick)
                });
            }
        }
    }
}

impl RustBotPlugin for GreedPlugin {
    fn configure(&mut self, conf: &mut IrcBotConfigurator) {
        conf.map_format(Format::from_str("greed").unwrap());
    }

    fn dispatch_cmd(&mut self, m: &CommandMapperDispatch, message: &IrcMessage) {
        match parse_command(m) {
            Some(Greed) => self.dispatch_cmd_greed(m, message),
            None => ()
        }
    }
}
<|endoftext|>


<commit_before>use cairo::ImageSurface;
use cairo_sys;
use glib::translate::ToGlibPtr;
use wlroots::utils::current_time;
use wlroots::wlroots_sys;
use wlroots::{project_box, Area, CompositorHandle, Origin, OutputHandle, OutputHandler,
            OutputLayoutHandle, Renderer, Size, SurfaceHandle, WL_SHM_FORMAT_ARGB8888};

use awesome::{Drawin, Objectable, DRAWINS_HANDLE, LUA};
use compositor::{Server, View};
use rlua::{self, AnyUserData, Lua};
use std::rc::Rc;

pub struct Output;

impl OutputHandler for Output {
fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
    dehandle!(
        @compositor = {compositor};
        @output = {output};
        let state: &mut Server = compositor.data.downcast_mut().unwrap();
        let Server { ref mut layout,
                        ref mut views,
                        .. } = *state;
        let renderer = compositor.renderer.as_mut().expect("gles2 disabled");
        let mut renderer = renderer.render(output, None);
            renderer.clear([0.25, 0.25, 0.25, 1.0]);
            render_views(&mut renderer, layout, views);
            LUA.with(|lua| {
                let lua = lua.borrow();
                match render_drawins(&*lua, &mut renderer) {
                    Ok(_) => {},
                    Err(err) => {
                        warn!("Error rendering drawins: {:#?}", err);
                    }
                }
            }));
    }
}

fn render_surface(renderer: &mut Renderer,
                  layout: &mut OutputLayoutHandle,
                  surface: &mut SurfaceHandle,
                  lx: i32,
                  ly: i32) {
    with_handles!([(surface: {surface}), (layout: {&mut *layout})] => {
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
            height * renderer.output.scale() as i32);
        let render_box = Area::new(Origin::new(lx, ly),
        Size::new(render_width,
                  render_height));

        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = project_box(render_box,
                                     transform,
                                     0.0,
                                     renderer.output
                                     .transform_matrix());
            renderer.render_texture_with_matrix(&surface.texture(), matrix);
            surface.send_frame_done(current_time());
        }

    }).unwrap();
}

/// Render all of the client views.
fn render_views(renderer: &mut Renderer,
                layout: &mut OutputLayoutHandle,
                views: &mut Vec<Rc<View>>) {
    for view in views.iter_mut().rev() {
        let origin = view.origin.get();
        view.for_each_surface(&mut |surface: SurfaceHandle, sx, sy| {
            dehandle!(
                @surface = {surface};
                @layout = {&*layout};
                let (width, height) = surface.current_state().size();
                let (render_width, render_height) =
                    (width * renderer.output.scale() as i32,
                     height * renderer.output.scale() as i32);
                let render_box = Area::new(Origin::new(origin.x + sx, origin.y + sy),
                                           Size::new(render_width,
                                                     render_height));

                if layout.intersects(renderer.output, render_box) {
                    let transform = renderer.output.get_transform().invert();
                    let matrix = project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
                    renderer.render_texture_with_matrix(&surface.texture(), matrix);
                    surface.send_frame_done(current_time());
                })
        });
    }
}

/// Render all of the drawins provided by Lua.
fn render_drawins(lua: &Lua, renderer: &mut Renderer) -> rlua::Result<()> {
    let drawins = lua.named_registry_value::<Vec<AnyUserData>>(DRAWINS_HANDLE)?;
    error!("Drawins: {}", drawins.len());
    for drawin in drawins {
        let mut drawin = Drawin::cast(drawin.into())?;
        if let Some(texture) = drawin.texture()?.take() {
            unsafe {
                error!("Deleting {:p}", texture.as_ptr());
                wlroots_sys::wlr_texture_destroy(texture.as_ptr());
            }
        }
        if !drawin.get_visible()? {
            continue
        }
        let geometry = drawin.get_geometry()?;
        let texture;
        {
            let drawable = drawin.drawable()?;
            let mut drawable_state = drawable.state()?;
            let surface = match drawable_state.surface.as_mut() {
                Some(surface) => surface,
                None => continue
            };
            let Area { size: Size { width, height },
                       .. } = geometry;
            let data = get_data(surface);
            texture = renderer.create_texture_from_pixels(WL_SHM_FORMAT_ARGB8888,
                                                          (width * 4) as _,
                                                          width as _,
                                                          height as _,
                                                          data)
                .expect("Could not allocate texture");
            let transform_matrix = renderer.output.transform_matrix();
            let inverted_transform = renderer.output.get_transform().invert();
            let matrix = project_box(geometry, inverted_transform, 0.0, transform_matrix);
            renderer.render_texture_with_matrix(&texture, matrix);
        }
        unsafe {
            error!("Saving {:p}", texture.as_ptr());
        }
        *drawin.texture()? = Some(texture);
    }
    Ok(())
}

/// Get the data associated with an ImageSurface.
fn get_data(surface: &mut ImageSurface) -> &[u8] {
    use std::slice;
    // NOTE This is safe to do because there's one thread.
    //
    // We know Lua is not modifying it because it's not running.
    //
    // Otherwise we'd need to make a copy of the buffer. This ensure we
    // don't need to do that.
    unsafe {
        let len = surface.get_stride() as usize * surface.get_height() as usize;
        let surface = surface.to_glib_none().0;
        slice::from_raw_parts(cairo_sys::cairo_image_surface_get_data(surface as _), len)
    }
}
<commit_msg>Really shitty fix for this memory leak<commit_after>use cairo::ImageSurface;
use cairo_sys;
use glib::translate::ToGlibPtr;
use wlroots::utils::current_time;
use wlroots::wlroots_sys;
use wlroots::{project_box, Area, CompositorHandle, Origin, OutputHandle, OutputHandler,
            OutputLayoutHandle, Renderer, Size, SurfaceHandle, WL_SHM_FORMAT_ARGB8888};

use awesome::{Drawin, Objectable, DRAWINS_HANDLE, LUA};
use compositor::{Server, View};
use rlua::{self, AnyUserData, Lua, ToLua};
use std::rc::Rc;

pub struct Output;

impl OutputHandler for Output {
fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
    dehandle!(
        @compositor = {compositor};
        @output = {output};
        let state: &mut Server = compositor.data.downcast_mut().unwrap();
        let Server { ref mut layout,
                        ref mut views,
                        .. } = *state;
        let renderer = compositor.renderer.as_mut().expect("gles2 disabled");
        let mut renderer = renderer.render(output, None);
            renderer.clear([0.25, 0.25, 0.25, 1.0]);
            render_views(&mut renderer, layout, views);
            LUA.with(|lua| {
                let lua = lua.borrow();
                match render_drawins(&*lua, &mut renderer) {
                    Ok(_) => {},
                    Err(err) => {
                        warn!("Error rendering drawins: {:#?}", err);
                    }
                }
            }));
    }
}

fn render_surface(renderer: &mut Renderer,
                  layout: &mut OutputLayoutHandle,
                  surface: &mut SurfaceHandle,
                  lx: i32,
                  ly: i32) {
    with_handles!([(surface: {surface}), (layout: {&mut *layout})] => {
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
            height * renderer.output.scale() as i32);
        let render_box = Area::new(Origin::new(lx, ly),
        Size::new(render_width,
                  render_height));

        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = project_box(render_box,
                                     transform,
                                     0.0,
                                     renderer.output
                                     .transform_matrix());
            renderer.render_texture_with_matrix(&surface.texture(), matrix);
            surface.send_frame_done(current_time());
        }

    }).unwrap();
}

/// Render all of the client views.
fn render_views(renderer: &mut Renderer,
                layout: &mut OutputLayoutHandle,
                views: &mut Vec<Rc<View>>) {
    for view in views.iter_mut().rev() {
        let origin = view.origin.get();
        view.for_each_surface(&mut |surface: SurfaceHandle, sx, sy| {
            dehandle!(
                @surface = {surface};
                @layout = {&*layout};
                let (width, height) = surface.current_state().size();
                let (render_width, render_height) =
                    (width * renderer.output.scale() as i32,
                     height * renderer.output.scale() as i32);
                let render_box = Area::new(Origin::new(origin.x + sx, origin.y + sy),
                                           Size::new(render_width,
                                                     render_height));

                if layout.intersects(renderer.output, render_box) {
                    let transform = renderer.output.get_transform().invert();
                    let matrix = project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
                    renderer.render_texture_with_matrix(&surface.texture(), matrix);
                    surface.send_frame_done(current_time());
                })
        });
    }
}

fn remove_old_drawins(lua: &Lua) -> rlua::Result<()> {
    let mut drawins = lua.named_registry_value::<Vec<AnyUserData>>(DRAWINS_HANDLE)?;
    for drawin_obj in &mut drawins {
        let mut drawin = Drawin::cast(drawin_obj.clone().into())?;
        if let Some(texture) = drawin.texture()?.take() {
            unsafe {
                error!("Deleting {:p}", texture.as_ptr());
                wlroots_sys::wlr_texture_destroy(texture.as_ptr());
            }
        }
        *drawin_obj = match drawin.to_lua(lua)? {
            rlua::Value::UserData(userdata) => userdata,
            _ => unreachable!()
        }
    }
    lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
    Ok(())
}

/// Render all of the drawins provided by Lua.
fn render_drawins(lua: &Lua, renderer: &mut Renderer) -> rlua::Result<()> {
    let drawins = lua.named_registry_value::<Vec<AnyUserData>>(DRAWINS_HANDLE)?;
    for drawin in drawins {
        let mut drawin = Drawin::cast(drawin.into())?;
        if !drawin.get_visible()? {
            continue
        }
        let geometry = drawin.get_geometry()?;
        let texture;
        {
            let drawable = drawin.drawable()?;
            let mut drawable_state = drawable.state()?;
            let surface = match drawable_state.surface.as_mut() {
                Some(surface) => surface,
                None => continue
            };
            let Area { size: Size { width, height },
                       .. } = geometry;
            let data = get_data(surface);
            texture = renderer.create_texture_from_pixels(WL_SHM_FORMAT_ARGB8888,
                                                          (width * 4) as _,
                                                          width as _,
                                                          height as _,
                                                          data)
                .expect("Could not allocate texture");
            let transform_matrix = renderer.output.transform_matrix();
            let inverted_transform = renderer.output.get_transform().invert();
            let matrix = project_box(geometry, inverted_transform, 0.0, transform_matrix);
            renderer.render_texture_with_matrix(&texture, matrix);
        }
        unsafe {
            error!("Saving {:p}", texture.as_ptr());
        }
        *drawin.texture()? = Some(texture);
    }
    Ok(())
}

/// Get the data associated with an ImageSurface.
fn get_data(surface: &mut ImageSurface) -> &[u8] {
    use std::slice;
    // NOTE This is safe to do because there's one thread.
    //
    // We know Lua is not modifying it because it's not running.
    //
    // Otherwise we'd need to make a copy of the buffer. This ensure we
    // don't need to do that.
    unsafe {
        let len = surface.get_stride() as usize * surface.get_height() as usize;
        let surface = surface.to_glib_none().0;
        slice::from_raw_parts(cairo_sys::cairo_image_surface_get_data(surface as _), len)
    }
}
<|endoftext|>


<commit_before>#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area,
            last_area: ((self_ptr as u32) + self.size - self.entry_size) as *const MemoryArea,
            entry_size: self.entry_size,
        }
    }
}

#[repr(C)]
pub struct MemoryArea {
    pub base_addr: u64,
    pub length: u64,
    typ: u32,
    _reserved: u32,
}

#[derive(Clone)]
pub struct MemoryAreaIter {
    current_area: *const MemoryArea,
    last_area: *const MemoryArea,
    entry_size: u32,
}

impl Iterator for MemoryAreaIter {
    type Item = &'static MemoryArea;
    fn next(&mut self) -> Option<&'static MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*self.current_area};
            self.current_area = ((self.current_area as u32) + self.entry_size)
                as *const MemoryArea;
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<commit_msg>Prevent overflow in `src/memory_map.rs` (#15)<commit_after>#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area,
            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64)
                as *const MemoryArea,
            entry_size: self.entry_size,
        }
    }
}

#[repr(C)]
pub struct MemoryArea {
    pub base_addr: u64,
    pub length: u64,
    typ: u32,
    _reserved: u32,
}

#[derive(Clone)]
pub struct MemoryAreaIter {
    current_area: *const MemoryArea,
    last_area: *const MemoryArea,
    entry_size: u32,
}

impl Iterator for MemoryAreaIter {
    type Item = &'static MemoryArea;
    fn next(&mut self) -> Option<&'static MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*self.current_area};
            self.current_area = ((self.current_area as u64) + self.entry_size as u64)
                as *const MemoryArea;
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<|endoftext|>


<commit_before>//! Low-Level bindings for NumPy C API.
//!
//! https://numpy.org/doc/stable/reference/c-api
#![allow(non_camel_case_types, clippy::too_many_arguments)]

use pyo3::{ffi, Python};
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr::null_mut;

fn get_numpy_api(_py: Python, module: &str, capsule: &str) -> *const *const c_void {
    let module = CString::new(module).unwrap();
    let capsule = CString::new(capsule).unwrap();
    unsafe {
        let numpy = ffi::PyImport_ImportModule(module.as_ptr());
        assert!(!numpy.is_null(), "Failed to import numpy module");
        let capsule = ffi::PyObject_GetAttrString(numpy as _, capsule.as_ptr());
        assert!(!capsule.is_null(), "Failed to import numpy module");
        ffi::PyCapsule_GetPointer(capsule, null_mut()) as _
    }
}

// Define Array&UFunc APIs
macro_rules! impl_api {
    [$offset: expr; $fname: ident ( $($arg: ident : $t: ty),* ) $( -> $ret: ty )* ] => {
        #[allow(non_snake_case)]
        pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* {
            let fptr = self.get($offset)
                           as *const extern fn ($($arg : $t), *) $( -> $ret )*;
            (*fptr)($($arg), *)
        }
    };
    // To allow fn a(b: type,) -> ret
    [$offset: expr; $fname: ident ( $($arg: ident : $t:ty,)* ) $( -> $ret: ty )* ] => {
        impl_api![$offset; $fname( $($arg: $t),*) $( -> $ret )*];
    }
}

pub mod array;
pub mod flags;
pub mod objects;
pub mod types;
pub mod ufunc;

pub use self::array::*;
pub use self::flags::*;
pub use self::objects::*;
pub use self::types::*;
pub use self::ufunc::*;
<commit_msg>More verbose error reporting when importing numpy module<commit_after>//! Low-Level bindings for NumPy C API.
//!
//! https://numpy.org/doc/stable/reference/c-api
#![allow(non_camel_case_types, clippy::too_many_arguments)]

use pyo3::{ffi, Python};
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr::null_mut;

fn get_numpy_api(_py: Python, module: &str, capsule: &str) -> *const *const c_void {
    let module = CString::new(module).unwrap();
    let capsule = CString::new(capsule).unwrap();
    unsafe {
        let numpy = ffi::PyImport_ImportModule(module.as_ptr());
        assert!(!numpy.is_null(), "Failed to import numpy module");
        let capsule = ffi::PyObject_GetAttrString(numpy as _, capsule.as_ptr());
        assert!(!capsule.is_null(), "Failed to get numpy capsule API");
        ffi::PyCapsule_GetPointer(capsule, null_mut()) as _
    }
}

// Define Array&UFunc APIs
macro_rules! impl_api {
    [$offset: expr; $fname: ident ( $($arg: ident : $t: ty),* ) $( -> $ret: ty )* ] => {
        #[allow(non_snake_case)]
        pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* {
            let fptr = self.get($offset)
                           as *const extern fn ($($arg : $t), *) $( -> $ret )*;
            (*fptr)($($arg), *)
        }
    };
    // To allow fn a(b: type,) -> ret
    [$offset: expr; $fname: ident ( $($arg: ident : $t:ty,)* ) $( -> $ret: ty )* ] => {
        impl_api![$offset; $fname( $($arg: $t),*) $( -> $ret )*];
    }
}

pub mod array;
pub mod flags;
pub mod objects;
pub mod types;
pub mod ufunc;

pub use self::array::*;
pub use self::flags::*;
pub use self::objects::*;
pub use self::types::*;
pub use self::ufunc::*;
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Palindrome_detection
#![allow(unused_features)]

// Returns true if the string is a palindrome
fn palindrome(string: &str) -> bool {
    // The first part of the string
    let forward = string.chars().take(string.len() / 2);

    // The second part of the string in reverse order
    let reverse = string.chars().rev().take(string.len() / 2);

    // We group the two parts of the string in tuples
    let both_directions = forward.zip(reverse);

    // The word is a palindrome if each tuple contains two times
    // the same character
    both_directions.all(|(a, b)| {a == b})
}

// Demonstration code
#[cfg(not(test))]
fn main() {
    let test_strings = ["nope", "eevee", "lalala", "rust", "lalalal"];
    for &string in &test_strings {
        println!("{}: {}", string, palindrome(string));
    }
}

#[test]
fn test_palindromes() {
    let palindromes = ["eevee", "lalalal", "オオオオ", "", "anna"];
    let non_palindromes = ["nope", "lalala", "car", "rain", "house", "computer", "rust"];

    assert!(palindromes.iter().all(|&s| palindrome(s)));
    assert!(non_palindromes.iter().all(|&s| !palindrome(s)));
}
<commit_msg>Fix build<commit_after>// Implements http://rosettacode.org/wiki/Palindrome_detection
#![allow(unused_features)]

// Returns true if the string is a palindrome
fn palindrome(string: &str) -> bool {
    // The first part of the string
    let forward = string.chars().take(string.len() / 2);

    // The second part of the string in reverse order
    let reverse = string.chars().rev().take(string.len() / 2);

    // We group the two parts of the string in tuples
    let mut both_directions = forward.zip(reverse);

    // The word is a palindrome if each tuple contains two times
    // the same character
    both_directions.all(|(a, b)| {a == b})
}

// Demonstration code
#[cfg(not(test))]
fn main() {
    let test_strings = ["nope", "eevee", "lalala", "rust", "lalalal"];
    for &string in &test_strings {
        println!("{}: {}", string, palindrome(string));
    }
}

#[test]
fn test_palindromes() {
    let palindromes = ["eevee", "lalalal", "オオオオ", "", "anna"];
    let non_palindromes = ["nope", "lalala", "car", "rain", "house", "computer", "rust"];

    assert!(palindromes.iter().all(|&s| palindrome(s)));
    assert!(non_palindromes.iter().all(|&s| !palindrome(s)));
}
<|endoftext|>