<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![allow(non_snake_case)]

#![feature(phase)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

/// An actor-based remote devtools server implementation. Only tested with nightly Firefox
/// versions at time of writing. Largely based on reverse-engineering of Firefox chrome
/// devtool logs and reading of [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

extern crate collections;
extern crate core;
extern crate devtools_traits;
extern crate serialize;
extern crate sync;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use protocol::JsonPacketStream;

use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg};
use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;

use std::cell::RefCell;
use std::collections::HashMap;
use std::comm;
use std::comm::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut};
use sync::{Arc, Mutex};

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod inspector;
    pub mod root;
    pub mod tab;
}
mod protocol;

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = comm::channel();
    spawn_named("Devtools", proc() {
        run_server(receiver, port)
    });
    sender
}

static POLL_TIMEOUT: u64 = 300;

fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
    let listener = TcpListener::bind(format!("{}:{}", "127.0.0.1", port).as_slice());

    // bind the listener to the specified address
    let mut acceptor = listener.listen().unwrap();
    acceptor.set_timeout(Some(POLL_TIMEOUT));

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = Arc::new(Mutex::new(registry));

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_name().unwrap());
        {
            let actors = actors.lock();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(json_packet) => {
                    match actors.lock().handle_message(json_packet.as_object().unwrap(),
                                                       &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            stream.close_read();
                            stream.close_write();
                            break 'outer
                        }
                    }
                }
                Err(e) => {
                    println!("error: {}", e.desc);
                    break 'outer
                }
            }
        }
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         pipeline: PipelineId,
                         sender: Sender<DevtoolScriptControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>) {
        let mut actors = actors.lock();

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: sender,
                pipeline: pipeline,
            };
            //TODO: send along the current page title and URL
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: "".to_string(),
                url: "about:blank".to_string(),
                console: console.name(),
                inspector: inspector.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector)
        };

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
    }

    //TODO: figure out some system that allows us to watch for new connections,
    //      shut down existing ones at arbitrary times, and also watch for messages
    //      from multiple script tasks simultaneously. Polling for new connections
    //      for 300ms and then checking the receiver is not a good compromise
    //      (and makes Servo hang on exit if there's an open connection, no less).
    // accept connections and process them, spawning a new tasks for each one
    loop {
        match acceptor.accept() {
            Err(ref e) if e.kind == TimedOut => {
                match receiver.try_recv() {
                    Ok(ServerExitMsg) | Err(Disconnected) => break,
                    Ok(NewGlobal(id, sender)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines),
                    Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
                }
            }
            Err(_e) => { /* connection failed */ }
            Ok(stream) => {
                let actors = actors.clone();
                accepted_connections.push(stream.clone());
                spawn_named("DevtoolsClientHandler", proc() {
                    // connection succeeded
                    handle_client(actors, stream.clone())
                })
            }
        }
    }

    for connection in accepted_connections.iter_mut() {
        let _read = connection.close_read();
        let _write = connection.close_write();
    }
}
<commit_msg>auto merge of #4233 : driftersprt/servo/BUG-4232, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![allow(non_snake_case)]

#![feature(phase)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

/// An actor-based remote devtools server implementation. Only tested with nightly Firefox
/// versions at time of writing. Largely based on reverse-engineering of Firefox chrome
/// devtool logs and reading of [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

extern crate collections;
extern crate core;
extern crate devtools_traits;
extern crate serialize;
extern crate sync;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use protocol::JsonPacketStream;

use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg};
use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;

use std::cell::RefCell;
use std::collections::HashMap;
use std::comm;
use std::comm::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut};
use sync::{Arc, Mutex};

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod inspector;
    pub mod root;
    pub mod tab;
}
mod protocol;

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = comm::channel();
    spawn_named("Devtools", proc() {
        run_server(receiver, port)
    });
    sender
}

static POLL_TIMEOUT: u64 = 300;

fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
    let listener = TcpListener::bind(format!("{}:{}", "127.0.0.1", port).as_slice());

    // bind the listener to the specified address
    let mut acceptor = listener.listen().unwrap();
    acceptor.set_timeout(Some(POLL_TIMEOUT));

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = Arc::new(Mutex::new(registry));

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_name().unwrap());
        {
            let actors = actors.lock();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(json_packet) => {
                    match actors.lock().handle_message(json_packet.as_object().unwrap(),
                                                       &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            let _ = stream.close_read();
                            let _ = stream.close_write();
                            break 'outer
                        }
                    }
                }
                Err(e) => {
                    println!("error: {}", e.desc);
                    break 'outer
                }
            }
        }
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         pipeline: PipelineId,
                         sender: Sender<DevtoolScriptControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>) {
        let mut actors = actors.lock();

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: sender,
                pipeline: pipeline,
            };
            //TODO: send along the current page title and URL
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: "".to_string(),
                url: "about:blank".to_string(),
                console: console.name(),
                inspector: inspector.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector)
        };

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
    }

    //TODO: figure out some system that allows us to watch for new connections,
    //      shut down existing ones at arbitrary times, and also watch for messages
    //      from multiple script tasks simultaneously. Polling for new connections
    //      for 300ms and then checking the receiver is not a good compromise
    //      (and makes Servo hang on exit if there's an open connection, no less).
    // accept connections and process them, spawning a new tasks for each one
    loop {
        match acceptor.accept() {
            Err(ref e) if e.kind == TimedOut => {
                match receiver.try_recv() {
                    Ok(ServerExitMsg) | Err(Disconnected) => break,
                    Ok(NewGlobal(id, sender)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines),
                    Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
                }
            }
            Err(_e) => { /* connection failed */ }
            Ok(stream) => {
                let actors = actors.clone();
                accepted_connections.push(stream.clone());
                spawn_named("DevtoolsClientHandler", proc() {
                    // connection succeeded
                    handle_client(actors, stream.clone())
                })
            }
        }
    }

    for connection in accepted_connections.iter_mut() {
        let _read = connection.close_read();
        let _write = connection.close_write();
    }
}
<|endoftext|>


<commit_before>//! Code sink that writes binary machine code into contiguous memory.
//!
//! The `CodeSink` trait is the most general way of extracting binary machine code from Cretonne,
//! and it is implemented by things like the `test binemit` file test driver to generate
//! hexadecimal machine code. The `CodeSink` has some undesirable performance properties because of
//! the dual abstraction: `TargetIsa` is a trait object implemented by each supported ISA, so it
//! can't have any generic functions that could be specialized for each `CodeSink` implementation.
//! This results in many virtual function callbacks (one per `put*` call) when
//! `TargetIsa::emit_inst()` is used.
//!
//! The `MemoryCodeSink` type fixes the performance problem because it is a type known to
//! `TargetIsa` so it can specialize its machine code generation for the type. The trade-off is
//! that a `MemoryCodeSink` will always write binary machine code to raw memory. It forwards any
//! relocations to a `RelocSink` trait object. Relocations are less frequent than the
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.

use ir::{Ebb, FuncRef, GlobalVar, JumpTable};
use super::{CodeSink, CodeOffset, Reloc};
use std::ptr::write_unaligned;

/// A `CodeSink` that writes binary machine code directly into memory.
///
/// A `MemoryCodeSink` object should be used when emitting a Cretonne IL function into executable
/// memory. It writes machine code directly to a raw pointer without any bounds checking, so make
/// sure to allocate enough memory for the whole function. The number of bytes required is returned
/// by the `Context::compile()` function.
///
/// Any relocations in the function are forwarded to the `RelocSink` trait object.
///
/// Note that `MemoryCodeSink` writes multi-byte values in the native byte order of the host. This
/// is not the right thing to do for cross compilation.
pub struct MemoryCodeSink<'a> {
    data: *mut u8,
    offset: isize,
    relocs: &'a mut RelocSink,
}

impl<'a> MemoryCodeSink<'a> {
    /// Create a new memory code sink that writes a function to the memory pointed to by `data`.
    pub fn new(data: *mut u8, relocs: &mut RelocSink) -> MemoryCodeSink {
        MemoryCodeSink {
            data,
            offset: 0,
            relocs,
        }
    }
}

/// A trait for receiving relocations for code that is emitted directly into memory.
pub trait RelocSink {
    /// Add a relocation referencing an EBB at the current offset.
    fn reloc_ebb(&mut self, CodeOffset, Reloc, Ebb);

    /// Add a relocation referencing an external function at the current offset.
    fn reloc_func(&mut self, CodeOffset, Reloc, FuncRef);

    /// Add a relocation referencing an external global variable symbol at the
    /// current offset.
    fn reloc_globalsym(&mut self, CodeOffset, Reloc, GlobalVar);

    /// Add a relocation referencing a jump table.
    /// Add a relocation referencing a jump table.
    fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
}

impl<'a> CodeSink for MemoryCodeSink<'a> {
    fn offset(&self) -> CodeOffset {
        self.offset as CodeOffset
    }

    fn put1(&mut self, x: u8) {
        unsafe {
            write_unaligned(self.data.offset(self.offset), x);
        }
        self.offset += 1;
    }

    fn put2(&mut self, x: u16) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u16, x);
        }
        self.offset += 2;
    }

    fn put4(&mut self, x: u32) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u32, x);
        }
        self.offset += 4;
    }

    fn put8(&mut self, x: u64) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u64, x);
        }
        self.offset += 8;
    }

    fn reloc_ebb(&mut self, rel: Reloc, ebb: Ebb) {
        let ofs = self.offset();
        self.relocs.reloc_ebb(ofs, rel, ebb);
    }

    fn reloc_func(&mut self, rel: Reloc, func: FuncRef) {
        let ofs = self.offset();
        self.relocs.reloc_func(ofs, rel, func);
    }

    fn reloc_globalsym(&mut self, rel: Reloc, global: GlobalVar) {
        let ofs = self.offset();
        self.relocs.reloc_globalsym(ofs, rel, global);
    }

    fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) {
        let ofs = self.offset();
        self.relocs.reloc_jt(ofs, rel, jt);
    }
}
<commit_msg>Clean up copypasta.<commit_after>//! Code sink that writes binary machine code into contiguous memory.
//!
//! The `CodeSink` trait is the most general way of extracting binary machine code from Cretonne,
//! and it is implemented by things like the `test binemit` file test driver to generate
//! hexadecimal machine code. The `CodeSink` has some undesirable performance properties because of
//! the dual abstraction: `TargetIsa` is a trait object implemented by each supported ISA, so it
//! can't have any generic functions that could be specialized for each `CodeSink` implementation.
//! This results in many virtual function callbacks (one per `put*` call) when
//! `TargetIsa::emit_inst()` is used.
//!
//! The `MemoryCodeSink` type fixes the performance problem because it is a type known to
//! `TargetIsa` so it can specialize its machine code generation for the type. The trade-off is
//! that a `MemoryCodeSink` will always write binary machine code to raw memory. It forwards any
//! relocations to a `RelocSink` trait object. Relocations are less frequent than the
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.

use ir::{Ebb, FuncRef, GlobalVar, JumpTable};
use super::{CodeSink, CodeOffset, Reloc};
use std::ptr::write_unaligned;

/// A `CodeSink` that writes binary machine code directly into memory.
///
/// A `MemoryCodeSink` object should be used when emitting a Cretonne IL function into executable
/// memory. It writes machine code directly to a raw pointer without any bounds checking, so make
/// sure to allocate enough memory for the whole function. The number of bytes required is returned
/// by the `Context::compile()` function.
///
/// Any relocations in the function are forwarded to the `RelocSink` trait object.
///
/// Note that `MemoryCodeSink` writes multi-byte values in the native byte order of the host. This
/// is not the right thing to do for cross compilation.
pub struct MemoryCodeSink<'a> {
    data: *mut u8,
    offset: isize,
    relocs: &'a mut RelocSink,
}

impl<'a> MemoryCodeSink<'a> {
    /// Create a new memory code sink that writes a function to the memory pointed to by `data`.
    pub fn new(data: *mut u8, relocs: &mut RelocSink) -> MemoryCodeSink {
        MemoryCodeSink {
            data,
            offset: 0,
            relocs,
        }
    }
}

/// A trait for receiving relocations for code that is emitted directly into memory.
pub trait RelocSink {
    /// Add a relocation referencing an EBB at the current offset.
    fn reloc_ebb(&mut self, CodeOffset, Reloc, Ebb);

    /// Add a relocation referencing an external function at the current offset.
    fn reloc_func(&mut self, CodeOffset, Reloc, FuncRef);

    /// Add a relocation referencing an external global variable symbol at the
    /// current offset.
    fn reloc_globalsym(&mut self, CodeOffset, Reloc, GlobalVar);

    /// Add a relocation referencing a jump table.
    fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
}

impl<'a> CodeSink for MemoryCodeSink<'a> {
    fn offset(&self) -> CodeOffset {
        self.offset as CodeOffset
    }

    fn put1(&mut self, x: u8) {
        unsafe {
            write_unaligned(self.data.offset(self.offset), x);
        }
        self.offset += 1;
    }

    fn put2(&mut self, x: u16) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u16, x);
        }
        self.offset += 2;
    }

    fn put4(&mut self, x: u32) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u32, x);
        }
        self.offset += 4;
    }

    fn put8(&mut self, x: u64) {
        unsafe {
            write_unaligned(self.data.offset(self.offset) as *mut u64, x);
        }
        self.offset += 8;
    }

    fn reloc_ebb(&mut self, rel: Reloc, ebb: Ebb) {
        let ofs = self.offset();
        self.relocs.reloc_ebb(ofs, rel, ebb);
    }

    fn reloc_func(&mut self, rel: Reloc, func: FuncRef) {
        let ofs = self.offset();
        self.relocs.reloc_func(ofs, rel, func);
    }

    fn reloc_globalsym(&mut self, rel: Reloc, global: GlobalVar) {
        let ofs = self.offset();
        self.relocs.reloc_globalsym(ofs, rel, global);
    }

    fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) {
        let ofs = self.offset();
        self.relocs.reloc_jt(ofs, rel, jt);
    }
}
<|endoftext|>


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

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0154: r##"
Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.

Here is an example that demonstrates the error:

```
fn f() {
    // Variable declaration before import
    let x = 0;
    use std::io::Read;
    ...
}
```

The solution is to declare the imports at the top of the block, function, or
file.

Here is the previous example again, with the correct order:

```
fn f() {
    use std::io::Read;
    let x = 0;
    ...
}
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0251: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::*; // error, do `use foo::baz as quux` instead on the previous line

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0252: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::baz; // error, do `use bar::baz as quux` instead

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0253: r##"
Attempt was made to import an unimportable value. This can happen when
trying to import a method from a trait. An example of this error:

```
mod foo {
    pub trait MyTrait {
        fn do_something();
    }
}
use foo::MyTrait::do_something;
```

It's illegal to directly import methods belonging to a trait or concrete type.
"##,

E0255: r##"
You can't import a value whose name is the same as another value defined in the
module.

An example of this error:

```
use bar::foo; // error, do `use bar::foo as baz` instead

fn foo() {}

mod bar {
     pub fn foo() {}
}

fn main() {}
```
"##,

E0256: r##"
You can't import a type or module when the name of the item being imported is
the same as another type or submodule defined in the module.

An example of this error:

```
use foo::Bar; // error

type Bar = u32;

mod foo {
    pub mod Bar { }
}

fn main() {}
```
"##,

E0259: r##"
The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.

Wrong example:

```
extern crate a;
extern crate crate_a as a;
```

The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.

Correct example:

```
extern crate a;
extern crate crate_a as other_name;
```
"##,

E0260: r##"
The name for an item declaration conflicts with an external crate's name.

For instance,

```
extern crate abc;

struct abc;
```

There are two possible solutions:

Solution #1: Rename the item.

```
extern crate abc;

struct xyz;
```

Solution #2: Import the crate with a different name.

```
extern crate abc as xyz;

struct abc;
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0317: r##"
User-defined types or type parameters cannot shadow the primitive types.
This error indicates you tried to define a type, struct or enum with the same
name as an existing primitive type.

See the Types section of the reference for more information about the primitive
types:

http://doc.rust-lang.org/reference.html#types
"##,

E0364: r##"
Private items cannot be publicly re-exported.  This error indicates that
you attempted to `pub use` a type or value that was not itself public.

Here is an example that demonstrates the error:

```
mod foo {
    const X: u32 = 1;
}
pub use foo::X;
```

The solution to this problem is to ensure that the items that you are
re-exporting are themselves marked with `pub`:

```
mod foo {
    pub const X: u32 = 1;
}
pub use foo::X;
```

See the 'Use Declarations' section of the reference for more information
on this topic:

http://doc.rust-lang.org/reference.html#use-declarations
"##,

E0365: r##"
Private modules cannot be publicly re-exported.  This error indicates
that you attempted to `pub use` a module that was not itself public.

Here is an example that demonstrates the error:

```
mod foo {
    pub const X: u32 = 1;
}
pub use foo as foo2;

```
The solution to this problem is to ensure that the module that you are
re-exporting is itself marked with `pub`:

```
pub mod foo {
    pub const X: u32 = 1;
}
pub use foo as foo2;
```

See the 'Use Declarations' section of the reference for more information
on this topic:

http://doc.rust-lang.org/reference.html#use-declarations
"##,

E0403: r##"
Some type parameters have the same name. Example of erroneous code:

```
fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
                            //        parameter in this type parameter list
```

Please verify that none of the type parameterss are misspelled, and rename any
clashing parameters. Example:

```
fn foo<T, Y>(s: T, u: Y) {} // ok!
```
"##,

E0404: r##"
You tried to implement something which was not a trait on an object. Example of
erroneous code:

```
struct Foo;
struct Bar;

impl Foo for Bar {} // error: `Foo` is not a trait
```

Please verify that you didn't misspell the trait's name or otherwise use the
wrong identifier. Example:

```
trait Foo {
    // some functions
}
struct Bar;

impl Foo for Bar { // ok!
    // functions implementation
}
```
"##,

E0405: r##"
An unknown trait was implemented. Example of erroneous code:

```
struct Foo;

impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
```

Please verify that the name of the trait wasn't misspelled and ensure that it
was imported. Example:

```
// solution 1:
use some_file::SomeTrait;

// solution 2:
trait SomeTrait {
    // some functions
}

struct Foo;

impl SomeTrait for Foo { // ok!
    // implements functions
}
```
"##,

E0407: r##"
A definition of a method not in the implemented trait was given in a trait
implementation. Example of erroneous code:

```
trait Foo {
    fn a();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
    fn b() {} // error: method `b` is not a member of trait `Foo`
}
```

Please verify you didn't misspell the method name and you used the correct
trait. First example:

```
trait Foo {
    fn a();
    fn b();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
    fn b() {} // ok!
}
```

Second example:

```
trait Foo {
    fn a();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
}

impl Bar {
    fn b() {}
}
```
"##,

E0417: r##"
A static variable was referenced in a pattern. Example of erroneous code:

```
static FOO : i32 = 0;

match 0 {
    FOO => {} // error: static variables cannot be referenced in a
              //        pattern, use a `const` instead
    _ => {}
}
```

The compiler needs to know the value of the pattern at compile time,
which is not possible with a `static` variable. Please verify that the
variable is spelled correctly and if so, try to use a `const` instead.
Example:

```
const FOO : i32 = 0;

match 0 {
    FOO => {} // ok!
    _ => {}
}
```
"##,

E0424: r##"
The `self` keyword was used in a static method. Example of erroneous code:

```
struct Foo;

impl Foo {
    fn bar(self) {}

    fn foo() {
        self.bar(); // error: `self` is not available in a static method.
    }
}
```

Please check if the method's argument list should have contained self,
&self, or &mut self (in case you didn't want to create a static method),
and add it if so. Example:

```
struct Foo;

impl Foo {
    fn bar(self) {}

    fn foo(self) {
        self.bar(); // ok!
    }
}
```
"##,

E0428: r##"
A type or module has been defined more than once. Example of erroneous
code:

```
struct Bar;
struct Bar; // error: duplicate definition of value `Bar`
```

Please verify you didn't misspell the type/module's name or remove/rename the
duplicated one. Example:

```
struct Bar;
struct Bar2; // ok!
```
"##,

E0433: r##"
Invalid import. Example of erroneous code:

```
use something_which_doesnt_exist;
// error: unresolved import `something_which_doesnt_exist`
```

Please verify you didn't misspell the import's name.
"##,

}

register_diagnostics! {
    E0153, // called no where
    E0157, // called from no where
    E0254, // import conflicts with imported crate in this module
    E0257,
    E0258,
    E0401, // can't use type parameters from outer function
    E0402, // cannot use an outer type parameter in this context
    E0406, // undeclared associated type
    E0408, // variable from pattern #1 is not bound in pattern #
    E0409, // variable is bound with different mode in pattern # than in
           // pattern #1
    E0410, // variable from pattern is not bound in pattern 1
    E0411, // use of `Self` outside of an impl or trait
    E0412, // use of undeclared
    E0413, // declaration of shadows an enum variant or unit-like struct in
           // scope
    E0414, // only irrefutable patterns allowed here
    E0415, // identifier is bound more than once in this parameter list
    E0416, // identifier is bound more than once in the same pattern
    E0418, // is not an enum variant, struct or const
    E0419, // unresolved enum variant, struct or const
    E0420, // is not an associated const
    E0421, // unresolved associated const
    E0422, // does not name a structure
    E0423, // is a struct variant name, but this expression uses it like a
           // function name
    E0425, // unresolved name
    E0426, // use of undeclared label
    E0427, // cannot use `ref` binding mode with ...
    E0429, // `self` imports are only allowed within a { } list
    E0430, // `self` import can only appear once in the list
    E0431, // `self` import can only appear in an import list with a non-empty
           // prefix
    E0432, // unresolved import
    E0434, // can't capture dynamic environment in a fn item
    E0435, // attempt to use a non-constant value in a constant
    E0437, // type is not a member of trait
    E0438, // const is not a member of trait
}
<commit_msg>Improve error explanation<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0154: r##"
Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.

Here is an example that demonstrates the error:

```
fn f() {
    // Variable declaration before import
    let x = 0;
    use std::io::Read;
    ...
}
```

The solution is to declare the imports at the top of the block, function, or
file.

Here is the previous example again, with the correct order:

```
fn f() {
    use std::io::Read;
    let x = 0;
    ...
}
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0251: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::*; // error, do `use foo::baz as quux` instead on the previous line

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0252: r##"
Two items of the same name cannot be imported without rebinding one of the
items under a new local name.

An example of this error:

```
use foo::baz;
use bar::baz; // error, do `use bar::baz as quux` instead

fn main() {}

mod foo {
    pub struct baz;
}

mod bar {
    pub mod baz {}
}
```
"##,

E0253: r##"
Attempt was made to import an unimportable value. This can happen when
trying to import a method from a trait. An example of this error:

```
mod foo {
    pub trait MyTrait {
        fn do_something();
    }
}
use foo::MyTrait::do_something;
```

It's illegal to directly import methods belonging to a trait or concrete type.
"##,

E0255: r##"
You can't import a value whose name is the same as another value defined in the
module.

An example of this error:

```
use bar::foo; // error, do `use bar::foo as baz` instead

fn foo() {}

mod bar {
     pub fn foo() {}
}

fn main() {}
```
"##,

E0256: r##"
You can't import a type or module when the name of the item being imported is
the same as another type or submodule defined in the module.

An example of this error:

```
use foo::Bar; // error

type Bar = u32;

mod foo {
    pub mod Bar { }
}

fn main() {}
```
"##,

E0259: r##"
The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.

Wrong example:

```
extern crate a;
extern crate crate_a as a;
```

The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.

Correct example:

```
extern crate a;
extern crate crate_a as other_name;
```
"##,

E0260: r##"
The name for an item declaration conflicts with an external crate's name.

For instance,

```
extern crate abc;

struct abc;
```

There are two possible solutions:

Solution #1: Rename the item.

```
extern crate abc;

struct xyz;
```

Solution #2: Import the crate with a different name.

```
extern crate abc as xyz;

struct abc;
```

See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:

http://doc.rust-lang.org/reference.html#statements
"##,

E0317: r##"
User-defined types or type parameters cannot shadow the primitive types.
This error indicates you tried to define a type, struct or enum with the same
name as an existing primitive type.

See the Types section of the reference for more information about the primitive
types:

http://doc.rust-lang.org/reference.html#types
"##,

E0364: r##"
Private items cannot be publicly re-exported.  This error indicates that
you attempted to `pub use` a type or value that was not itself public.

Here is an example that demonstrates the error:

```
mod foo {
    const X: u32 = 1;
}
pub use foo::X;
```

The solution to this problem is to ensure that the items that you are
re-exporting are themselves marked with `pub`:

```
mod foo {
    pub const X: u32 = 1;
}
pub use foo::X;
```

See the 'Use Declarations' section of the reference for more information
on this topic:

http://doc.rust-lang.org/reference.html#use-declarations
"##,

E0365: r##"
Private modules cannot be publicly re-exported.  This error indicates
that you attempted to `pub use` a module that was not itself public.

Here is an example that demonstrates the error:

```
mod foo {
    pub const X: u32 = 1;
}
pub use foo as foo2;

```
The solution to this problem is to ensure that the module that you are
re-exporting is itself marked with `pub`:

```
pub mod foo {
    pub const X: u32 = 1;
}
pub use foo as foo2;
```

See the 'Use Declarations' section of the reference for more information
on this topic:

http://doc.rust-lang.org/reference.html#use-declarations
"##,

E0403: r##"
Some type parameters have the same name. Example of erroneous code:

```
fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
                            //        parameter in this type parameter list
```

Please verify that none of the type parameterss are misspelled, and rename any
clashing parameters. Example:

```
fn foo<T, Y>(s: T, u: Y) {} // ok!
```
"##,

E0404: r##"
You tried to implement something which was not a trait on an object. Example of
erroneous code:

```
struct Foo;
struct Bar;

impl Foo for Bar {} // error: `Foo` is not a trait
```

Please verify that you didn't misspell the trait's name or otherwise use the
wrong identifier. Example:

```
trait Foo {
    // some functions
}
struct Bar;

impl Foo for Bar { // ok!
    // functions implementation
}
```
"##,

E0405: r##"
An unknown trait was implemented. Example of erroneous code:

```
struct Foo;

impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
```

Please verify that the name of the trait wasn't misspelled and ensure that it
was imported. Example:

```
// solution 1:
use some_file::SomeTrait;

// solution 2:
trait SomeTrait {
    // some functions
}

struct Foo;

impl SomeTrait for Foo { // ok!
    // implements functions
}
```
"##,

E0407: r##"
A definition of a method not in the implemented trait was given in a trait
implementation. Example of erroneous code:

```
trait Foo {
    fn a();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
    fn b() {} // error: method `b` is not a member of trait `Foo`
}
```

Please verify you didn't misspell the method name and you used the correct
trait. First example:

```
trait Foo {
    fn a();
    fn b();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
    fn b() {} // ok!
}
```

Second example:

```
trait Foo {
    fn a();
}

struct Bar;

impl Foo for Bar {
    fn a() {}
}

impl Bar {
    fn b() {}
}
```
"##,

E0417: r##"
A static variable was referenced in a pattern. Example of erroneous code:

```
static FOO : i32 = 0;

match 0 {
    FOO => {} // error: static variables cannot be referenced in a
              //        pattern, use a `const` instead
    _ => {}
}
```

The compiler needs to know the value of the pattern at compile time;
compile-time patterns can defined via const or enum items. Please verify
that the identifier is spelled correctly, and if so, use a const instead
of static to define it. Example:

```
const FOO : i32 = 0;

match 0 {
    FOO => {} // ok!
    _ => {}
}
```
"##,

E0424: r##"
The `self` keyword was used in a static method. Example of erroneous code:

```
struct Foo;

impl Foo {
    fn bar(self) {}

    fn foo() {
        self.bar(); // error: `self` is not available in a static method.
    }
}
```

Please check if the method's argument list should have contained self,
&self, or &mut self (in case you didn't want to create a static method),
and add it if so. Example:

```
struct Foo;

impl Foo {
    fn bar(self) {}

    fn foo(self) {
        self.bar(); // ok!
    }
}
```
"##,

E0428: r##"
A type or module has been defined more than once. Example of erroneous
code:

```
struct Bar;
struct Bar; // error: duplicate definition of value `Bar`
```

Please verify you didn't misspell the type/module's name or remove/rename the
duplicated one. Example:

```
struct Bar;
struct Bar2; // ok!
```
"##,

E0433: r##"
Invalid import. Example of erroneous code:

```
use something_which_doesnt_exist;
// error: unresolved import `something_which_doesnt_exist`
```

Please verify you didn't misspell the import's name.
"##,

}

register_diagnostics! {
    E0153, // called no where
    E0157, // called from no where
    E0254, // import conflicts with imported crate in this module
    E0257,
    E0258,
    E0401, // can't use type parameters from outer function
    E0402, // cannot use an outer type parameter in this context
    E0406, // undeclared associated type
    E0408, // variable from pattern #1 is not bound in pattern #
    E0409, // variable is bound with different mode in pattern # than in
           // pattern #1
    E0410, // variable from pattern is not bound in pattern 1
    E0411, // use of `Self` outside of an impl or trait
    E0412, // use of undeclared
    E0413, // declaration of shadows an enum variant or unit-like struct in
           // scope
    E0414, // only irrefutable patterns allowed here
    E0415, // identifier is bound more than once in this parameter list
    E0416, // identifier is bound more than once in the same pattern
    E0418, // is not an enum variant, struct or const
    E0419, // unresolved enum variant, struct or const
    E0420, // is not an associated const
    E0421, // unresolved associated const
    E0422, // does not name a structure
    E0423, // is a struct variant name, but this expression uses it like a
           // function name
    E0425, // unresolved name
    E0426, // use of undeclared label
    E0427, // cannot use `ref` binding mode with ...
    E0429, // `self` imports are only allowed within a { } list
    E0430, // `self` import can only appear once in the list
    E0431, // `self` import can only appear in an import list with a non-empty
           // prefix
    E0432, // unresolved import
    E0434, // can't capture dynamic environment in a fn item
    E0435, // attempt to use a non-constant value in a constant
    E0437, // type is not a member of trait
    E0438, // const is not a member of trait
}
<|endoftext|>


<commit_before>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Pick a pivot: Pick the middle element by skipping half the length and keeping just one.
        // let it_pivot = array.iter().skip(n / 2).take(1);
        // Take the first element as the pivot.
        // let it_pivot = array.iter().take(1);
        //
        // for it in it_pivot {
        //     println!("  0. it: {:?}", it);
        // }

        // Loop over array, finding smaller elements than the pivot.
        // for it in array.iter().skip(1) {
        //     //println!("  1. it: {:?}", it);
        //     if it < it_pivot {
        //         println!("  1. it: {:?} smaller than pivot!", it);
        //     }
        // }
        // array.swap(0,1);

        // array.iter().enumerate().map(|(i,x)| {});

        // // Take the first element as pivot.
        // let a = array.iter_mut().skip(1).enumerate().fold(
        //     (0, array[0]), |acc, item| {
        //         if acc.1 > item.1 {
        //             // Element is smaller than pivot; swap them!
        //             array.swap(acc.0, item.0);
        //             // Return the accumulator as being the new index of pivot (which is now at
        //             // at the location of the fold()) with the pivot value which shouldn't change.
        //             (item.0, acc.1)
        //         } else {
        //             // Nothing to do as element is larger than pivot. Just return new accumulator.
        //             (acc.0, acc.1)
        //         }
        //     }
        // );

        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<commit_msg>Cleanups<commit_after>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<|endoftext|>


<commit_before>#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
extern crate clap;
#[macro_use] extern crate semver;
extern crate toml;
extern crate url;
#[macro_use] extern crate version;

extern crate libimagentrylink;
extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;

use std::process::exit;
use std::ops::Deref;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagstore::error::StoreError;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagerror::trace::{trace_error, trace_error_exit};
use libimagentrylink::external::ExternalLinker;
use clap::ArgMatches;
use url::Url;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-link",
                                    &version!()[..],
                                    "Link entries",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            match name {
                "internal" => handle_internal_linking(&rt),
                "external" => handle_external_linking(&rt),
                _ => {
                    warn!("No commandline call");
                    exit(1);
                },
            }
        });
}

fn handle_internal_linking(rt: &Runtime) {
    use libimagentrylink::internal::InternalLinker;

    debug!("Handle internal linking call");
    let cmd = rt.cli().subcommand_matches("internal").unwrap();

    if cmd.is_present("list") {
        debug!("List...");
        for entry in cmd.value_of("list").unwrap().split(',') {
            debug!("Listing for '{}'", entry);
            match get_entry_by_name(rt, entry) {
                Ok(e) => {
                    e.get_internal_links()
                        .map(|links| {
                            for (i, link) in links.iter().map(|l| l.to_str()).filter_map(|x| x).enumerate() {
                                println!("{: <3}: {}", i, link);
                            }
                        })
                        .map_err(|e| trace_error(&e))
                        .ok();
                },

                Err(e) => {
                    trace_error(&e);
                    break;
                },
            }
        }
        debug!("Listing ready!");
    } else {
        let mut from = {
            let from = get_from_entry(&rt);
            if from.is_none() {
                warn!("No 'from' entry");
                exit(1);
            }
            from.unwrap()
        };
        debug!("Link from = {:?}", from.deref());

        let to = {
            let to = get_to_entries(&rt);
            if to.is_none() {
                warn!("No 'to' entry");
                exit(1);
            }
            to.unwrap()
        };
        debug!("Link to = {:?}", to.iter().map(|f| f.deref()).collect::<Vec<&Entry>>());

        match cmd.subcommand_name() {
            Some("add") => {
                for mut to_entry in to {
                    if let Err(e) = to_entry.add_internal_link(&mut from) {
                        trace_error_exit(&e, 1);
                    }
                }
            },

            Some("remove") => {
                for mut to_entry in to {
                    if let Err(e) = to_entry.remove_internal_link(&mut from) {
                        trace_error_exit(&e, 1);
                    }
                }
            },

            _ => unreachable!(),
        };
    }
}

fn get_from_entry<'a>(rt: &'a Runtime) -> Option<FileLockEntry<'a>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .value_of("from")
        .and_then(|from_name| {
            match get_entry_by_name(rt, from_name) {
                Err(e) => {
                    debug!("We couldn't get the entry from name: '{:?}'", from_name);
                    trace_error(&e); None
                },
                Ok(e) => Some(e),
            }

        })
}

fn get_to_entries<'a>(rt: &'a Runtime) -> Option<Vec<FileLockEntry<'a>>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .values_of("to")
        .map(|values| {
            let mut v = vec![];
            for entry in values.map(|v| get_entry_by_name(rt, v)) {
                match entry {
                    Err(e) => trace_error(&e),
                    Ok(e) => v.push(e),
                }
            }
            v
        })
}

fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<FileLockEntry<'a>, StoreError> {
    use libimagstore::storeid::build_entry_path;
    build_entry_path(rt.store(), name)
        .and_then(|path| rt.store().retrieve(path))
}

fn handle_external_linking(rt: &Runtime) {
    let scmd       = rt.cli().subcommand_matches("external").unwrap();
    let entry_name = scmd.value_of("id").unwrap(); // enforced by clap
    let entry      = get_entry_by_name(rt, entry_name);
    if entry.is_err() {
        trace_error_exit(&entry.unwrap_err(), 1);
    }
    let mut entry = entry.unwrap();

    if scmd.is_present("add") {
        debug!("Adding link to entry!");
        add_link_to_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("remove") {
        debug!("Removing link from entry!");
        remove_link_from_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("set") {
        debug!("Setting links in entry!");
        set_links_for_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("list") {
        debug!("Listing links in entry!");
        list_links_for_entry(rt.store(), &mut entry);
        return;
    }

    panic!("Clap failed to enforce one of 'add', 'remove', 'set' or 'list'");
}

fn add_link_to_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let link = matches.value_of("add").unwrap();

    let link = Url::parse(link);
    if link.is_err() {
        debug!("URL parsing error...");
        trace_error_exit(&link.unwrap_err(), 1);
    }
    let link = link.unwrap();

    if let Err(e) = entry.add_external_link(store, link) {
        debug!("Error while adding external link...");
        trace_error(&e);
    } else {
        debug!("Everything worked well");
        info!("Ok");
    }
}

fn remove_link_from_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let link = matches.value_of("remove").unwrap();

    let link = Url::parse(link);
    if link.is_err() {
        trace_error_exit(&link.unwrap_err(), 1);
    }
    let link = link.unwrap();

    if let Err(e) = entry.remove_external_link(store, link) {
        trace_error(&e);
    } else {
        info!("Ok");
    }
}

fn set_links_for_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let links = matches
        .value_of("links")
        .map(String::from)
        .unwrap()
        .split(',')
        .map(|uri| {
            match Url::parse(uri) {
                Err(e) => {
                    warn!("Could not parse '{}' as URL, ignoring", uri);
                    trace_error(&e);
                    None
                },
                Ok(u) => Some(u),
            }
        })
        .filter_map(|x| x)
        .collect();

    if let Err(e) = entry.set_external_links(store, links) {
        trace_error(&e);
    } else {
        info!("Ok");
    }
}

fn list_links_for_entry(store: &Store, entry: &mut FileLockEntry) {
    let res = entry.get_external_links(store)
        .and_then(|links| {
            for (i, link) in links.iter().enumerate() {
                println!("{: <3}: {}", i, link);
            }
            Ok(())
        });

    match res {
        Err(e) => {
            trace_error(&e);
        },
        Ok(_) => {
            info!("Ok");
        },
    }
}

<commit_msg>Fix imga-link::main::* for new StoreId interface<commit_after>#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
extern crate clap;
#[macro_use] extern crate semver;
extern crate toml;
extern crate url;
#[macro_use] extern crate version;

extern crate libimagentrylink;
extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;

use std::process::exit;
use std::ops::Deref;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagstore::error::StoreError;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagerror::trace::{trace_error, trace_error_exit};
use libimagentrylink::external::ExternalLinker;
use clap::ArgMatches;
use url::Url;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-link",
                                    &version!()[..],
                                    "Link entries",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            match name {
                "internal" => handle_internal_linking(&rt),
                "external" => handle_external_linking(&rt),
                _ => {
                    warn!("No commandline call");
                    exit(1);
                },
            }
        });
}

fn handle_internal_linking(rt: &Runtime) {
    use libimagentrylink::internal::InternalLinker;

    debug!("Handle internal linking call");
    let cmd = rt.cli().subcommand_matches("internal").unwrap();

    if cmd.is_present("list") {
        debug!("List...");
        for entry in cmd.value_of("list").unwrap().split(',') {
            debug!("Listing for '{}'", entry);
            match get_entry_by_name(rt, entry) {
                Ok(Some(e)) => {
                    e.get_internal_links()
                        .map(|links| {
                            for (i, link) in links.iter().map(|l| l.to_str().ok()).filter_map(|x| x).enumerate() {
                                println!("{: <3}: {}", i, link);
                            }
                        })
                        .map_err(|e| trace_error(&e))
                        .ok();
                },

                Ok(None) => {
                    warn!("Entry not found: {:?}", entry);
                    break;
                }

                Err(e) => {
                    trace_error(&e);
                    break;
                },
            }
        }
        debug!("Listing ready!");
    } else {
        let mut from = {
            let from = get_from_entry(&rt);
            if from.is_none() {
                warn!("No 'from' entry");
                exit(1);
            }
            from.unwrap()
        };
        debug!("Link from = {:?}", from.deref());

        let to = {
            let to = get_to_entries(&rt);
            if to.is_none() {
                warn!("No 'to' entry");
                exit(1);
            }
            to.unwrap()
        };
        debug!("Link to = {:?}", to.iter().map(|f| f.deref()).collect::<Vec<&Entry>>());

        match cmd.subcommand_name() {
            Some("add") => {
                for mut to_entry in to {
                    if let Err(e) = to_entry.add_internal_link(&mut from) {
                        trace_error_exit(&e, 1);
                    }
                }
            },

            Some("remove") => {
                for mut to_entry in to {
                    if let Err(e) = to_entry.remove_internal_link(&mut from) {
                        trace_error_exit(&e, 1);
                    }
                }
            },

            _ => unreachable!(),
        };
    }
}

fn get_from_entry<'a>(rt: &'a Runtime) -> Option<FileLockEntry<'a>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .value_of("from")
        .and_then(|from_name| {
            match get_entry_by_name(rt, from_name) {
                Err(e) => {
                    debug!("We couldn't get the entry from name: '{:?}'", from_name);
                    trace_error(&e); None
                },
                Ok(Some(e)) => Some(e),
                Ok(None)    => None,
            }

        })
}

fn get_to_entries<'a>(rt: &'a Runtime) -> Option<Vec<FileLockEntry<'a>>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .values_of("to")
        .map(|values| {
            let mut v = vec![];
            for entry in values.map(|v| get_entry_by_name(rt, v)) {
                match entry {
                    Err(e) => trace_error(&e),
                    Ok(Some(e)) => v.push(e),
                    Ok(None) => warn!("Entry not found: {:?}", v),
                }
            }
            v
        })
}

fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<Option<FileLockEntry<'a>>, StoreError> {
    use std::path::PathBuf;
    use libimagstore::storeid::StoreId;

    StoreId::new(Some(rt.store().path().clone()), PathBuf::from(name))
        .and_then(|id| rt.store().get(id))
}

fn handle_external_linking(rt: &Runtime) {
    let scmd       = rt.cli().subcommand_matches("external").unwrap();
    let entry_name = scmd.value_of("id").unwrap(); // enforced by clap
    let entry      = get_entry_by_name(rt, entry_name);
    if entry.is_err() {
        trace_error_exit(&entry.unwrap_err(), 1);
    }
    let entry = entry.unwrap();
    if entry.is_none() {
        warn!("Entry nt found: {:?}", entry_name);
        return;
    }
    let mut entry = entry.unwrap();

    if scmd.is_present("add") {
        debug!("Adding link to entry!");
        add_link_to_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("remove") {
        debug!("Removing link from entry!");
        remove_link_from_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("set") {
        debug!("Setting links in entry!");
        set_links_for_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("list") {
        debug!("Listing links in entry!");
        list_links_for_entry(rt.store(), &mut entry);
        return;
    }

    panic!("Clap failed to enforce one of 'add', 'remove', 'set' or 'list'");
}

fn add_link_to_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let link = matches.value_of("add").unwrap();

    let link = Url::parse(link);
    if link.is_err() {
        debug!("URL parsing error...");
        trace_error_exit(&link.unwrap_err(), 1);
    }
    let link = link.unwrap();

    if let Err(e) = entry.add_external_link(store, link) {
        debug!("Error while adding external link...");
        trace_error(&e);
    } else {
        debug!("Everything worked well");
        info!("Ok");
    }
}

fn remove_link_from_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let link = matches.value_of("remove").unwrap();

    let link = Url::parse(link);
    if link.is_err() {
        trace_error_exit(&link.unwrap_err(), 1);
    }
    let link = link.unwrap();

    if let Err(e) = entry.remove_external_link(store, link) {
        trace_error(&e);
    } else {
        info!("Ok");
    }
}

fn set_links_for_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let links = matches
        .value_of("links")
        .map(String::from)
        .unwrap()
        .split(',')
        .map(|uri| {
            match Url::parse(uri) {
                Err(e) => {
                    warn!("Could not parse '{}' as URL, ignoring", uri);
                    trace_error(&e);
                    None
                },
                Ok(u) => Some(u),
            }
        })
        .filter_map(|x| x)
        .collect();

    if let Err(e) = entry.set_external_links(store, links) {
        trace_error(&e);
    } else {
        info!("Ok");
    }
}

fn list_links_for_entry(store: &Store, entry: &mut FileLockEntry) {
    let res = entry.get_external_links(store)
        .and_then(|links| {
            for (i, link) in links.iter().enumerate() {
                println!("{: <3}: {}", i, link);
            }
            Ok(())
        });

    match res {
        Err(e) => {
            trace_error(&e);
        },
        Ok(_) => {
            info!("Ok");
        },
    }
}

<|endoftext|>


<commit_before>//! Netherrack-specific reading I/O operations

use io_operations::reader::Reader;

extern crate varint;

extern crate bit_utils;
use self::bit_utils::BitInformation;

pub trait NetherrackReader : Reader {

    /// Reads an unsigned 32-bit Varint from this NetherrackReader
    fn read_unsigned_varint_32(&mut self) -> Result<u32, &'static str> {

        // The number of bits to shift by. <<0, <<7, <<14, etc
        let mut shift_amount: u32 = 0;

        // The decoded value
        let mut decoded_value: u32 = 0;

        loop {

            let byte_value = self.read_unsigned_byte();

            if byte_value.is_err() {
                return Err("Byte in read_unsigned_varint_32 returned an error");
            } else {
                let byte_value: u8 = byte_value.unwrap();

                decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount;

                // See if we're supposed to keep reading
                if byte_value.has_most_signifigant_bit() {
                    shift_amount += 7;
                } else {
                    return Ok(decoded_value);
                }
            }

        }

    }

}

impl NetherrackReader for ::std::io::Cursor<Vec<u8>> { }
impl NetherrackReader for ::std::net::TcpStream { }
<commit_msg>Use matching while reading an unsigned byte instead of an if/else<commit_after>//! Netherrack-specific reading I/O operations

use io_operations::reader::Reader;

extern crate varint;

extern crate bit_utils;
use self::bit_utils::BitInformation;

pub trait NetherrackReader : Reader {

    /// Reads an unsigned 32-bit Varint from this NetherrackReader
    fn read_unsigned_varint_32(&mut self) -> Result<u32, &'static str> {

        // The number of bits to shift by. <<0, <<7, <<14, etc
        let mut shift_amount: u32 = 0;

        // The decoded value
        let mut decoded_value: u32 = 0;

        loop {

            match self.read_unsigned_byte() {
                Err(error) => {
                    error!("Got an error while reading a byte for an unsigned varint32: {}", error);
                    return Err("Could not read an unsigned byte for an unsigned varint32");
                }

                Ok(byte_value) => {
                    decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount;

                    // See if we're supposed to keep reading
                    if byte_value.has_most_signifigant_bit() {
                        shift_amount += 7;
                    } else {
                        return Ok(decoded_value);
                    }
                }
            }

        }

    }

}

impl NetherrackReader for ::std::io::Cursor<Vec<u8>> { }
impl NetherrackReader for ::std::net::TcpStream { }
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate languageserver_types;
#[macro_use]
extern crate log;
extern crate simple_logging;
extern crate url;
extern crate syntax;
extern crate errors;

mod transport;
mod jsonrpc;

use std::cell::RefCell;
use std::io;
use std::io::{BufRead, Write};
use std::ops::DerefMut;
use languageserver_types as lst;
use url::Url;
use jsonrpc::{RpcHandler, Response};
use transport::Transport;

fn main() {
    simple_logging::log_to_stderr(log::LogLevelFilter::Trace)
        .expect("failed to initialize logging");

    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let stdout = stdout.lock();

    let transport = RefCell::new(Transport::new(stdin, stdout));
    let mut rpc = RpcHandler::new();

    rpc.add_method("initialize", |_: lst::InitializeParams| {
        Response::Success::<_, ()>(lst::InitializeResult {
            capabilities: lst::ServerCapabilities {
                text_document_sync: Some(lst::TextDocumentSyncKind::Full),
                .. Default::default()
            },
        })
    });

    rpc.add_notification("initialized", |_: serde_json::Value| {
    });

    rpc.add_notification("textDocument/didOpen", |params: lst::DidOpenTextDocumentParams| {
        publish_diagnostics(
            &params.text_document.text,
            params.text_document.uri,
            transport.borrow_mut().deref_mut(),
        );
    });

    rpc.add_notification("textDocument/didSave", |_: lst::DidSaveTextDocumentParams| {
    });

    rpc.add_notification("textDocument/didClose", |_: lst::DidCloseTextDocumentParams| {
    });

    rpc.add_notification("textDocument/didChange", |params: lst::DidChangeTextDocumentParams| {
        if params.content_changes.len() != 1 ||
            params.content_changes[0].range.is_some() ||
            params.content_changes[0].range_length.is_some()
        {
            debug!("got bad edit with `didChange` event");
        } else {
            publish_diagnostics(
                &params.content_changes[0].text,
                params.text_document.uri,
                transport.borrow_mut().deref_mut(),
            );
        }
    });

    loop {
        let response = {
            let msg = transport
                .borrow_mut()
                .read_message()
                .expect("failed to read message");
            rpc.handle_call(&msg)
        };
        if let Some(response) = response {
            transport
                .borrow_mut()
                .send_message(&response)
                .expect("failed to send");
        }
    }
}

fn publish_diagnostics<R, W>(source: &str, doc: Url, transport: &mut Transport<R, W>)
    where R: BufRead, W: Write
{
    let diagnostics = make_diagnostics(source);
    let params = lst::PublishDiagnosticsParams {
        uri: doc,
        diagnostics,
    };
    #[derive(Serialize)]
    struct Notification {
        jsonrpc: &'static str,
        method: &'static str,
        params: lst::PublishDiagnosticsParams,
    }

    let notification = Notification {
        jsonrpc: "2.0",
        method: "textDocument/publishDiagnostics",
        params,
    };
    let string = serde_json::to_string(&notification)
        .expect("failed to serialize diagnostics");
    transport.send_message(&string).expect("failed to write message");
}

fn make_diagnostics(source: &str) -> Vec<lst::Diagnostic> {
    let reporter = errors::Reporter::new();
    let tokens = syntax::lex(source, reporter.clone());
    let _ = syntax::parse(tokens, reporter.clone());
    reporter
        .get_diagnostics()
        .into_iter()
        .map(|d| note_to_diagnostic(&d.notes[0], d.message))
        .collect()
}

fn note_to_diagnostic(note: &errors::reporter::Note, msg: String) -> lst::Diagnostic {
    fn convert_pos(pos: errors::position::Position) -> lst::Position {
        lst::Position {
            line: (pos.line - 1) as u64,
            character: (pos.column - 1) as u64,
        }
    }
    fn convert_range(range: errors::position::Span) -> lst::Range {
        lst::Range {
            start: convert_pos(range.start),
            end: convert_pos(range.end),
        }
    }
    lst::Diagnostic {
        range: convert_range(note.span),
        severity: Some(lst::DiagnosticSeverity::Error),
        code: None,
        source: Some("plank".into()),
        message: msg,
    }
}
<commit_msg>make lang-server give a bit more accurate diagnotics<commit_after>#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate languageserver_types;
#[macro_use]
extern crate log;
extern crate simple_logging;
extern crate url;
extern crate syntax;
extern crate errors;

mod transport;
mod jsonrpc;

use std::cell::RefCell;
use std::io;
use std::io::{BufRead, Write};
use std::ops::DerefMut;
use languageserver_types as lst;
use url::Url;
use jsonrpc::{RpcHandler, Response};
use transport::Transport;

fn main() {
    simple_logging::log_to_stderr(log::LogLevelFilter::Trace)
        .expect("failed to initialize logging");

    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let stdout = stdout.lock();

    let transport = RefCell::new(Transport::new(stdin, stdout));
    let mut rpc = RpcHandler::new();

    rpc.add_method("initialize", |_: lst::InitializeParams| {
        Response::Success::<_, ()>(lst::InitializeResult {
            capabilities: lst::ServerCapabilities {
                text_document_sync: Some(lst::TextDocumentSyncKind::Full),
                .. Default::default()
            },
        })
    });

    rpc.add_notification("initialized", |_: serde_json::Value| {
    });

    rpc.add_notification("textDocument/didOpen", |params: lst::DidOpenTextDocumentParams| {
        publish_diagnostics(
            &params.text_document.text,
            params.text_document.uri,
            transport.borrow_mut().deref_mut(),
        );
    });

    rpc.add_notification("textDocument/didSave", |_: lst::DidSaveTextDocumentParams| {
    });

    rpc.add_notification("textDocument/didClose", |_: lst::DidCloseTextDocumentParams| {
    });

    rpc.add_notification("textDocument/didChange", |params: lst::DidChangeTextDocumentParams| {
        if params.content_changes.len() != 1 ||
            params.content_changes[0].range.is_some() ||
            params.content_changes[0].range_length.is_some()
        {
            debug!("got bad edit with `didChange` event");
        } else {
            publish_diagnostics(
                &params.content_changes[0].text,
                params.text_document.uri,
                transport.borrow_mut().deref_mut(),
            );
        }
    });

    loop {
        let response = {
            let msg = transport
                .borrow_mut()
                .read_message()
                .expect("failed to read message");
            rpc.handle_call(&msg)
        };
        if let Some(response) = response {
            transport
                .borrow_mut()
                .send_message(&response)
                .expect("failed to send");
        }
    }
}

fn publish_diagnostics<R, W>(source: &str, doc: Url, transport: &mut Transport<R, W>)
    where R: BufRead, W: Write
{
    let diagnostics = make_diagnostics(source);
    let params = lst::PublishDiagnosticsParams {
        uri: doc,
        diagnostics,
    };
    #[derive(Serialize)]
    struct Notification {
        jsonrpc: &'static str,
        method: &'static str,
        params: lst::PublishDiagnosticsParams,
    }

    let notification = Notification {
        jsonrpc: "2.0",
        method: "textDocument/publishDiagnostics",
        params,
    };
    let string = serde_json::to_string(&notification)
        .expect("failed to serialize diagnostics");
    transport.send_message(&string).expect("failed to write message");
}

fn make_diagnostics(source: &str) -> Vec<lst::Diagnostic> {
    let reporter = errors::Reporter::new();
    let tokens = syntax::lex(source, reporter.clone());
    let _ = syntax::parse(tokens, reporter.clone());
    reporter
        .get_diagnostics()
        .into_iter()
        .filter_map(convert_diagnostic)
        .collect()
}

fn convert_diagnostic(d: errors::reporter::Diagnostic) -> Option<lst::Diagnostic> {
    fn convert_pos(pos: errors::position::Position) -> lst::Position {
        lst::Position {
            line: (pos.line - 1) as u64,
            character: (pos.column - 1) as u64,
        }
    }
    fn convert_range(range: errors::position::Span) -> lst::Range {
        lst::Range {
            start: convert_pos(range.start),
            end: convert_pos(range.end),
        }
    }
    let primary_span = match d.primary_span {
        Some(span) => span,
        None => return None,
    };
    let severity = match d.severity {
        errors::reporter::Severity::Error => lst::DiagnosticSeverity::Error,
        errors::reporter::Severity::Warning => lst::DiagnosticSeverity::Warning,
    };
    Some(lst::Diagnostic {
        range: convert_range(primary_span),
        severity: Some(severity),
        code: None,
        source: Some("plank".into()),
        message: d.message,
    })
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())
     .env_remove("RUSTC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<commit_msg>Auto merge of #3930 - alexcrichton:more-clean, r=alexcrichton<commit_after>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())
     .env_remove("__CARGO_DEFAULT_LIB_METADATA")
     .env_remove("RUSTC")
     .env_remove("RUSTDOC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<|endoftext|>