<commit_before>// Copyright 2016 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! {

E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.

For example:

```compile_fail,E0178
trait Foo {}

struct Bar<'a> {
    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```

More details can be found in [RFC 438].

[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,

E0536: r##"
The `not` cfg-predicate was malformed.

Erroneous code example:

```compile_fail,E0536
#[cfg(not())] // error: expected 1 cfg-pattern
pub fn something() {}

pub fn main() {}
```

The `not` predicate expects one cfg-pattern. Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0537: r##"
An unknown predicate was used inside the `cfg` attribute.

Erroneous code example:

```compile_fail,E0537
#[cfg(unknown())] // error: invalid predicate `unknown`
pub fn something() {}

pub fn main() {}
```

The `cfg` attribute supports only three kinds of predicates:

 * any
 * all
 * not

Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0538: r##"
Attribute contains multiple of the same meta item.

Erroneous code example:

```compile_fail,E0538
#[deprecated(
    since="1.0.0",
    note="First deprecation note.",
    note="Second deprecation note." // error: multiple same meta item
)]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. Each key may only be
used once in each attribute.

To fix the problem, remove all but one of the meta items with the same key.

Example:

```
#[deprecated(
    since="1.0.0",
    note="First deprecation note."
)]
fn deprecated_function() {}
```
"##,

E0541: r##"
An unknown meta item was used.

Erroneous code example:

```compile_fail,E0541
#[deprecated(
    since="1.0.0",
    // error: unknown meta item
    reason="Example invalid meta item. Should be 'note'")
]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. The keys provided
must be one of the valid keys for the specified attribute.

To fix the problem, either remove the unknown meta item, or rename it if you
provided the wrong name.

In the erroneous code example above, the wrong name was provided, so changing
to a correct one it will fix the error. Example:

```
#[deprecated(
    since="1.0.0",
    note="This is a valid meta item for the deprecated attribute."
)]
fn deprecated_function() {}
```
"##,

E0552: r##"
A unrecognized representation attribute was used.

Erroneous code example:

```compile_fail,E0552
#[repr(D)] // error: unrecognized representation hint
struct MyStruct {
    my_field: usize
}
```

You can use a `repr` attribute to tell the compiler how you want a struct or
enum to be laid out in memory.

Make sure you're using one of the supported options:

```
#[repr(C)] // ok!
struct MyStruct {
    my_field: usize
}
```

For more information about specifying representations, see the ["Alternative
Representations" section] of the Rustonomicon.

["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html
"##,

E0554: r##"
Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.

Example of erroneous code (on a stable compiler):

```ignore (depends on release channel)
#![feature(non_ascii_idents)] // error: #![feature] may not be used on the
                              //        stable release channel
```

If you need the feature, make sure to use a nightly release of the compiler
(but be warned that the feature may be removed or altered in the future).
"##,

E0557: r##"
A feature attribute named a feature that has been removed.

Erroneous code example:

```compile_fail,E0557
#![feature(managed_boxes)] // error: feature has been removed
```

Delete the offending feature attribute.
"##,

E0565: r##"
A literal was used in an attribute that doesn't support literals.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#![feature(attr_literals)]

#[inline("always")] // error: unsupported literal
pub fn something() {}
```

Literals in attributes are new and largely unsupported. Work to support literals
where appropriate is ongoing. Try using an unquoted name instead:

```
#[inline(always)]
pub fn something() {}
```
"##,

E0583: r##"
A file wasn't found for an out-of-line module.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
mod file_that_doesnt_exist; // error: file not found for module

fn main() {}
```

Please be sure that a file corresponding to the module exists. If you
want to use a module named `file_that_doesnt_exist`, you need to have a file
named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the
same directory.
"##,

E0585: r##"
A documentation comment that doesn't document anything was found.

Erroneous code example:

```compile_fail,E0585
fn main() {
    // The following doc comment will fail:
    /// This is a useless doc comment!
}
```

Documentation comments need to be followed by items, including functions,
types, modules, etc. Examples:

```
/// I'm documenting the following struct:
struct Foo;

/// I'm documenting the following function:
fn foo() {}
```
"##,

E0586: r##"
An inclusive range was used with no end.

Erroneous code example:

```compile_fail,E0586
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=]; // error: inclusive range was used with no end
}
```

An inclusive range needs an end in order to *include* it. If you just need a
start and no end, use a non-inclusive range (with `..`):

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..]; // ok!
}
```

Or put an end to your inclusive range:

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=3]; // ok!
}
```
"##,

E0589: r##"
The value of `N` that was specified for `repr(align(N))` was not a power
of two, or was greater than 2^29.

```compile_fail,E0589
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
enum Foo {
    Bar(u64),
}
```
"##,

E0658: r##"
An unstable feature was used.

Erroneous code example:

```compile_fail,E658
#[repr(u128)] // error: use of unstable library feature 'repr128'
enum Foo {
    Bar(u64),
}
```

If you're using a stable or a beta version of rustc, you won't be able to use
any unstable features. In order to do so, please switch to a nightly version of
rustc (by using rustup).

If you're using a nightly version of rustc, just add the corresponding feature
to be able to use it:

```
#![feature(repr128)]

#[repr(u128)] // ok!
enum Foo {
    Bar(u64),
}
```
"##,

E0633: r##"
The `unwind` attribute was malformed.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[unwind()] // error: expected one argument
pub extern fn something() {}

fn main() {}
```

The `#[unwind]` attribute should be used as follows:

- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function
  should abort the process if it attempts to unwind. This is the safer
  and preferred option.

- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function
  should be allowed to unwind. This can easily result in Undefined
  Behavior (UB), so be careful.

NB. The default behavior here is "allowed", but this is unspecified
and likely to change in the future.

"##,

}

register_diagnostics! {
    E0539, // incorrect meta item
    E0540, // multiple rustc_deprecated attributes
    E0542, // missing 'since'
    E0543, // missing 'reason'
    E0544, // multiple stability levels
    E0545, // incorrect 'issue'
    E0546, // missing 'feature'
    E0547, // missing 'issue'
    E0548, // incorrect stability attribute type
    E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
    E0550, // multiple deprecated attributes
    E0551, // incorrect meta item
    E0553, // multiple rustc_const_unstable attributes
    E0555, // malformed feature attribute, expected #![feature(...)]
    E0556, // malformed feature, expected just one word
    E0584, // file for module `..` found at both .. and ..
    E0629, // missing 'feature' (rustc_const_unstable)
    E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
    E0693, // incorrect `repr(align)` attribute format
    E0694, // an unknown tool name found in scoped attributes
}
<commit_msg>Slightly better summary for E0538<commit_after>// Copyright 2016 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! {

E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.

For example:

```compile_fail,E0178
trait Foo {}

struct Bar<'a> {
    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```

More details can be found in [RFC 438].

[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,

E0536: r##"
The `not` cfg-predicate was malformed.

Erroneous code example:

```compile_fail,E0536
#[cfg(not())] // error: expected 1 cfg-pattern
pub fn something() {}

pub fn main() {}
```

The `not` predicate expects one cfg-pattern. Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0537: r##"
An unknown predicate was used inside the `cfg` attribute.

Erroneous code example:

```compile_fail,E0537
#[cfg(unknown())] // error: invalid predicate `unknown`
pub fn something() {}

pub fn main() {}
```

The `cfg` attribute supports only three kinds of predicates:

 * any
 * all
 * not

Example:

```
#[cfg(not(target_os = "linux"))] // ok!
pub fn something() {}

pub fn main() {}
```

For more information about the cfg attribute, read:
https://doc.rust-lang.org/reference.html#conditional-compilation
"##,

E0538: r##"
Attribute contains same meta item more than once.

Erroneous code example:

```compile_fail,E0538
#[deprecated(
    since="1.0.0",
    note="First deprecation note.",
    note="Second deprecation note." // error: multiple same meta item
)]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. Each key may only be
used once in each attribute.

To fix the problem, remove all but one of the meta items with the same key.

Example:

```
#[deprecated(
    since="1.0.0",
    note="First deprecation note."
)]
fn deprecated_function() {}
```
"##,

E0541: r##"
An unknown meta item was used.

Erroneous code example:

```compile_fail,E0541
#[deprecated(
    since="1.0.0",
    // error: unknown meta item
    reason="Example invalid meta item. Should be 'note'")
]
fn deprecated_function() {}
```

Meta items are the key-value pairs inside of an attribute. The keys provided
must be one of the valid keys for the specified attribute.

To fix the problem, either remove the unknown meta item, or rename it if you
provided the wrong name.

In the erroneous code example above, the wrong name was provided, so changing
to a correct one it will fix the error. Example:

```
#[deprecated(
    since="1.0.0",
    note="This is a valid meta item for the deprecated attribute."
)]
fn deprecated_function() {}
```
"##,

E0552: r##"
A unrecognized representation attribute was used.

Erroneous code example:

```compile_fail,E0552
#[repr(D)] // error: unrecognized representation hint
struct MyStruct {
    my_field: usize
}
```

You can use a `repr` attribute to tell the compiler how you want a struct or
enum to be laid out in memory.

Make sure you're using one of the supported options:

```
#[repr(C)] // ok!
struct MyStruct {
    my_field: usize
}
```

For more information about specifying representations, see the ["Alternative
Representations" section] of the Rustonomicon.

["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html
"##,

E0554: r##"
Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.

Example of erroneous code (on a stable compiler):

```ignore (depends on release channel)
#![feature(non_ascii_idents)] // error: #![feature] may not be used on the
                              //        stable release channel
```

If you need the feature, make sure to use a nightly release of the compiler
(but be warned that the feature may be removed or altered in the future).
"##,

E0557: r##"
A feature attribute named a feature that has been removed.

Erroneous code example:

```compile_fail,E0557
#![feature(managed_boxes)] // error: feature has been removed
```

Delete the offending feature attribute.
"##,

E0565: r##"
A literal was used in an attribute that doesn't support literals.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#![feature(attr_literals)]

#[inline("always")] // error: unsupported literal
pub fn something() {}
```

Literals in attributes are new and largely unsupported. Work to support literals
where appropriate is ongoing. Try using an unquoted name instead:

```
#[inline(always)]
pub fn something() {}
```
"##,

E0583: r##"
A file wasn't found for an out-of-line module.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
mod file_that_doesnt_exist; // error: file not found for module

fn main() {}
```

Please be sure that a file corresponding to the module exists. If you
want to use a module named `file_that_doesnt_exist`, you need to have a file
named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the
same directory.
"##,

E0585: r##"
A documentation comment that doesn't document anything was found.

Erroneous code example:

```compile_fail,E0585
fn main() {
    // The following doc comment will fail:
    /// This is a useless doc comment!
}
```

Documentation comments need to be followed by items, including functions,
types, modules, etc. Examples:

```
/// I'm documenting the following struct:
struct Foo;

/// I'm documenting the following function:
fn foo() {}
```
"##,

E0586: r##"
An inclusive range was used with no end.

Erroneous code example:

```compile_fail,E0586
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=]; // error: inclusive range was used with no end
}
```

An inclusive range needs an end in order to *include* it. If you just need a
start and no end, use a non-inclusive range (with `..`):

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..]; // ok!
}
```

Or put an end to your inclusive range:

```
fn main() {
    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
    let x = &tmp[1..=3]; // ok!
}
```
"##,

E0589: r##"
The value of `N` that was specified for `repr(align(N))` was not a power
of two, or was greater than 2^29.

```compile_fail,E0589
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
enum Foo {
    Bar(u64),
}
```
"##,

E0658: r##"
An unstable feature was used.

Erroneous code example:

```compile_fail,E658
#[repr(u128)] // error: use of unstable library feature 'repr128'
enum Foo {
    Bar(u64),
}
```

If you're using a stable or a beta version of rustc, you won't be able to use
any unstable features. In order to do so, please switch to a nightly version of
rustc (by using rustup).

If you're using a nightly version of rustc, just add the corresponding feature
to be able to use it:

```
#![feature(repr128)]

#[repr(u128)] // ok!
enum Foo {
    Bar(u64),
}
```
"##,

E0633: r##"
The `unwind` attribute was malformed.

Erroneous code example:

```ignore (compile_fail not working here; see Issue #43707)
#[unwind()] // error: expected one argument
pub extern fn something() {}

fn main() {}
```

The `#[unwind]` attribute should be used as follows:

- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function
  should abort the process if it attempts to unwind. This is the safer
  and preferred option.

- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function
  should be allowed to unwind. This can easily result in Undefined
  Behavior (UB), so be careful.

NB. The default behavior here is "allowed", but this is unspecified
and likely to change in the future.

"##,

}

register_diagnostics! {
    E0539, // incorrect meta item
    E0540, // multiple rustc_deprecated attributes
    E0542, // missing 'since'
    E0543, // missing 'reason'
    E0544, // multiple stability levels
    E0545, // incorrect 'issue'
    E0546, // missing 'feature'
    E0547, // missing 'issue'
    E0548, // incorrect stability attribute type
    E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
    E0550, // multiple deprecated attributes
    E0551, // incorrect meta item
    E0553, // multiple rustc_const_unstable attributes
    E0555, // malformed feature attribute, expected #![feature(...)]
    E0556, // malformed feature, expected just one word
    E0584, // file for module `..` found at both .. and ..
    E0629, // missing 'feature' (rustc_const_unstable)
    E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
    E0693, // incorrect `repr(align)` attribute format
    E0694, // an unknown tool name found in scoped attributes
}
<|endoftext|>


<commit_before><commit_msg>fix `with_capacity` for zero-size vectors<commit_after><|endoftext|>


<commit_before><commit_msg>dispatch!<commit_after><|endoftext|>


<commit_before><commit_msg>Reusable Diagnostic Example<commit_after>use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term::termcolor::StandardStream;
use codespan_reporting::term::{self, ColorArg};
use std::ops::Range;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(name = "emit")]
pub struct Opts {
	#[structopt(long = "color",
		parse(try_from_str),
		default_value = "auto",
		possible_values = ColorArg::VARIANTS,
		case_insensitive = true
	)]
	color: ColorArg,
}

fn main() -> anyhow::Result<()> {
	let file = SimpleFile::new(
		"main.rs",
		unindent::unindent(
			r#"
                fn main() {
                    let foo: i32 = "hello, world";
                    foo += 1;
                }
            "#,
		),
	);

	let errors = [
		Error::MismatchType(
			Item::new(20..23, "i32"),
			Item::new(31..45, "\"hello, world\""),
		),
		Error::MutatingImmutable(Item::new(20..23, "foo"), Item::new(51..59, "foo += 1")),
	];

    // Map all errors into `Diagnostic`
	let diagnostics: Vec<Diagnostic<()>> = errors.iter().map(Error::report).collect();

	let opts = Opts::from_args();
	let writer = StandardStream::stderr(opts.color.into());
	let config = codespan_reporting::term::Config::default();
	for diagnostic in &diagnostics {
		term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
	}

	Ok(())
}

/// An error enum that represent all possible errors within your program
enum Error {
	MismatchType(Item, Item),
	MutatingImmutable(Item, Item),
}

impl Error {
	fn report(&self) -> Diagnostic<()> {
		match self {
			Error::MismatchType(left, right) => Diagnostic::error()
				.with_code("E0308")
				.with_message("mismatch types")
				.with_labels(vec![
					Label::primary((), right.range.clone()).with_message(format!(
						"Expected `{}`, found: `{}`",
						left.content, right.content
					)),
					Label::secondary((), left.range.clone()).with_message("expected due to this"),
				]),
			Error::MutatingImmutable(original, mutating) => Diagnostic::error()
				.with_code("E0384")
				.with_message(format!(
					"cannot mutate immutable variable `{}`",
					original.content
				))
				.with_labels(vec![
					Label::secondary((), original.range.clone()).with_message(unindent::unindent(
						&format!(
							r#"
                                    first assignment to `{0}`
                                    help: make this binding mutable: `mut {0}`
                                "#,
							original.content
						),
					)),
					Label::primary((), mutating.range.clone())
						.with_message("cannot assign twice to immutable variable"),
				]),
		}
	}
}

/// Representing a single error point in `Error` enum
/// In a more complex program it could also contain `FileId` to handle error that occurs inside multiple files
struct Item {
	range: Range<usize>,
	content: String,
}

impl Item {
	fn new(range: Range<usize>, content: impl Into<String>) -> Item {
		let content = content.into();
		Item { range, content }
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Algorithm of Horspool.
//! Window-based, similar to but faster than Boyer-Moore.
//!
//! # Idea
//! Look at a search window m, match pattern backwards.
//! In case of a mismatch, you can jump behind that.
//! Best case time complexity: O(n / m)
//! Worst case time complexity: O(n * m)
//! With a large alphabet, you are likely
//! around the best case, and faster than the rather
//! complicated Boyer-Moore.
//!
//! The algorithm has two phases (let a be the last symbol in the window):
//!
//! 1. test phase: compare the last symbol of the window.
//!    If it matches, compare the whole pattern.
//!    If it does not match, continue with the shift phase.
//! 2. shift phase: let l[a] be the rightmost position of a in
//!    the pattern without the last symbol. If it does not occur
//!    let l[a] be -1. Shift the window by m - 1 - l[a]. I.e.
//!    we shift the window such that the rightmost a matches
//!    the a at the end of the last window.
//!    If a does not occur in the pattern, we shift by the whole length.
//!
//! # Example
//!
//! ```
//! use bio::pattern_matching::horspool::Horspool;
//! let text = b"ACGGCTAGGAAAAAGACTGAGGACTGAAAA";
//! let pattern = b"GAAAA";
//! let horspool = Horspool::new(pattern);
//! let occ: Vec<usize> = horspool.find_all(text).collect();
//! assert_eq!(occ, [8, 25]);
//! ```

pub struct Horspool<'a> {
    shift: Vec<usize>,
    m: usize,
    pattern: &'a [u8]
}

impl<'a> Horspool<'a> {
    pub fn new(pattern: &'a [u8]) -> Self {
        let m = pattern.len();
        let mut shift = vec![m; 256];
        // shift is m for all not occurring characters
        // and m - 1 - j for all others
        for (j, &a) in pattern[..m-1].iter().enumerate() {
            shift[a as usize] = m - 1 - j;
        }

        Horspool {
            m: m, shift: shift, pattern: pattern
        }
    }

    pub fn find_all<'b>(&'b self, text: &'b [u8]) -> HorspoolMatches {
        HorspoolMatches {
            horspool: self, text: text, n: text.len(),
            last: self.m - 1,
            pattern_last: self.pattern[self.m - 1]
        }
    }
}

pub struct HorspoolMatches<'a> {
    horspool: &'a Horspool<'a>,
    text: &'a [u8],
    n: usize,
    last: usize,
    pattern_last: u8
}

impl<'a> Iterator for HorspoolMatches<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            // shift until the last symbol matches
            while self.last < self.n
                && self.text[self.last] != self.pattern_last {
                self.last += self.horspool.shift[self.text[self.last] as usize];
            }
            // stop if end of text is reached
            if self.last >= self.n {
                return None;
            }

            // putative start position
            let i = self.last - self.horspool.m + 1;
            let j = self.last;

            // shift again (after both match and mismatch, this makes sense)
            self.last += self.horspool.shift[self.pattern_last as usize];

            if self.text[i..j] == self.horspool.pattern[..self.horspool.m-1] {
                return Some(i);
            }
        }
    }
}

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

    #[test]
    fn test_shift() {
        let pattern = b"AACB";
        let horspool = Horspool::new(pattern);
        assert_eq!(horspool.shift[b'A' as usize], 2);
        assert_eq!(horspool.shift[b'C' as usize], 1);
        assert_eq!(horspool.shift[b'B' as usize], 4);
        assert_eq!(horspool.shift[b'X' as usize], 4);
    }
}
<commit_msg>Fixed overflow in horspool.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Algorithm of Horspool.
//! Window-based, similar to but faster than Boyer-Moore.
//!
//! # Idea
//! Look at a search window m, match pattern backwards.
//! In case of a mismatch, you can jump behind that.
//! Best case time complexity: O(n / m)
//! Worst case time complexity: O(n * m)
//! With a large alphabet, you are likely
//! around the best case, and faster than the rather
//! complicated Boyer-Moore.
//!
//! The algorithm has two phases (let a be the last symbol in the window):
//!
//! 1. test phase: compare the last symbol of the window.
//!    If it matches, compare the whole pattern.
//!    If it does not match, continue with the shift phase.
//! 2. shift phase: let l[a] be the rightmost position of a in
//!    the pattern without the last symbol. If it does not occur
//!    let l[a] be -1. Shift the window by m - 1 - l[a]. I.e.
//!    we shift the window such that the rightmost a matches
//!    the a at the end of the last window.
//!    If a does not occur in the pattern, we shift by the whole length.
//!
//! # Example
//!
//! ```
//! use bio::pattern_matching::horspool::Horspool;
//! let text = b"ACGGCTAGGAAAAAGACTGAGGACTGAAAA";
//! let pattern = b"GAAAA";
//! let horspool = Horspool::new(pattern);
//! let occ: Vec<usize> = horspool.find_all(text).collect();
//! assert_eq!(occ, [8, 25]);
//! ```

pub struct Horspool<'a> {
    shift: Vec<usize>,
    m: usize,
    pattern: &'a [u8]
}

impl<'a> Horspool<'a> {
    pub fn new(pattern: &'a [u8]) -> Self {
        let m = pattern.len();
        let mut shift = vec![m; 256];
        // shift is m for all not occurring characters
        // and m - 1 - j for all others
        for (j, &a) in pattern[..m-1].iter().enumerate() {
            shift[a as usize] = m - 1 - j;
        }

        Horspool {
            m: m, shift: shift, pattern: pattern
        }
    }

    pub fn find_all<'b>(&'b self, text: &'b [u8]) -> HorspoolMatches {
        HorspoolMatches {
            horspool: self, text: text, n: text.len(),
            last: self.m - 1,
            pattern_last: self.pattern[self.m - 1]
        }
    }
}

pub struct HorspoolMatches<'a> {
    horspool: &'a Horspool<'a>,
    text: &'a [u8],
    n: usize,
    last: usize,
    pattern_last: u8
}

impl<'a> Iterator for HorspoolMatches<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            // shift until the last symbol matches
            while self.last < self.n
                && self.text[self.last] != self.pattern_last {
                self.last += self.horspool.shift[self.text[self.last] as usize];
            }
            // stop if end of text is reached
            if self.last >= self.n {
                return None;
            }

            // putative start position
            let i = self.last + 1 - self.horspool.m;
            let j = self.last;

            // shift again (after both match and mismatch, this makes sense)
            self.last += self.horspool.shift[self.pattern_last as usize];

            if self.text[i..j] == self.horspool.pattern[..self.horspool.m-1] {
                return Some(i);
            }
        }
    }
}

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

    #[test]
    fn test_shift() {
        let pattern = b"AACB";
        let horspool = Horspool::new(pattern);
        assert_eq!(horspool.shift[b'A' as usize], 2);
        assert_eq!(horspool.shift[b'C' as usize], 1);
        assert_eq!(horspool.shift[b'B' as usize], 4);
        assert_eq!(horspool.shift[b'X' as usize], 4);
    }
}
<|endoftext|>


<commit_before><commit_msg>Problem 57<commit_after>#[deriving(Clone)]
enum BinaryTree<T> {
    Node(T, ~BinaryTree<T>, ~BinaryTree<T>),
    Empty
}

impl<T: Eq> Eq for BinaryTree<T> {
    fn eq(&self, other: &BinaryTree<T>) -> bool {
        match (self, other) {
            (&Empty, &Empty) => true,
            (&Node(ref a, ref ll, ref lr), &Node(ref b, ref rl, ref rr)) if a == b =>
                ll == rl && lr == rr,
            _ => false
        }
    }
}

fn construct<T: Ord>(list: ~[T]) -> BinaryTree<T> {
    fn insert<T: Ord>(tree: BinaryTree<T>, elem: T) -> BinaryTree<T> {
        match tree {
            Empty           =>  Node(elem, ~Empty, ~Empty),
            Node(e, ~l, ~r) =>  if elem < e {
                                    Node(e, ~insert(l, elem), ~r)
                                } else {
                                    Node(e, ~l, ~insert(r, elem))
                                }
        }
    }
    list.move_iter().fold(Empty, |t, e| insert(t, e))
}

fn main() {
    assert!(construct(~[3, 2, 5, 7, 1]) ==
            Node(3, ~Node(2, ~Node(1, ~Empty, ~Empty), ~Empty),
                    ~Node(5, ~Empty, ~Node(7, ~Empty, ~Empty))));
}
<|endoftext|>


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

// ignore-arm
// ignore-aarch64
// ignore-powerpc
// ignore-aarch64
// ignore-wasm
// ignore-emscripten
// ignore-windows
// min-system-llvm-version 5.0
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]

#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0
// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
}
<commit_msg>test: remove duplicate ignore-aarch64 from stack-probes test<commit_after>// Copyright 2016 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.

// ignore-arm
// ignore-aarch64
// ignore-powerpc
// ignore-wasm
// ignore-emscripten
// ignore-windows
// min-system-llvm-version 5.0
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]

#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0
// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
}
<|endoftext|>


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

use std::thread;

fn main() {
    thread::Thread::spawn(move || { // no need for -> ()
        loop {
            println!("hello");
        }
    });
}
<|endoftext|>


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

trait Test {}

macro_rules! test {
( $($name:ident)+) => (
    impl<$($name: Test),*> Test for ($($name,)*) {
    }
)
}

test!(A B C);

fn main() {}
<|endoftext|>


<commit_before><commit_msg>(doc) Add echo example<commit_after>// An example that echoes the body of the request back as the response.
//
// Shows how to read the request body with error handling and how to return a
// response. See `helper_macros` example for a different way to handle errors.

extern crate iron;

use std::io::Read;

use iron::prelude::*;
use iron::status;

fn echo(request: &mut Request) -> IronResult<Response> {
    let mut body = Vec::new();
    request
        .body
        .read_to_end(&mut body)
        .map_err(|e| IronError::new(e, (status::InternalServerError, "Error reading request")))?;
    Ok(Response::with((status::Ok, body)))
}

fn main() {
    Iron::new(echo).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before><commit_msg>added fifo example<commit_after>
extern crate atom;

use std::thread;
use std::sync::{Arc, Barrier};
use atom::*;

struct Link {
    next: AtomSetOnce<Link, Arc<Link>>
}

fn main() {
    let b = Arc::new(Barrier::new(11));

    let head = Arc::new(Link{next: AtomSetOnce::empty()});

    for _ in (0..10) {
        let b = b.clone();
        let head = head.clone();
        thread::spawn(move || {
            let mut hptr = &*head;

            for _ in (0..100) {
                let mut my_awesome_node = Arc::new(Link {
                    next: AtomSetOnce::empty()
                });

                loop {
                    while let Some(h) = hptr.next.get(Ordering::SeqCst) {
                        hptr = h;
                    }

                    my_awesome_node = match hptr.next.set_if_none(my_awesome_node, Ordering::SeqCst) {
                        Some(v) => v,
                        None => break
                    };
                }
            }
            b.wait();
        });
    }

    b.wait();

    let mut hptr = &*head;
    let mut count = 0;
    while let Some(h) = hptr.next.get(Ordering::SeqCst) {
        hptr = h;
        count += 1;
    }
    println!("Using {} threads we wrote {} links at the same time!", 10, count);
}<|endoftext|>


<commit_before><commit_msg>Rollup merge of #78391 - JulianKnodt:mc_test, r=lcnr<commit_after>// run-pass

#![feature(min_const_generics)]

const fn identity<const T: u32>() -> u32 { T }

#[derive(Eq, PartialEq, Debug)]
pub struct ConstU32<const U: u32>;

pub fn new() -> ConstU32<{ identity::<3>() }> {
  ConstU32::<{ identity::<3>() }>
}

fn main() {
  let v = new();
  assert_eq!(v, ConstU32::<3>);
}
<|endoftext|>


<commit_before><commit_msg>Remove feature(duration) now that it is stable in nightly<commit_after><|endoftext|>


<commit_before><commit_msg>Test(basic_syncback): add test (currently failing)<commit_after><|endoftext|>


<commit_before><commit_msg>fix(lib): `unwrap` has been deprecated in favor of `into_inner`<commit_after><|endoftext|>


<commit_before>use std::io::{fs, IoResult};
use std::io;

use ansi_term::{ANSIString, Colour, Style};
use ansi_term::Style::Plain;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan, Fixed};

use users::Users;

use number_prefix::{binary_prefix, decimal_prefix, Prefixed, Standalone, PrefixNames};

use column::{Column, SizeFormat, Cell};
use column::Column::*;
use dir::Dir;
use filetype::HasType;

/// This grey value is directly in between white and black, so it's guaranteed
/// to show up on either backgrounded terminal.
pub static GREY: Colour = Fixed(244);

/// A **File** is a wrapper around one of Rust's Path objects, along with
/// associated data about the file.
///
/// Each file is definitely going to have its filename displayed at least
/// once, have its file extension extracted at least once, and have its stat
/// information queried at least once, so it makes sense to do all this at the
/// start and hold on to all the information.
pub struct File<'a> {
    pub name:  String,
    pub dir:   Option<&'a Dir>,
    pub ext:   Option<String>,
    pub path:  Path,
    pub stat:  io::FileStat,
}

impl<'a> File<'a> {
    /// Create a new File object from the given Path, inside the given Dir, if
    /// appropriate. Paths specified directly on the command-line have no Dirs.
    ///
    /// This uses lstat instead of stat, which doesn't follow symbolic links.
    pub fn from_path(path: &Path, parent: Option<&'a Dir>) -> IoResult<File<'a>> {
        fs::lstat(path).map(|stat| File::with_stat(stat, path, parent))
    }

    /// Create a new File object from the given Stat result, and other data.
    pub fn with_stat(stat: io::FileStat, path: &Path, parent: Option<&'a Dir>) -> File<'a> {
        let v = path.filename().unwrap();  // fails if / or . or ..
        let filename = String::from_utf8_lossy(v);

        File {
            path:  path.clone(),
            dir:   parent,
            stat:  stat,
            name:  filename.to_string(),
            ext:   ext(filename.as_slice()),
        }
    }

    /// Whether this file is a dotfile or not.
    pub fn is_dotfile(&self) -> bool {
        self.name.as_slice().starts_with(".")
    }

    /// Whether this file is a temporary file or not.
    pub fn is_tmpfile(&self) -> bool {
        let name = self.name.as_slice();
        name.ends_with("~") || (name.starts_with("#") && name.ends_with("#"))
    }

    /// Get the data for a column, formatted as a coloured string.
    pub fn display<U: Users>(&self, column: &Column, users_cache: &mut U) -> Cell {
        match *column {
            Permissions  => self.permissions_string(),
            FileName     => self.file_name_view(),
            FileSize(f)  => self.file_size(f),
            HardLinks    => self.hard_links(),
            Inode        => self.inode(),
            Blocks       => self.blocks(),
            User         => self.user(users_cache),
            Group        => self.group(users_cache),
        }
    }

    /// The "file name view" is what's displayed in the column and lines
    /// views, but *not* in the grid view.
    ///
    /// It consists of the file name coloured in the appropriate style, and,
    /// if it's a symlink, an arrow pointing to the file it links to, also
    /// coloured in the appropriate style.
    ///
    /// If the symlink target doesn't exist, then instead of displaying
    /// an error, highlight the target and arrow in red. The error would
    /// be shown out of context, and it's almost always because the
    /// target doesn't exist.
    pub fn file_name_view(&self) -> Cell {
        let name = &*self.name;
        let style = self.file_colour();

        if self.stat.kind == io::FileType::Symlink {
            match fs::readlink(&self.path) {
                Ok(path) => {
                    let target_path = match self.dir {
                        Some(dir) => dir.path.join(path),
                        None => path,
                    };

                    match self.target_file(&target_path) {
                        Ok(file) => Cell {
                            length: 0,  // These lengths are never actually used...
                            text: format!("{} {} {}{}{}",
                                          style.paint(name),
                                          GREY.paint("=>"),
                                          Cyan.paint(target_path.dirname_str().unwrap()),
                                          Cyan.paint("/"),
                                          file.file_colour().paint(file.name.as_slice())),
                        },
                        Err(filename) => Cell {
                            length: 0,  // ...because the rightmost column lengths are ignored!
                            text: format!("{} {} {}",
                                          style.paint(name),
                                          Red.paint("=>"),
                                          Red.underline().paint(filename.as_slice())),
                        },
                    }
                }
                Err(_) => Cell::paint(style, name),
            }
        }
        else {
            Cell::paint(style, name)
        }
    }

    /// The `ansi_term::Style` that this file's name should be painted.
    pub fn file_colour(&self) -> Style {
        self.get_type().style()
    }

    /// The Unicode 'display width' of the filename.
    ///
    /// This is related to the number of graphemes in the string: most
    /// characters are 1 columns wide, but in some contexts, certain
    /// characters are actually 2 columns wide.
    pub fn file_name_width(&self) -> usize {
        self.name.as_slice().width(false)
    }

    /// Assuming the current file is a symlink, follows the link and
    /// returns a File object from the path the link points to.
    ///
    /// If statting the file fails (usually because the file on the
    /// other end doesn't exist), returns the *filename* of the file
    /// that should be there.
    fn target_file(&self, target_path: &Path) -> Result<File, String> {
        let v = target_path.filename().unwrap();
        let filename = String::from_utf8_lossy(v);

        // Use stat instead of lstat - we *want* to follow links.
        if let Ok(stat) = fs::stat(target_path) {
            Ok(File {
                path:  target_path.clone(),
                dir:   self.dir,
                stat:  stat,
                name:  filename.to_string(),
                ext:   ext(filename.as_slice()),
            })
        }
        else {
            Err(filename.to_string())
        }
    }

    /// This file's number of hard links as a coloured string.
    fn hard_links(&self) -> Cell {
        let style = if self.has_multiple_links() { Red.on(Yellow) } else { Red.normal() };
        Cell::paint(style, &*self.stat.unstable.nlink.to_string())
    }

    /// Whether this is a regular file with more than one link.
    ///
    /// This is important, because a file with multiple links is uncommon,
    /// while you can come across directories and other types with multiple
    /// links much more often.
    fn has_multiple_links(&self) -> bool {
        self.stat.kind == io::FileType::RegularFile && self.stat.unstable.nlink > 1
    }

    /// This file's inode as a coloured string.
    fn inode(&self) -> Cell {
        Cell::paint(Purple.normal(), &*self.stat.unstable.inode.to_string())
    }

    /// This file's number of filesystem blocks (if available) as a coloured string.
    fn blocks(&self) -> Cell {
        if self.stat.kind == io::FileType::RegularFile || self.stat.kind == io::FileType::Symlink {
            Cell::paint(Cyan.normal(), &*self.stat.unstable.blocks.to_string())
        }
        else {
            Cell { text: GREY.paint("-").to_string(), length: 1 }
        }
    }

    /// This file's owner's username as a coloured string.
    ///
    /// If the user is not present, then it formats the uid as a number
    /// instead. This usually happens when a user is deleted, but still owns
    /// files.
    fn user<U: Users>(&self, users_cache: &mut U) -> Cell {
        let uid = self.stat.unstable.uid as i32;

        let user_name = match users_cache.get_user_by_uid(uid) {
            Some(user) => user.name,
            None => uid.to_string(),
        };

        let style = if users_cache.get_current_uid() == uid { Yellow.bold() } else { Plain };
        Cell::paint(style, &*user_name)
    }

    /// This file's group name as a coloured string.
    ///
    /// As above, if not present, it formats the gid as a number instead.
    fn group<U: Users>(&self, users_cache: &mut U) -> Cell {
        let gid = self.stat.unstable.gid as u32;
        let mut style = Plain;

        let group_name = match users_cache.get_group_by_gid(gid) {
            Some(group) => {
                let current_uid = users_cache.get_current_uid();
                if let Some(current_user) = users_cache.get_user_by_uid(current_uid) {
                    if current_user.primary_group == group.gid || group.members.contains(&current_user.name) {
                        style = Yellow.bold();
                    }
                }
                group.name
            },
            None => gid.to_string(),
        };

        Cell::paint(style, &*group_name)
    }

    /// This file's size, formatted using the given way, as a coloured string.
    ///
    /// For directories, no size is given. Although they do have a size on
    /// some filesystems, I've never looked at one of those numbers and gained
    /// any information from it, so by emitting "-" instead, the table is less
    /// cluttered with numbers.
    fn file_size(&self, size_format: SizeFormat) -> Cell {
        if self.stat.kind == io::FileType::Directory {
            Cell { text: GREY.paint("-").to_string(), length: 1 }
        }
        else {
            let result = match size_format {
                SizeFormat::DecimalBytes => decimal_prefix(self.stat.size as f64),
                SizeFormat::BinaryBytes  => binary_prefix(self.stat.size as f64),
                SizeFormat::JustBytes    => return Cell::paint(Green.bold(), &*self.stat.size.to_string())
            };

            match result {
                Standalone(bytes) => Cell::paint(Green.bold(), &*bytes.to_string()),
                Prefixed(prefix, n) => {
                    let number = if n < 10f64 { format!("{:.1}", n) } else { format!("{:.0}", n) };
                    let symbol = prefix.symbol();

                    Cell {
                        text: format!("{}{}", Green.bold().paint(&*number), Green.paint(symbol)),
                        length: number.len() + symbol.len(),
                    }
                }
            }
        }
    }

    /// This file's type, represented by a coloured character.
    ///
    /// Although the file type can usually be guessed from the colour of the
    /// file, `ls` puts this character there, so people will expect it.
    fn type_char(&self) -> ANSIString {
        return match self.stat.kind {
            io::FileType::RegularFile   => Plain.paint("."),
            io::FileType::Directory     => Blue.paint("d"),
            io::FileType::NamedPipe     => Yellow.paint("|"),
            io::FileType::BlockSpecial  => Purple.paint("s"),
            io::FileType::Symlink       => Cyan.paint("l"),
            io::FileType::Unknown       => Plain.paint("?"),
        }
    }

    /// Generate the "rwxrwxrwx" permissions string, like how ls does it.
    ///
    /// Each character is given its own colour. The first three permission
    /// bits are bold because they're the ones used most often, and executable
    /// files are underlined to make them stand out more.
    fn permissions_string(&self) -> Cell {
        let bits = self.stat.perm;
        let executable_colour = match self.stat.kind {
            io::FileType::RegularFile => Green.bold().underline(),
            _ => Green.bold(),
        };

        let string = format!("{}{}{}{}{}{}{}{}{}{}",
            self.type_char(),
            File::permission_bit(&bits, io::USER_READ,     "r", Yellow.bold()),
            File::permission_bit(&bits, io::USER_WRITE,    "w", Red.bold()),
            File::permission_bit(&bits, io::USER_EXECUTE,  "x", executable_colour),
            File::permission_bit(&bits, io::GROUP_READ,    "r", Yellow.normal()),
            File::permission_bit(&bits, io::GROUP_WRITE,   "w", Red.normal()),
            File::permission_bit(&bits, io::GROUP_EXECUTE, "x", Green.normal()),
            File::permission_bit(&bits, io::OTHER_READ,    "r", Yellow.normal()),
            File::permission_bit(&bits, io::OTHER_WRITE,   "w", Red.normal()),
            File::permission_bit(&bits, io::OTHER_EXECUTE, "x", Green.normal()),
       );

        Cell { text: string, length: 10 }
    }

    /// Helper method for the permissions string.
    fn permission_bit(bits: &io::FilePermission, bit: io::FilePermission, character: &'static str, style: Style) -> ANSIString<'static> {
        if bits.contains(bit) {
            style.paint(character)
        }
        else {
            GREY.paint("-")
        }
    }

    /// For this file, return a vector of alternate file paths that, if any of
    /// them exist, mean that *this* file should be coloured as `Compiled`.
    ///
    /// The point of this is to highlight compiled files such as `foo.o` when
    /// their source file `foo.c` exists in the same directory. It's too
    /// dangerous to highlight *all* compiled, so the paths in this vector
    /// are checked for existence first: for example, `foo.js` is perfectly
    /// valid without `foo.coffee`.
    pub fn get_source_files(&self) -> Vec<Path> {
        if let Some(ref ext) = self.ext {
            match ext.as_slice() {
                "class" => vec![self.path.with_extension("java")],  // Java
                "css"   => vec![self.path.with_extension("sass"),   self.path.with_extension("less")],  // SASS, Less
                "elc"   => vec![self.path.with_extension("el")],    // Emacs Lisp
                "hi"    => vec![self.path.with_extension("hs")],    // Haskell
                "js"    => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")],  // CoffeeScript, TypeScript
                "o"     => vec![self.path.with_extension("c"),      self.path.with_extension("cpp")], // C, C++
                "pyc"   => vec![self.path.with_extension("py")],    // Python

                "aux" => vec![self.path.with_extension("tex")],  // TeX: auxiliary file
                "bbl" => vec![self.path.with_extension("tex")],  // BibTeX bibliography file
                "blg" => vec![self.path.with_extension("tex")],  // BibTeX log file
                "lof" => vec![self.path.with_extension("tex")],  // TeX list of figures
                "log" => vec![self.path.with_extension("tex")],  // TeX log file
                "lot" => vec![self.path.with_extension("tex")],  // TeX list of tables
                "toc" => vec![self.path.with_extension("tex")],  // TeX table of contents

                _ => vec![],  // No source files if none of the above
            }
        }
        else {
            vec![]  // No source files if there's no extension, either!
        }
    }
}

/// Extract an extension from a string, if one is present.
///
/// The extension is the series of characters after the last dot. This
/// deliberately counts dotfiles, so the ".git" folder has the extension "git".
fn ext<'a>(name: &'a str) -> Option<String> {
    name.rfind('.').map(|p| name[p+1..].to_string())
}
<commit_msg>Extract symlink stuff into its own method<commit_after>use std::io::{fs, IoResult};
use std::io;

use ansi_term::{ANSIString, Colour, Style};
use ansi_term::Style::Plain;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan, Fixed};

use users::Users;

use number_prefix::{binary_prefix, decimal_prefix, Prefixed, Standalone, PrefixNames};

use column::{Column, SizeFormat, Cell};
use column::Column::*;
use dir::Dir;
use filetype::HasType;

/// This grey value is directly in between white and black, so it's guaranteed
/// to show up on either backgrounded terminal.
pub static GREY: Colour = Fixed(244);

/// A **File** is a wrapper around one of Rust's Path objects, along with
/// associated data about the file.
///
/// Each file is definitely going to have its filename displayed at least
/// once, have its file extension extracted at least once, and have its stat
/// information queried at least once, so it makes sense to do all this at the
/// start and hold on to all the information.
pub struct File<'a> {
    pub name:  String,
    pub dir:   Option<&'a Dir>,
    pub ext:   Option<String>,
    pub path:  Path,
    pub stat:  io::FileStat,
}

impl<'a> File<'a> {
    /// Create a new File object from the given Path, inside the given Dir, if
    /// appropriate. Paths specified directly on the command-line have no Dirs.
    ///
    /// This uses lstat instead of stat, which doesn't follow symbolic links.
    pub fn from_path(path: &Path, parent: Option<&'a Dir>) -> IoResult<File<'a>> {
        fs::lstat(path).map(|stat| File::with_stat(stat, path, parent))
    }

    /// Create a new File object from the given Stat result, and other data.
    pub fn with_stat(stat: io::FileStat, path: &Path, parent: Option<&'a Dir>) -> File<'a> {
        let v = path.filename().unwrap();  // fails if / or . or ..
        let filename = String::from_utf8_lossy(v);

        File {
            path:  path.clone(),
            dir:   parent,
            stat:  stat,
            name:  filename.to_string(),
            ext:   ext(filename.as_slice()),
        }
    }

    /// Whether this file is a dotfile or not.
    pub fn is_dotfile(&self) -> bool {
        self.name.as_slice().starts_with(".")
    }

    /// Whether this file is a temporary file or not.
    pub fn is_tmpfile(&self) -> bool {
        let name = self.name.as_slice();
        name.ends_with("~") || (name.starts_with("#") && name.ends_with("#"))
    }

    /// Get the data for a column, formatted as a coloured string.
    pub fn display<U: Users>(&self, column: &Column, users_cache: &mut U) -> Cell {
        match *column {
            Permissions  => self.permissions_string(),
            FileName     => self.file_name_view(),
            FileSize(f)  => self.file_size(f),
            HardLinks    => self.hard_links(),
            Inode        => self.inode(),
            Blocks       => self.blocks(),
            User         => self.user(users_cache),
            Group        => self.group(users_cache),
        }
    }

    /// The "file name view" is what's displayed in the column and lines
    /// views, but *not* in the grid view.
    ///
    /// It consists of the file name coloured in the appropriate style,
    /// with special formatting for a symlink.
    pub fn file_name_view(&self) -> Cell {
        if self.stat.kind == io::FileType::Symlink {
            self.symlink_file_name_view()
        }
        else {
            Cell {
                length: 0,  // This length is ignored (rightmost column)
                text: self.file_colour().paint(&*self.name).to_string(),
            }
        }
    }

    /// If this file is a symlink, returns a string displaying its name,
    /// and an arrow pointing to the file it links to, which is also
    /// coloured in the appropriate style.
    ///
    /// If the symlink target doesn't exist, then instead of displaying
    /// an error, highlight the target and arrow in red. The error would
    /// be shown out of context, and it's almost always because the
    /// target doesn't exist.
    fn symlink_file_name_view(&self) -> Cell {
        let name = &*self.name;
        let style = self.file_colour();

        if let Ok(path) = fs::readlink(&self.path) {
            let target_path = match self.dir {
                Some(dir) => dir.path.join(path),
                None => path,
            };

            match self.target_file(&target_path) {
                Ok(file) => Cell {
                    length: 0,  // These lengths are never actually used...
                    text: format!("{} {} {}{}{}",
                                  style.paint(name),
                                  GREY.paint("=>"),
                                  Cyan.paint(target_path.dirname_str().unwrap()),
                                  Cyan.paint("/"),
                                  file.file_colour().paint(file.name.as_slice())),
                },
                Err(filename) => Cell {
                    length: 0,  // ...because the rightmost column lengths are ignored!
                    text: format!("{} {} {}",
                                  style.paint(name),
                                  Red.paint("=>"),
                                  Red.underline().paint(filename.as_slice())),
                },
            }
        }
        else {
            Cell::paint(style, name)
        }
    }

    /// The `ansi_term::Style` that this file's name should be painted.
    pub fn file_colour(&self) -> Style {
        self.get_type().style()
    }

    /// The Unicode 'display width' of the filename.
    ///
    /// This is related to the number of graphemes in the string: most
    /// characters are 1 columns wide, but in some contexts, certain
    /// characters are actually 2 columns wide.
    pub fn file_name_width(&self) -> usize {
        self.name.as_slice().width(false)
    }

    /// Assuming the current file is a symlink, follows the link and
    /// returns a File object from the path the link points to.
    ///
    /// If statting the file fails (usually because the file on the
    /// other end doesn't exist), returns the *filename* of the file
    /// that should be there.
    fn target_file(&self, target_path: &Path) -> Result<File, String> {
        let v = target_path.filename().unwrap();
        let filename = String::from_utf8_lossy(v);

        // Use stat instead of lstat - we *want* to follow links.
        if let Ok(stat) = fs::stat(target_path) {
            Ok(File {
                path:  target_path.clone(),
                dir:   self.dir,
                stat:  stat,
                name:  filename.to_string(),
                ext:   ext(filename.as_slice()),
            })
        }
        else {
            Err(filename.to_string())
        }
    }

    /// This file's number of hard links as a coloured string.
    fn hard_links(&self) -> Cell {
        let style = if self.has_multiple_links() { Red.on(Yellow) } else { Red.normal() };
        Cell::paint(style, &*self.stat.unstable.nlink.to_string())
    }

    /// Whether this is a regular file with more than one link.
    ///
    /// This is important, because a file with multiple links is uncommon,
    /// while you can come across directories and other types with multiple
    /// links much more often.
    fn has_multiple_links(&self) -> bool {
        self.stat.kind == io::FileType::RegularFile && self.stat.unstable.nlink > 1
    }

    /// This file's inode as a coloured string.
    fn inode(&self) -> Cell {
        Cell::paint(Purple.normal(), &*self.stat.unstable.inode.to_string())
    }

    /// This file's number of filesystem blocks (if available) as a coloured string.
    fn blocks(&self) -> Cell {
        if self.stat.kind == io::FileType::RegularFile || self.stat.kind == io::FileType::Symlink {
            Cell::paint(Cyan.normal(), &*self.stat.unstable.blocks.to_string())
        }
        else {
            Cell { text: GREY.paint("-").to_string(), length: 1 }
        }
    }

    /// This file's owner's username as a coloured string.
    ///
    /// If the user is not present, then it formats the uid as a number
    /// instead. This usually happens when a user is deleted, but still owns
    /// files.
    fn user<U: Users>(&self, users_cache: &mut U) -> Cell {
        let uid = self.stat.unstable.uid as i32;

        let user_name = match users_cache.get_user_by_uid(uid) {
            Some(user) => user.name,
            None => uid.to_string(),
        };

        let style = if users_cache.get_current_uid() == uid { Yellow.bold() } else { Plain };
        Cell::paint(style, &*user_name)
    }

    /// This file's group name as a coloured string.
    ///
    /// As above, if not present, it formats the gid as a number instead.
    fn group<U: Users>(&self, users_cache: &mut U) -> Cell {
        let gid = self.stat.unstable.gid as u32;
        let mut style = Plain;

        let group_name = match users_cache.get_group_by_gid(gid) {
            Some(group) => {
                let current_uid = users_cache.get_current_uid();
                if let Some(current_user) = users_cache.get_user_by_uid(current_uid) {
                    if current_user.primary_group == group.gid || group.members.contains(&current_user.name) {
                        style = Yellow.bold();
                    }
                }
                group.name
            },
            None => gid.to_string(),
        };

        Cell::paint(style, &*group_name)
    }

    /// This file's size, formatted using the given way, as a coloured string.
    ///
    /// For directories, no size is given. Although they do have a size on
    /// some filesystems, I've never looked at one of those numbers and gained
    /// any information from it, so by emitting "-" instead, the table is less
    /// cluttered with numbers.
    fn file_size(&self, size_format: SizeFormat) -> Cell {
        if self.stat.kind == io::FileType::Directory {
            Cell { text: GREY.paint("-").to_string(), length: 1 }
        }
        else {
            let result = match size_format {
                SizeFormat::DecimalBytes => decimal_prefix(self.stat.size as f64),
                SizeFormat::BinaryBytes  => binary_prefix(self.stat.size as f64),
                SizeFormat::JustBytes    => return Cell::paint(Green.bold(), &*self.stat.size.to_string())
            };

            match result {
                Standalone(bytes) => Cell::paint(Green.bold(), &*bytes.to_string()),
                Prefixed(prefix, n) => {
                    let number = if n < 10f64 { format!("{:.1}", n) } else { format!("{:.0}", n) };
                    let symbol = prefix.symbol();

                    Cell {
                        text: format!("{}{}", Green.bold().paint(&*number), Green.paint(symbol)),
                        length: number.len() + symbol.len(),
                    }
                }
            }
        }
    }

    /// This file's type, represented by a coloured character.
    ///
    /// Although the file type can usually be guessed from the colour of the
    /// file, `ls` puts this character there, so people will expect it.
    fn type_char(&self) -> ANSIString {
        return match self.stat.kind {
            io::FileType::RegularFile   => Plain.paint("."),
            io::FileType::Directory     => Blue.paint("d"),
            io::FileType::NamedPipe     => Yellow.paint("|"),
            io::FileType::BlockSpecial  => Purple.paint("s"),
            io::FileType::Symlink       => Cyan.paint("l"),
            io::FileType::Unknown       => Plain.paint("?"),
        }
    }

    /// Generate the "rwxrwxrwx" permissions string, like how ls does it.
    ///
    /// Each character is given its own colour. The first three permission
    /// bits are bold because they're the ones used most often, and executable
    /// files are underlined to make them stand out more.
    fn permissions_string(&self) -> Cell {
        let bits = self.stat.perm;
        let executable_colour = match self.stat.kind {
            io::FileType::RegularFile => Green.bold().underline(),
            _ => Green.bold(),
        };

        let string = format!("{}{}{}{}{}{}{}{}{}{}",
            self.type_char(),
            File::permission_bit(&bits, io::USER_READ,     "r", Yellow.bold()),
            File::permission_bit(&bits, io::USER_WRITE,    "w", Red.bold()),
            File::permission_bit(&bits, io::USER_EXECUTE,  "x", executable_colour),
            File::permission_bit(&bits, io::GROUP_READ,    "r", Yellow.normal()),
            File::permission_bit(&bits, io::GROUP_WRITE,   "w", Red.normal()),
            File::permission_bit(&bits, io::GROUP_EXECUTE, "x", Green.normal()),
            File::permission_bit(&bits, io::OTHER_READ,    "r", Yellow.normal()),
            File::permission_bit(&bits, io::OTHER_WRITE,   "w", Red.normal()),
            File::permission_bit(&bits, io::OTHER_EXECUTE, "x", Green.normal()),
       );

        Cell { text: string, length: 10 }
    }

    /// Helper method for the permissions string.
    fn permission_bit(bits: &io::FilePermission, bit: io::FilePermission, character: &'static str, style: Style) -> ANSIString<'static> {
        if bits.contains(bit) {
            style.paint(character)
        }
        else {
            GREY.paint("-")
        }
    }

    /// For this file, return a vector of alternate file paths that, if any of
    /// them exist, mean that *this* file should be coloured as `Compiled`.
    ///
    /// The point of this is to highlight compiled files such as `foo.o` when
    /// their source file `foo.c` exists in the same directory. It's too
    /// dangerous to highlight *all* compiled, so the paths in this vector
    /// are checked for existence first: for example, `foo.js` is perfectly
    /// valid without `foo.coffee`.
    pub fn get_source_files(&self) -> Vec<Path> {
        if let Some(ref ext) = self.ext {
            match ext.as_slice() {
                "class" => vec![self.path.with_extension("java")],  // Java
                "css"   => vec![self.path.with_extension("sass"),   self.path.with_extension("less")],  // SASS, Less
                "elc"   => vec![self.path.with_extension("el")],    // Emacs Lisp
                "hi"    => vec![self.path.with_extension("hs")],    // Haskell
                "js"    => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")],  // CoffeeScript, TypeScript
                "o"     => vec![self.path.with_extension("c"),      self.path.with_extension("cpp")], // C, C++
                "pyc"   => vec![self.path.with_extension("py")],    // Python

                "aux" => vec![self.path.with_extension("tex")],  // TeX: auxiliary file
                "bbl" => vec![self.path.with_extension("tex")],  // BibTeX bibliography file
                "blg" => vec![self.path.with_extension("tex")],  // BibTeX log file
                "lof" => vec![self.path.with_extension("tex")],  // TeX list of figures
                "log" => vec![self.path.with_extension("tex")],  // TeX log file
                "lot" => vec![self.path.with_extension("tex")],  // TeX list of tables
                "toc" => vec![self.path.with_extension("tex")],  // TeX table of contents

                _ => vec![],  // No source files if none of the above
            }
        }
        else {
            vec![]  // No source files if there's no extension, either!
        }
    }
}

/// Extract an extension from a string, if one is present.
///
/// The extension is the series of characters after the last dot. This
/// deliberately counts dotfiles, so the ".git" folder has the extension "git".
fn ext<'a>(name: &'a str) -> Option<String> {
    name.rfind('.').map(|p| name[p+1..].to_string())
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use {Future, Wake, Tokens};

/// A future which "fuse"s an future once it's been resolved.
///
/// Normally futures can behave unpredictable once they're used after a future
/// has been resolved, but `Fuse` is always defined to return `None` from `poll`
/// after it has succeeded, and after it has succeeded all future calls to
/// `schedule` will be ignored.
pub struct Fuse<A> {
    future: A,
    done: bool,
}

pub fn new<A: Future>(f: A) -> Fuse<A> {
    Fuse {
        future: f,
        done: false,
    }
}

impl<A: Future> Future for Fuse<A> {
    type Item = A::Item;
    type Error = A::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<A::Item, A::Error>> {
        if self.done {
            None
        } else {
            let res = self.future.poll(tokens);
            self.done = res.is_some();
            return res
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if !self.done {
            self.future.schedule(wake);
        }
    }
}
<commit_msg>Drop the future early in Fuse<commit_after>use std::sync::Arc;

use {Future, Wake, Tokens};

/// A future which "fuse"s an future once it's been resolved.
///
/// Normally futures can behave unpredictable once they're used after a future
/// has been resolved, but `Fuse` is always defined to return `None` from `poll`
/// after it has succeeded, and after it has succeeded all future calls to
/// `schedule` will be ignored.
pub struct Fuse<A> {
    future: Option<A>,
}

pub fn new<A: Future>(f: A) -> Fuse<A> {
    Fuse {
        future: Some(f),
    }
}

impl<A: Future> Future for Fuse<A> {
    type Item = A::Item;
    type Error = A::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<A::Item, A::Error>> {
        let ret = self.future.as_mut().and_then(|f| f.poll(tokens));
        if ret.is_some() {
            self.future = None;
        }
        return ret
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if let Some(ref mut f) = self.future {
            f.schedule(wake);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>add free method<commit_after>use libc::c_char;
use std::ffi::CString;

#[no_mangle]
pub extern fn free(s: *mut c_char) {
  unsafe {
    if s.is_null() { return }
    CString::from_raw(s)
  };
}
<|endoftext|>


<commit_before><commit_msg>Update main.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed mutable vec warning<commit_after><|endoftext|>


<commit_before><commit_msg>Added download support.<commit_after><|endoftext|>


<commit_before>extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::old_io::fs;
use std::old_io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_int, c_uchar, c_void};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(&mut |&: _| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let selection = project_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&project_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    project_tree.append_column(&column);

    let mut project_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_buttons.set_size_request(-1, -1);
    build_buttons.add(&run_button);
    build_buttons.add(&build_button);
    build_buttons.add(&test_button);
    build_buttons.add(&clean_button);
    build_buttons.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_buttons, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut project_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::new_project(&mut state, &mut project_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::import_project(&mut state, &mut project_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(&mut || {
        ::projects::save_selection(&mut state);
    }));
    project_tree.connect(gtk::signals::RowCollapsed::new(&mut |iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    project_tree.connect(gtk::signals::RowExpanded::new(&mut |iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn nvim_attach(fd: ffi::c_int) {
    let mut arr = neovim::Array::new();
    arr.add_integer(80);
    arr.add_integer(24);
    arr.add_boolean(true);
    let msg = neovim::serialize_message(1, "ui_attach", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
    unsafe { ffi::write(fd, msg_ptr, msg.len() as ffi::size_t) };
}

fn nvim_execute(fd: ffi::c_int, command: &str) {
    let mut arr = neovim::Array::new();
    arr.add_string(command);
    let msg = neovim::serialize_message(1, "vim_command", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
    unsafe { ffi::write(fd, msg_ptr, msg.len() as ffi::size_t) };
}

fn receive_message(fd: ffi::c_int) -> Option<neovim::Array> {
    let mut buf : [ffi::c_uchar; 1024] = [0; 1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return None;
    }
    unsafe {
        let v = Vec::from_raw_buf(buf.as_ptr(), n as usize);
        let s = String::from_utf8_unchecked(v);
        Some(neovim::deserialize_message(&s))
    }
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::old_io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::old_io::fs::mkdir_recursive(&res_path.dir_path(), ::std::old_io::USER_DIR).ok();
                    ::std::old_io::File::create(&res_path).write_all(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::env::var("VIM").is_none() {
        ::std::env::set_var("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::old_io::File::create(&config_file).write_all(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_gui : [ffi::c_int; 2] = [0; 2]; // to nvim from gui
    let mut gui_nvim : [ffi::c_int; 2] = [0; 2]; // to gui from nvim
    unsafe {
        ffi::pipe(nvim_gui.as_mut_ptr());
        ffi::pipe(gui_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // start communicating with nvim
            nvim_attach(nvim_gui[1]);

            // listen for bufread events
            nvim_execute(nvim_gui[1], "au BufRead * call rpcnotify(1, \"bufread\", bufname(\"\"))");

            // receive messages
            while let Some(recv_arr) = receive_message(gui_nvim[0]) {
                if recv_arr.len() > 0 {
                    println!("Received: {:?}", recv_arr);
                }
            }
        });

        // start the gui
        gui_main(&mut pty, gui_nvim[0], gui_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // start nvim
        let mut args = Vec::new();
        for arg in ::std::env::args() {
            args.push(arg.into_string().unwrap());
        }
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::main_setup(args);
        neovim::channel_from_fds(nvim_gui[0], gui_nvim[1]);
        neovim::main_loop();
    }
}
<commit_msg>Pass args as reference<commit_after>extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::old_io::fs;
use std::old_io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_int, c_uchar, c_void};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(&mut |&: _| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let selection = project_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&project_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    project_tree.append_column(&column);

    let mut project_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_buttons.set_size_request(-1, -1);
    build_buttons.add(&run_button);
    build_buttons.add(&build_button);
    build_buttons.add(&test_button);
    build_buttons.add(&clean_button);
    build_buttons.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_buttons, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut project_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::new_project(&mut state, &mut project_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::import_project(&mut state, &mut project_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(&mut || {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(&mut || {
        ::projects::save_selection(&mut state);
    }));
    project_tree.connect(gtk::signals::RowCollapsed::new(&mut |iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    project_tree.connect(gtk::signals::RowExpanded::new(&mut |iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn nvim_attach(fd: ffi::c_int) {
    let mut arr = neovim::Array::new();
    arr.add_integer(80);
    arr.add_integer(24);
    arr.add_boolean(true);
    let msg = neovim::serialize_message(1, "ui_attach", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
    unsafe { ffi::write(fd, msg_ptr, msg.len() as ffi::size_t) };
}

fn nvim_execute(fd: ffi::c_int, command: &str) {
    let mut arr = neovim::Array::new();
    arr.add_string(command);
    let msg = neovim::serialize_message(1, "vim_command", &arr);
    let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
    unsafe { ffi::write(fd, msg_ptr, msg.len() as ffi::size_t) };
}

fn receive_message(fd: ffi::c_int) -> Option<neovim::Array> {
    let mut buf : [ffi::c_uchar; 1024] = [0; 1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return None;
    }
    unsafe {
        let v = Vec::from_raw_buf(buf.as_ptr(), n as usize);
        let s = String::from_utf8_unchecked(v);
        Some(neovim::deserialize_message(&s))
    }
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::old_io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::old_io::fs::mkdir_recursive(&res_path.dir_path(), ::std::old_io::USER_DIR).ok();
                    ::std::old_io::File::create(&res_path).write_all(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::env::var("VIM").is_none() {
        ::std::env::set_var("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::old_io::File::create(&config_file).write_all(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_gui : [ffi::c_int; 2] = [0; 2]; // to nvim from gui
    let mut gui_nvim : [ffi::c_int; 2] = [0; 2]; // to gui from nvim
    unsafe {
        ffi::pipe(nvim_gui.as_mut_ptr());
        ffi::pipe(gui_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // start communicating with nvim
            nvim_attach(nvim_gui[1]);

            // listen for bufread events
            nvim_execute(nvim_gui[1], "au BufRead * call rpcnotify(1, \"bufread\", bufname(\"\"))");

            // receive messages
            while let Some(recv_arr) = receive_message(gui_nvim[0]) {
                if recv_arr.len() > 0 {
                    println!("Received: {:?}", recv_arr);
                }
            }
        });

        // start the gui
        gui_main(&mut pty, gui_nvim[0], gui_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // start nvim
        let mut args = Vec::new();
        for arg in ::std::env::args() {
            args.push(arg.into_string().unwrap());
        }
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::main_setup(&args);
        neovim::channel_from_fds(nvim_gui[0], gui_nvim[1]);
        neovim::main_loop();
    }
}
<|endoftext|>


<commit_before><commit_msg>try to fill the numbers. works halfway<commit_after><|endoftext|>