<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)]

register_long_diagnostics! {

E0046: r##"
When trying to make some type implement a trait `Foo`, you must, at minimum,
provide implementations for all of `Foo`'s required methods (meaning the
methods that do not have default implementations), as well as any required
trait items like associated types or constants.
"##,

E0054: r##"
It is not allowed to cast to a bool. If you are trying to cast a numeric type
to a bool, you can compare it with zero instead:

```
let x = 5;

// Ok
let x_is_nonzero = x != 0;

// Not allowed, won't compile
let x_is_nonzero = x as bool;
```
"##,

E0062: r##"
This error indicates that during an attempt to build a struct or struct-like
enum variant, one of the fields was specified more than once.
"##,

E0063: r##"
This error indicates that during an attempt to build a struct or struct-like
enum variant, one of the fields was not provided.
"##,

E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
making them impossible to tell apart.

```
// Good.
enum Enum {
    P,
    X = 3,
    Y = 5
}

// Bad.
enum Enum {
    P = 3,
    X = 3,
    Y = 5
}
```

Note that variants without a manually specified discriminant are numbered from
top to bottom starting from 0, so clashes can occur with seemingly unrelated
variants.

```
enum Bad {
    X,
    Y = 0
}
```

Here `X` will have already been assigned the discriminant 0 by the time `Y` is
encountered, so a conflict occurs.
"##,

E0082: r##"
The default type for enum discriminants is `isize`, but it can be adjusted by
adding the `repr` attribute to the enum declaration. This error indicates that
an integer literal given as a discriminant is not a member of the discriminant
type. For example:

```
#[repr(u8)]
enum Thing {
    A = 1024,
    B = 5
}
```

Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
invalid. You may want to change representation types to fix this, or else change
invalid discriminant values so that they fit within the existing type.

Note also that without a representation manually defined, the compiler will
optimize by using the smallest integer type possible.
"##,

E0083: r##"
At present, it's not possible to define a custom representation for an enum with
a single variant. As a workaround you can add a `Dummy` variant.

See: https://github.com/rust-lang/rust/issues/10292
"##,

E0084: r##"
It is impossible to define an integer type to be used to represent zero-variant
enum values because there are no zero-variant enum values. There is no way to
construct an instance of the following type using only safe code:

```
enum Empty {}
```
"##

}

register_diagnostics! {
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0029,
    E0030,
    E0031,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0040, // explicit use of destructor method
    E0044,
    E0045,
    E0049,
    E0050,
    E0053,
    E0055,
    E0057,
    E0059,
    E0060,
    E0061,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0101,
    E0102,
    E0103,
    E0104,
    E0106,
    E0107,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0123,
    E0124,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0141,
    E0159,
    E0163,
    E0164,
    E0166,
    E0167,
    E0168,
    E0172,
    E0173, // manual implementations of unboxed closure traits are experimental
    E0174, // explicit use of unboxed closure methods are experimental
    E0178,
    E0182,
    E0183,
    E0184,
    E0185,
    E0186,
    E0187, // can't infer the kind of the closure
    E0188, // types differ in mutability
    E0189, // can only cast a boxed pointer to a boxed object
    E0190, // can only cast a &-pointer to an &-object
    E0191, // value of the associated type must be specified
    E0192, // negative imples are allowed just for `Send` and `Sync`
    E0193, // cannot bound type where clause bounds may only be attached to types
           // involving type parameters
    E0194,
    E0195, // lifetime parameters or bounds on method do not match the trait declaration
    E0196, // cannot determine a type for this closure
    E0197, // inherent impls cannot be declared as unsafe
    E0198, // negative implementations are not unsafe
    E0199, // implementing trait is not unsafe
    E0200, // trait requires an `unsafe impl` declaration
    E0201, // duplicate method in trait impl
    E0202, // associated items are not allowed in inherent impls
    E0203, // type parameter has more than one relaxed default bound,
           // and only one is supported
    E0204, // trait `Copy` may not be implemented for this type; field
           // does not implement `Copy`
    E0205, // trait `Copy` may not be implemented for this type; variant
           // does not implement `copy`
    E0206, // trait `Copy` may not be implemented for this type; type is
           // not a structure or enumeration
    E0207, // type parameter is not constrained by the impl trait, self type, or predicate
    E0208,
    E0209, // builtin traits can only be implemented on structs or enums
    E0210, // type parameter is not constrained by any local type
    E0211,
    E0212, // cannot extract an associated type from a higher-ranked trait bound
    E0213, // associated types are not accepted in this context
    E0214, // parenthesized parameters may only be used with a trait
    E0215, // angle-bracket notation is not stable with `Fn`
    E0216, // parenthetical notation is only stable with `Fn`
    E0217, // ambiguous associated type, defined in multiple supertraits
    E0218, // no associated type defined
    E0219, // associated type defined in higher-ranked supertrait
    E0220, // associated type not found for type parameter
    E0221, // ambiguous associated type in bounds
    E0222, // variadic function must have C calling convention
    E0223, // ambiguous associated type
    E0224, // at least one non-builtin train is required for an object type
    E0225, // only the builtin traits can be used as closure or object bounds
    E0226, // only a single explicit lifetime bound is permitted
    E0227, // ambiguous lifetime bound, explicit lifetime bound required
    E0228, // explicit lifetime bound required
    E0229, // associated type bindings are not allowed here
    E0230, // there is no type parameter on trait
    E0231, // only named substitution parameters are allowed
    E0232, // this attribute must have a value
    E0233,
    E0234, // `for` loop expression has type which does not implement the `Iterator` trait
    E0235, // structure constructor specifies a structure of type but
    E0236, // no lang item for range syntax
    E0237, // no lang item for range syntax
    E0238, // parenthesized parameters may only be used with a trait
    E0239, // `next` method of `Iterator` trait has unexpected type
    E0240,
    E0241,
    E0242, // internal error looking up a definition
    E0243, // wrong number of type arguments
    E0244, // wrong number of type arguments
    E0245, // not a trait
    E0246, // illegal recursive type
    E0247, // found module name used as a type
    E0248, // found value name used as a type
    E0249, // expected constant expr for array length
    E0250, // expected constant expr for array length
    E0318, // can't create default impls for traits outside their crates
    E0319, // trait impls for defaulted traits allowed just for structs/enums
    E0320, // recursive overflow during dropck
    E0321, // extended coherence rules for defaulted traits violated
    E0322, // cannot implement Sized explicitly
    E0323, // implemented an associated const when another trait item expected
    E0324, // implemented a method when another trait item expected
    E0325, // implemented an associated type when another trait item expected
    E0326, // associated const implemented with different type from trait
    E0327, // referred to method instead of constant in match pattern
    E0366, // dropck forbid specialization to concrete type or region
    E0367, // dropck forbid specialization to predicate not in struct/enum
    E0368, // binary operation `<op>=` cannot be applied to types
    E0369, // binary operation `<op>` cannot be applied to types
    E0371, // impl Trait for Trait is illegal
    E0372  // impl Trait for Trait where Trait is not object safe
}
<commit_msg>Change E0062 and E0063 to say each field should be specified once.<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)]

register_long_diagnostics! {

E0046: r##"
When trying to make some type implement a trait `Foo`, you must, at minimum,
provide implementations for all of `Foo`'s required methods (meaning the
methods that do not have default implementations), as well as any required
trait items like associated types or constants.
"##,

E0054: r##"
It is not allowed to cast to a bool. If you are trying to cast a numeric type
to a bool, you can compare it with zero instead:

```
let x = 5;

// Ok
let x_is_nonzero = x != 0;

// Not allowed, won't compile
let x_is_nonzero = x as bool;
```
"##,

E0062: r##"
This error indicates that during an attempt to build a struct or struct-like
enum variant, one of the fields was specified more than once. Each field should
be specified exactly one time.
"##,

E0063: r##"
This error indicates that during an attempt to build a struct or struct-like
enum variant, one of the fields was not provided. Each field should be specified
exactly once.
"##,

E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
making them impossible to tell apart.

```
// Good.
enum Enum {
    P,
    X = 3,
    Y = 5
}

// Bad.
enum Enum {
    P = 3,
    X = 3,
    Y = 5
}
```

Note that variants without a manually specified discriminant are numbered from
top to bottom starting from 0, so clashes can occur with seemingly unrelated
variants.

```
enum Bad {
    X,
    Y = 0
}
```

Here `X` will have already been assigned the discriminant 0 by the time `Y` is
encountered, so a conflict occurs.
"##,

E0082: r##"
The default type for enum discriminants is `isize`, but it can be adjusted by
adding the `repr` attribute to the enum declaration. This error indicates that
an integer literal given as a discriminant is not a member of the discriminant
type. For example:

```
#[repr(u8)]
enum Thing {
    A = 1024,
    B = 5
}
```

Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
invalid. You may want to change representation types to fix this, or else change
invalid discriminant values so that they fit within the existing type.

Note also that without a representation manually defined, the compiler will
optimize by using the smallest integer type possible.
"##,

E0083: r##"
At present, it's not possible to define a custom representation for an enum with
a single variant. As a workaround you can add a `Dummy` variant.

See: https://github.com/rust-lang/rust/issues/10292
"##,

E0084: r##"
It is impossible to define an integer type to be used to represent zero-variant
enum values because there are no zero-variant enum values. There is no way to
construct an instance of the following type using only safe code:

```
enum Empty {}
```
"##

}

register_diagnostics! {
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0029,
    E0030,
    E0031,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0040, // explicit use of destructor method
    E0044,
    E0045,
    E0049,
    E0050,
    E0053,
    E0055,
    E0057,
    E0059,
    E0060,
    E0061,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0101,
    E0102,
    E0103,
    E0104,
    E0106,
    E0107,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0123,
    E0124,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0141,
    E0159,
    E0163,
    E0164,
    E0166,
    E0167,
    E0168,
    E0172,
    E0173, // manual implementations of unboxed closure traits are experimental
    E0174, // explicit use of unboxed closure methods are experimental
    E0178,
    E0182,
    E0183,
    E0184,
    E0185,
    E0186,
    E0187, // can't infer the kind of the closure
    E0188, // types differ in mutability
    E0189, // can only cast a boxed pointer to a boxed object
    E0190, // can only cast a &-pointer to an &-object
    E0191, // value of the associated type must be specified
    E0192, // negative imples are allowed just for `Send` and `Sync`
    E0193, // cannot bound type where clause bounds may only be attached to types
           // involving type parameters
    E0194,
    E0195, // lifetime parameters or bounds on method do not match the trait declaration
    E0196, // cannot determine a type for this closure
    E0197, // inherent impls cannot be declared as unsafe
    E0198, // negative implementations are not unsafe
    E0199, // implementing trait is not unsafe
    E0200, // trait requires an `unsafe impl` declaration
    E0201, // duplicate method in trait impl
    E0202, // associated items are not allowed in inherent impls
    E0203, // type parameter has more than one relaxed default bound,
           // and only one is supported
    E0204, // trait `Copy` may not be implemented for this type; field
           // does not implement `Copy`
    E0205, // trait `Copy` may not be implemented for this type; variant
           // does not implement `copy`
    E0206, // trait `Copy` may not be implemented for this type; type is
           // not a structure or enumeration
    E0207, // type parameter is not constrained by the impl trait, self type, or predicate
    E0208,
    E0209, // builtin traits can only be implemented on structs or enums
    E0210, // type parameter is not constrained by any local type
    E0211,
    E0212, // cannot extract an associated type from a higher-ranked trait bound
    E0213, // associated types are not accepted in this context
    E0214, // parenthesized parameters may only be used with a trait
    E0215, // angle-bracket notation is not stable with `Fn`
    E0216, // parenthetical notation is only stable with `Fn`
    E0217, // ambiguous associated type, defined in multiple supertraits
    E0218, // no associated type defined
    E0219, // associated type defined in higher-ranked supertrait
    E0220, // associated type not found for type parameter
    E0221, // ambiguous associated type in bounds
    E0222, // variadic function must have C calling convention
    E0223, // ambiguous associated type
    E0224, // at least one non-builtin train is required for an object type
    E0225, // only the builtin traits can be used as closure or object bounds
    E0226, // only a single explicit lifetime bound is permitted
    E0227, // ambiguous lifetime bound, explicit lifetime bound required
    E0228, // explicit lifetime bound required
    E0229, // associated type bindings are not allowed here
    E0230, // there is no type parameter on trait
    E0231, // only named substitution parameters are allowed
    E0232, // this attribute must have a value
    E0233,
    E0234, // `for` loop expression has type which does not implement the `Iterator` trait
    E0235, // structure constructor specifies a structure of type but
    E0236, // no lang item for range syntax
    E0237, // no lang item for range syntax
    E0238, // parenthesized parameters may only be used with a trait
    E0239, // `next` method of `Iterator` trait has unexpected type
    E0240,
    E0241,
    E0242, // internal error looking up a definition
    E0243, // wrong number of type arguments
    E0244, // wrong number of type arguments
    E0245, // not a trait
    E0246, // illegal recursive type
    E0247, // found module name used as a type
    E0248, // found value name used as a type
    E0249, // expected constant expr for array length
    E0250, // expected constant expr for array length
    E0318, // can't create default impls for traits outside their crates
    E0319, // trait impls for defaulted traits allowed just for structs/enums
    E0320, // recursive overflow during dropck
    E0321, // extended coherence rules for defaulted traits violated
    E0322, // cannot implement Sized explicitly
    E0323, // implemented an associated const when another trait item expected
    E0324, // implemented a method when another trait item expected
    E0325, // implemented an associated type when another trait item expected
    E0326, // associated const implemented with different type from trait
    E0327, // referred to method instead of constant in match pattern
    E0366, // dropck forbid specialization to concrete type or region
    E0367, // dropck forbid specialization to predicate not in struct/enum
    E0368, // binary operation `<op>=` cannot be applied to types
    E0369, // binary operation `<op>` cannot be applied to types
    E0371, // impl Trait for Trait is illegal
    E0372  // impl Trait for Trait where Trait is not object safe
}
<|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.

use prelude::v1::*;
use io::prelude::*;

use io;

#[cfg(target_pointer_width = "64")]
pub const HEX_WIDTH: usize = 18;

#[cfg(target_pointer_width = "32")]
pub const HEX_WIDTH: usize = 10;

// All rust symbols are in theory lists of "::"-separated identifiers. Some
// assemblers, however, can't handle these characters in symbol names. To get
// around this, we use C++-style mangling. The mangling method is:
//
// 1. Prefix the symbol with "_ZN"
// 2. For each element of the path, emit the length plus the element
// 3. End the path with "E"
//
// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
//
// We're the ones printing our backtraces, so we can't rely on anything else to
// demangle our symbols. It's *much* nicer to look at demangled symbols, so
// this function is implemented to give us nice pretty output.
//
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> {
    // First validate the symbol. If it doesn't look like anything we're
    // expecting, we just print it literally. Note that we must handle non-rust
    // symbols because we could have any function in the backtrace.
    let mut valid = true;
    let mut inner = s;
    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
        inner = &s[3 .. s.len() - 1];
    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
        inner = &s[2 .. s.len() - 1];
    } else {
        valid = false;
    }

    if valid {
        let mut chars = inner.chars();
        while valid {
            let mut i = 0;
            for c in chars.by_ref() {
                if c.is_numeric() {
                    i = i * 10 + c as usize - '0' as usize;
                } else {
                    break
                }
            }
            if i == 0 {
                valid = chars.next().is_none();
                break
            } else if chars.by_ref().take(i - 1).count() != i - 1 {
                valid = false;
            }
        }
    }

    // Alright, let's do this.
    if !valid {
        try!(writer.write_all(s.as_bytes()));
    } else {
        let mut first = true;
        while !inner.is_empty() {
            if !first {
                try!(writer.write_all(b"::"));
            } else {
                first = false;
            }
            let mut rest = inner;
            while rest.char_at(0).is_numeric() {
                rest = &rest[1..];
            }
            let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
            inner = &rest[i..];
            rest = &rest[..i];
            while !rest.is_empty() {
                if rest.starts_with("$") {
                    macro_rules! demangle {
                        ($($pat:expr, => $demangled:expr),*) => ({
                            $(if rest.starts_with($pat) {
                                try!(writer.write_all($demangled));
                                rest = &rest[$pat.len()..];
                              } else)*
                            {
                                try!(writer.write_all(rest.as_bytes()));
                                break;
                            }

                        })
                    }

                    // see src/librustc/back/link.rs for these mappings
                    demangle! (
                        "$SP$", => b"@",
                        "$BP$", => b"*",
                        "$RF$", => b"&",
                        "$LT$", => b"<",
                        "$GT$", => b">",
                        "$LP$", => b"(",
                        "$RP$", => b")",
                        "$C$", => b",",

                        // in theory we can demangle any Unicode code point, but
                        // for simplicity we just catch the common ones.
                        "$u7e$", => b"~",
                        "$u20$", => b" ",
                        "$u27$", => b"'",
                        "$u5b$", => b"[",
                        "$u5d$", => b"]"
                    )
                } else {
                    let idx = match rest.find('$') {
                        None => rest.len(),
                        Some(i) => i,
                    };
                    try!(writer.write_all(rest[..idx].as_bytes()));
                    rest = &rest[idx..];
                }
            }
        }
    }

    Ok(())
}
<commit_msg>Rollup merge of #26132 - astraw:fix-demangle-comment, r=alexcrichton<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.

use prelude::v1::*;
use io::prelude::*;

use io;

#[cfg(target_pointer_width = "64")]
pub const HEX_WIDTH: usize = 18;

#[cfg(target_pointer_width = "32")]
pub const HEX_WIDTH: usize = 10;

// All rust symbols are in theory lists of "::"-separated identifiers. Some
// assemblers, however, can't handle these characters in symbol names. To get
// around this, we use C++-style mangling. The mangling method is:
//
// 1. Prefix the symbol with "_ZN"
// 2. For each element of the path, emit the length plus the element
// 3. End the path with "E"
//
// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
//
// We're the ones printing our backtraces, so we can't rely on anything else to
// demangle our symbols. It's *much* nicer to look at demangled symbols, so
// this function is implemented to give us nice pretty output.
//
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> {
    // First validate the symbol. If it doesn't look like anything we're
    // expecting, we just print it literally. Note that we must handle non-rust
    // symbols because we could have any function in the backtrace.
    let mut valid = true;
    let mut inner = s;
    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
        inner = &s[3 .. s.len() - 1];
    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
        inner = &s[2 .. s.len() - 1];
    } else {
        valid = false;
    }

    if valid {
        let mut chars = inner.chars();
        while valid {
            let mut i = 0;
            for c in chars.by_ref() {
                if c.is_numeric() {
                    i = i * 10 + c as usize - '0' as usize;
                } else {
                    break
                }
            }
            if i == 0 {
                valid = chars.next().is_none();
                break
            } else if chars.by_ref().take(i - 1).count() != i - 1 {
                valid = false;
            }
        }
    }

    // Alright, let's do this.
    if !valid {
        try!(writer.write_all(s.as_bytes()));
    } else {
        let mut first = true;
        while !inner.is_empty() {
            if !first {
                try!(writer.write_all(b"::"));
            } else {
                first = false;
            }
            let mut rest = inner;
            while rest.char_at(0).is_numeric() {
                rest = &rest[1..];
            }
            let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
            inner = &rest[i..];
            rest = &rest[..i];
            while !rest.is_empty() {
                if rest.starts_with("$") {
                    macro_rules! demangle {
                        ($($pat:expr, => $demangled:expr),*) => ({
                            $(if rest.starts_with($pat) {
                                try!(writer.write_all($demangled));
                                rest = &rest[$pat.len()..];
                              } else)*
                            {
                                try!(writer.write_all(rest.as_bytes()));
                                break;
                            }

                        })
                    }

                    // see src/librustc/back/link.rs for these mappings
                    demangle! (
                        "$SP$", => b"@",
                        "$BP$", => b"*",
                        "$RF$", => b"&",
                        "$LT$", => b"<",
                        "$GT$", => b">",
                        "$LP$", => b"(",
                        "$RP$", => b")",
                        "$C$", => b",",

                        // in theory we can demangle any Unicode code point, but
                        // for simplicity we just catch the common ones.
                        "$u7e$", => b"~",
                        "$u20$", => b" ",
                        "$u27$", => b"'",
                        "$u5b$", => b"[",
                        "$u5d$", => b"]"
                    )
                } else {
                    let idx = match rest.find('$') {
                        None => rest.len(),
                        Some(i) => i,
                    };
                    try!(writer.write_all(rest[..idx].as_bytes()));
                    rest = &rest[idx..];
                }
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use super::Result;
use solid::Solid;

pub const TAG_LENGTH: usize = 27;

#[derive(Debug)]
pub struct TransactionMessage {
  hash: String,
  address_hash: String,
  value: i64,
  tag: String,
  timestamp: f64,
  current_index: i32,
  last_index: i32,
  bundle_hash: String,
  trunk_hash: String,
  branch_hash: String,
  arrival: f64,
  is_milestone: bool,
  solid: Solid,
}

impl TransactionMessage {
  pub fn parse(
    source: &str,
    milestone_address: &str,
    milestone_start_index: &str,
  ) -> Result<Self> {
    let chunks: Vec<&str> = source.split(' ').collect();
    let hash = chunks[1].to_owned();
    let address_hash = chunks[2].to_owned();
    let value = chunks[3].parse()?;
    let tag = chunks[4][..TAG_LENGTH].to_owned();
    let timestamp = chunks[5].parse()?;
    let current_index = chunks[6].parse()?;
    let last_index = chunks[7].parse()?;
    let bundle_hash = chunks[8].to_owned();
    let trunk_hash = chunks[9].to_owned();
    let branch_hash = chunks[10].to_owned();
    let arrival = chunks[11].parse()?;
    let is_milestone = address_hash == milestone_address;
    let solid = if is_milestone && tag == milestone_start_index {
      Solid::Complete
    } else {
      Solid::None
    };
    Ok(Self {
      hash,
      address_hash,
      value,
      tag,
      timestamp,
      current_index,
      last_index,
      bundle_hash,
      trunk_hash,
      branch_hash,
      arrival,
      is_milestone,
      solid,
    })
  }

  impl_getter!(hash, &str);
  impl_getter!(address_hash, &str);
  impl_getter!(value, i64);
  impl_getter!(tag, &str);
  impl_getter!(timestamp, f64);
  impl_getter!(current_index, i32);
  impl_getter!(last_index, i32);
  impl_getter!(bundle_hash, &str);
  impl_getter!(trunk_hash, &str);
  impl_getter!(branch_hash, &str);
  impl_getter!(arrival, f64);
  impl_getter!(is_milestone, bool);
  impl_getter!(solid, Solid);
}
<commit_msg>Normalize `arrival` values<commit_after>use super::Result;
use solid::Solid;

pub const TAG_LENGTH: usize = 27;

#[derive(Debug)]
pub struct TransactionMessage {
  hash: String,
  address_hash: String,
  value: i64,
  tag: String,
  timestamp: f64,
  current_index: i32,
  last_index: i32,
  bundle_hash: String,
  trunk_hash: String,
  branch_hash: String,
  arrival: f64,
  is_milestone: bool,
  solid: Solid,
}

impl TransactionMessage {
  pub fn parse(
    source: &str,
    milestone_address: &str,
    milestone_start_index: &str,
  ) -> Result<Self> {
    let chunks: Vec<&str> = source.split(' ').collect();
    let hash = chunks[1].to_owned();
    let address_hash = chunks[2].to_owned();
    let value = chunks[3].parse()?;
    let tag = chunks[4][..TAG_LENGTH].to_owned();
    let timestamp = chunks[5].parse()?;
    let current_index = chunks[6].parse()?;
    let last_index = chunks[7].parse()?;
    let bundle_hash = chunks[8].to_owned();
    let trunk_hash = chunks[9].to_owned();
    let branch_hash = chunks[10].to_owned();
    let arrival = normalize_timestamp(chunks[11].parse()?);
    let is_milestone = address_hash == milestone_address;
    let solid = if is_milestone && tag == milestone_start_index {
      Solid::Complete
    } else {
      Solid::None
    };
    Ok(Self {
      hash,
      address_hash,
      value,
      tag,
      timestamp,
      current_index,
      last_index,
      bundle_hash,
      trunk_hash,
      branch_hash,
      arrival,
      is_milestone,
      solid,
    })
  }

  impl_getter!(hash, &str);
  impl_getter!(address_hash, &str);
  impl_getter!(value, i64);
  impl_getter!(tag, &str);
  impl_getter!(timestamp, f64);
  impl_getter!(current_index, i32);
  impl_getter!(last_index, i32);
  impl_getter!(bundle_hash, &str);
  impl_getter!(trunk_hash, &str);
  impl_getter!(branch_hash, &str);
  impl_getter!(arrival, f64);
  impl_getter!(is_milestone, bool);
  impl_getter!(solid, Solid);
}

fn normalize_timestamp(mut timestamp: f64) -> f64 {
  const THRESHOLD: f64 = 1_262_304_000_000.0; // 01.01.2010 in milliseconds
  if timestamp > THRESHOLD {
    timestamp /= 1000.0;
  }
  timestamp
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::Executor;
use anyhow::{ensure, format_err, Result};
use executor_types::BlockExecutor;
use libra_crypto::{hash::PRE_GENESIS_BLOCK_ID, HashValue};
use libra_logger::prelude::*;
use libra_state_view::StateView;
use libra_types::{
    access_path::AccessPath,
    account_config::association_address,
    block_info::{BlockInfo, GENESIS_EPOCH, GENESIS_ROUND, GENESIS_TIMESTAMP_USECS},
    ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
    libra_timestamp::LibraTimestampResource,
    on_chain_config::{config_address, ConfigurationResource},
    transaction::Transaction,
    waypoint::Waypoint,
};
use libra_vm::VMExecutor;
use move_core_types::move_resource::MoveResource;
use std::collections::btree_map::BTreeMap;
use storage_interface::{state_view::VerifiedStateView, DbReaderWriter, TreeState};

pub fn bootstrap_db_if_empty<V: VMExecutor>(
    db: &DbReaderWriter,
    genesis_txn: &Transaction,
) -> Result<Option<Waypoint>> {
    let tree_state = db.reader.get_latest_tree_state()?;
    if !tree_state.is_empty() {
        return Ok(None);
    }

    let committer = calculate_genesis::<V>(db, tree_state, genesis_txn)?;
    let waypoint = committer.waypoint;
    committer.commit()?;
    Ok(Some(waypoint))
}

pub struct GenesisCommitter<V: VMExecutor> {
    executor: Executor<V>,
    ledger_info_with_sigs: LedgerInfoWithSignatures,
    waypoint: Waypoint,
}

impl<V: VMExecutor> GenesisCommitter<V> {
    pub fn new(
        executor: Executor<V>,
        ledger_info_with_sigs: LedgerInfoWithSignatures,
    ) -> Result<Self> {
        let waypoint = Waypoint::new_epoch_boundary(ledger_info_with_sigs.ledger_info())?;

        Ok(Self {
            executor,
            ledger_info_with_sigs,
            waypoint,
        })
    }

    pub fn ledger_info_with_sigs(&self) -> &LedgerInfoWithSignatures {
        &self.ledger_info_with_sigs
    }

    pub fn waypoint(&self) -> Waypoint {
        self.waypoint
    }

    pub fn commit(mut self) -> Result<()> {
        self.executor
            .commit_blocks(vec![genesis_block_id()], self.ledger_info_with_sigs)?;
        info!("Genesis commited.");
        // DB bootstrapped, avoid anything that could fail after this.

        Ok(())
    }
}

pub fn calculate_genesis<V: VMExecutor>(
    db: &DbReaderWriter,
    tree_state: TreeState,
    genesis_txn: &Transaction,
) -> Result<GenesisCommitter<V>> {
    // DB bootstrapper works on either an empty transaction accumulator or an existing block chain.
    // In the very exetreme and sad situation of losing quorum among validators, we refer to the
    // second use case said above.
    let genesis_version = tree_state.num_transactions;
    let mut executor = Executor::<V>::new_on_unbootstrapped_db(db.clone(), tree_state);

    let block_id = HashValue::zero();
    let epoch = if genesis_version == 0 {
        GENESIS_EPOCH
    } else {
        let executor_trees = executor.get_executed_trees(*PRE_GENESIS_BLOCK_ID)?;
        let state_view = executor.get_executed_state_view(&executor_trees);
        get_state_epoch(&state_view)?
    };

    // Create a block with genesis_txn being the only txn. Execute it then commit it immediately.
    let result =
        executor.execute_block((block_id, vec![genesis_txn.clone()]), *PRE_GENESIS_BLOCK_ID)?;

    let root_hash = result.root_hash();
    let next_epoch_state = result
        .epoch_state()
        .as_ref()
        .ok_or_else(|| format_err!("Genesis transaction must emit a epoch change."))?;
    let executed_trees = executor.get_executed_trees(block_id)?;
    let state_view = executor.get_executed_state_view(&executed_trees);
    let timestamp_usecs = if genesis_version == 0 {
        // TODO(aldenhu): fix existing tests before using real timestamp and check on-chain epoch.
        GENESIS_TIMESTAMP_USECS
    } else {
        ensure!(
            epoch + 1 == get_state_epoch(&state_view)?,
            "Genesis txn didn't bump epoch."
        );
        get_state_timestamp(&state_view)?
    };

    let ledger_info_with_sigs = LedgerInfoWithSignatures::new(
        LedgerInfo::new(
            BlockInfo::new(
                epoch,
                GENESIS_ROUND,
                block_id,
                root_hash,
                genesis_version,
                timestamp_usecs,
                Some(next_epoch_state.clone()),
            ),
            HashValue::zero(), /* consensus_data_hash */
        ),
        BTreeMap::default(), /* signatures */
    );

    let committer = GenesisCommitter::new(executor, ledger_info_with_sigs)?;
    info!(
        "Genesis calculated: ledger_info_with_sigs {:?}, waypoint {:?}",
        committer.ledger_info_with_sigs, committer.waypoint,
    );
    Ok(committer)
}

fn get_state_timestamp(state_view: &VerifiedStateView) -> Result<u64> {
    let rsrc_bytes = &state_view
        .get(&AccessPath::new(
            association_address(),
            LibraTimestampResource::resource_path(),
        ))?
        .ok_or_else(|| format_err!("LibraTimestampResource missing."))?;
    let rsrc = lcs::from_bytes::<LibraTimestampResource>(&rsrc_bytes)?;
    Ok(rsrc.libra_timestamp.microseconds)
}

fn get_state_epoch(state_view: &VerifiedStateView) -> Result<u64> {
    let rsrc_bytes = &state_view
        .get(&AccessPath::new(
            config_address(),
            ConfigurationResource::resource_path(),
        ))?
        .ok_or_else(|| format_err!("ConfigurationResource missing."))?;
    let rsrc = lcs::from_bytes::<ConfigurationResource>(&rsrc_bytes)?;
    Ok(rsrc.epoch())
}

fn genesis_block_id() -> HashValue {
    HashValue::zero()
}
<commit_msg>Removing ledger_info_with_sigs from execution/executor/src/db_bootstrapper.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::Executor;
use anyhow::{ensure, format_err, Result};
use executor_types::BlockExecutor;
use libra_crypto::{hash::PRE_GENESIS_BLOCK_ID, HashValue};
use libra_logger::prelude::*;
use libra_state_view::StateView;
use libra_types::{
    access_path::AccessPath,
    account_config::association_address,
    block_info::{BlockInfo, GENESIS_EPOCH, GENESIS_ROUND, GENESIS_TIMESTAMP_USECS},
    ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
    libra_timestamp::LibraTimestampResource,
    on_chain_config::{config_address, ConfigurationResource},
    transaction::Transaction,
    waypoint::Waypoint,
};
use libra_vm::VMExecutor;
use move_core_types::move_resource::MoveResource;
use std::collections::btree_map::BTreeMap;
use storage_interface::{state_view::VerifiedStateView, DbReaderWriter, TreeState};

pub fn bootstrap_db_if_empty<V: VMExecutor>(
    db: &DbReaderWriter,
    genesis_txn: &Transaction,
) -> Result<Option<Waypoint>> {
    let tree_state = db.reader.get_latest_tree_state()?;
    if !tree_state.is_empty() {
        return Ok(None);
    }

    let committer = calculate_genesis::<V>(db, tree_state, genesis_txn)?;
    let waypoint = committer.waypoint;
    committer.commit()?;
    Ok(Some(waypoint))
}

pub struct GenesisCommitter<V: VMExecutor> {
    executor: Executor<V>,
    ledger_info_with_sigs: LedgerInfoWithSignatures,
    waypoint: Waypoint,
}

impl<V: VMExecutor> GenesisCommitter<V> {
    pub fn new(
        executor: Executor<V>,
        ledger_info_with_sigs: LedgerInfoWithSignatures,
    ) -> Result<Self> {
        let waypoint = Waypoint::new_epoch_boundary(ledger_info_with_sigs.ledger_info())?;

        Ok(Self {
            executor,
            ledger_info_with_sigs,
            waypoint,
        })
    }

    pub fn waypoint(&self) -> Waypoint {
        self.waypoint
    }

    pub fn commit(mut self) -> Result<()> {
        self.executor
            .commit_blocks(vec![genesis_block_id()], self.ledger_info_with_sigs)?;
        info!("Genesis commited.");
        // DB bootstrapped, avoid anything that could fail after this.

        Ok(())
    }
}

pub fn calculate_genesis<V: VMExecutor>(
    db: &DbReaderWriter,
    tree_state: TreeState,
    genesis_txn: &Transaction,
) -> Result<GenesisCommitter<V>> {
    // DB bootstrapper works on either an empty transaction accumulator or an existing block chain.
    // In the very exetreme and sad situation of losing quorum among validators, we refer to the
    // second use case said above.
    let genesis_version = tree_state.num_transactions;
    let mut executor = Executor::<V>::new_on_unbootstrapped_db(db.clone(), tree_state);

    let block_id = HashValue::zero();
    let epoch = if genesis_version == 0 {
        GENESIS_EPOCH
    } else {
        let executor_trees = executor.get_executed_trees(*PRE_GENESIS_BLOCK_ID)?;
        let state_view = executor.get_executed_state_view(&executor_trees);
        get_state_epoch(&state_view)?
    };

    // Create a block with genesis_txn being the only txn. Execute it then commit it immediately.
    let result =
        executor.execute_block((block_id, vec![genesis_txn.clone()]), *PRE_GENESIS_BLOCK_ID)?;

    let root_hash = result.root_hash();
    let next_epoch_state = result
        .epoch_state()
        .as_ref()
        .ok_or_else(|| format_err!("Genesis transaction must emit a epoch change."))?;
    let executed_trees = executor.get_executed_trees(block_id)?;
    let state_view = executor.get_executed_state_view(&executed_trees);
    let timestamp_usecs = if genesis_version == 0 {
        // TODO(aldenhu): fix existing tests before using real timestamp and check on-chain epoch.
        GENESIS_TIMESTAMP_USECS
    } else {
        ensure!(
            epoch + 1 == get_state_epoch(&state_view)?,
            "Genesis txn didn't bump epoch."
        );
        get_state_timestamp(&state_view)?
    };

    let ledger_info_with_sigs = LedgerInfoWithSignatures::new(
        LedgerInfo::new(
            BlockInfo::new(
                epoch,
                GENESIS_ROUND,
                block_id,
                root_hash,
                genesis_version,
                timestamp_usecs,
                Some(next_epoch_state.clone()),
            ),
            HashValue::zero(), /* consensus_data_hash */
        ),
        BTreeMap::default(), /* signatures */
    );

    let committer = GenesisCommitter::new(executor, ledger_info_with_sigs)?;
    info!(
        "Genesis calculated: ledger_info_with_sigs {:?}, waypoint {:?}",
        committer.ledger_info_with_sigs, committer.waypoint,
    );
    Ok(committer)
}

fn get_state_timestamp(state_view: &VerifiedStateView) -> Result<u64> {
    let rsrc_bytes = &state_view
        .get(&AccessPath::new(
            association_address(),
            LibraTimestampResource::resource_path(),
        ))?
        .ok_or_else(|| format_err!("LibraTimestampResource missing."))?;
    let rsrc = lcs::from_bytes::<LibraTimestampResource>(&rsrc_bytes)?;
    Ok(rsrc.libra_timestamp.microseconds)
}

fn get_state_epoch(state_view: &VerifiedStateView) -> Result<u64> {
    let rsrc_bytes = &state_view
        .get(&AccessPath::new(
            config_address(),
            ConfigurationResource::resource_path(),
        ))?
        .ok_or_else(|| format_err!("ConfigurationResource missing."))?;
    let rsrc = lcs::from_bytes::<ConfigurationResource>(&rsrc_bytes)?;
    Ok(rsrc.epoch())
}

fn genesis_block_id() -> HashValue {
    HashValue::zero()
}
<|endoftext|>


<commit_before><commit_msg>Work on rep events<commit_after><|endoftext|>


<commit_before>//!Types for interpolation between multiple colors.

use num::{Float, One, Zero, NumCast};
use std::cmp::max;
use approx::ApproxEq;

use flt;

use Mix;

///A linear interpolation between colors.
///
///It's used to smoothly transition between a series of colors, that can be
///either evenly spaced or have customized positions. The gradient is
///continuous between the control points, but it's possible to iterate over a
///number of evenly spaced points using the `take` method. Any point outside
///the domain of the gradient will have the same color as the closest control
///point.
#[derive(Clone, Debug)]
pub struct Gradient<C: Mix + Clone>(Vec<(C::Scalar, C)>);

impl<C: Mix + Clone> Gradient<C> {
    ///Create a gradient of evenly spaced colors with the domain [0.0, 1.0].
    ///There must be at least one color.
    pub fn new<I: IntoIterator<Item = C>>(colors: I) -> Gradient<C> {
        let mut points: Vec<_> = colors.into_iter().map(|c| (C::Scalar::zero(), c)).collect();
        assert!(points.len() > 0);
        let step_size = C::Scalar::one() / flt(max(points.len() - 1, 1) as f64);

        for (i, &mut (ref mut p, _)) in points.iter_mut().enumerate() {
            *p = flt::<C::Scalar, _>(i) * step_size;
        }

        Gradient(points)
    }

    ///Create a gradient of colors with custom spacing and domain. There must be
    ///at least one color and they are expected to be ordered by their
    ///position value.
    pub fn with_domain(colors: Vec<(C::Scalar, C)>) -> Gradient<C> {
        assert!(colors.len() > 0);

        //Maybe sort the colors?
        Gradient(colors)
    }

    ///Get a color from the gradient. The color of the closest control point
    ///will be returned if `i` is outside the domain.
    pub fn get(&self, i: C::Scalar) -> C {
        let &(mut min, ref min_color) = self.0.get(0).expect("a Gradient must contain at least one color");
        let mut min_color = min_color;
        let mut min_index = 0;

        if i <= min {
            return min_color.clone();
        }

        let &(mut max, ref max_color) = self.0.last().expect("a Gradient must contain at least one color");
        let mut max_color = max_color;
        let mut max_index = self.0.len() - 1;

        if i >= max {
            return max_color.clone();
        }

        while min_index < max_index - 1 {
            let index = min_index + (max_index - min_index) / 2;

            let (p, ref color) = self.0[index];

            if i <= p {
                max = p;
                max_color = color;
                max_index = index;
            } else {
                min = p;
                min_color = color;
                min_index = index;
            }
        }

        let factor = (i - min) / (max - min);

        min_color.mix(max_color, factor)
    }

    ///Take `n` evenly spaced colors from the gradient, as an iterator.
    pub fn take(&self, n: usize) -> Take<C> {
        let (min, max) = self.domain();

        Take {
            gradient: MaybeSlice::NotSlice(self),
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }

    ///Slice this gradient to limit its domain.
    pub fn slice<R: Into<Range<C::Scalar>>>(&self, range: R) -> Slice<C> {
        Slice {
            gradient: self,
            range: range.into(),
        }
    }

    ///Get the limits of this gradient's domain.
    pub fn domain(&self) -> (C::Scalar, C::Scalar) {
        let &(min, _) = self.0.get(0).expect("a Gradient must contain at least one color");
        let &(max, _) = self.0.last().expect("a Gradient must contain at least one color");
        (min, max)
    }
}

///An iterator over interpolated colors.
#[derive(Clone)]
pub struct Take<'a, C: Mix + Clone + 'a> {
    gradient: MaybeSlice<'a, C>,
    from: C::Scalar,
    diff: C::Scalar,
    len: usize,
    current: usize,
}

impl<'a, C: Mix + Clone> Iterator for Take<'a, C> {
    type Item = C;

    fn next(&mut self) -> Option<C> {
        if self.current < self.len {
            let i = self.from + (self.diff / flt(self.len)) * flt(self.current);
            self.current += 1;
            Some(self.gradient.get(i))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len - self.current, Some(self.len - self.current))
    }
}

impl<'a, C: Mix + Clone> ExactSizeIterator for Take<'a, C> {}

///A slice of a Gradient that limits its domain.
#[derive(Clone, Debug)]
pub struct Slice<'a, C: Mix + Clone + 'a> {
    gradient: &'a Gradient<C>,
    range: Range<C::Scalar>,
}

impl<'a, C: Mix + Clone> Slice<'a, C> {
    ///Get a color from the gradient slice. The color of the closest domain
    ///limit will be returned if `i` is outside the domain.
    pub fn get(&self, i: C::Scalar) -> C {
        self.gradient.get(self.range.clamp(i))
    }

    ///Take `n` evenly spaced colors from the gradient slice, as an iterator.
    pub fn take(&self, n: usize) -> Take<C> {
        let (min, max) = self.domain();

        Take {
            gradient: MaybeSlice::Slice(self.clone()),
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }

    ///Slice this gradient slice to further limit its domain. Ranges outside
    ///the domain will be clamped to the nearest domain limit.
    pub fn slice<R: Into<Range<C::Scalar>>>(&self, range: R) -> Slice<C> {
        Slice {
            gradient: self.gradient,
            range: self.range.constrain(&range.into())
        }
    }

    ///Get the limits of this gradient slice's domain.
    pub fn domain(&self) -> (C::Scalar, C::Scalar) {
        if let Range { from: Some(from), to: Some(to) } = self.range {
            (from, to)
        } else {
            let (from, to) = self.gradient.domain();
            (self.range.from.unwrap_or(from), self.range.to.unwrap_or(to))
        }
    }
}

///A domain range for gradient slices.
#[derive(Clone, Debug, PartialEq)]
pub struct Range<T: Float> {
    from: Option<T>,
    to: Option<T>,
}

impl<T: Float> Range<T> {
    fn clamp(&self, mut x: T) -> T {
        x = self.from.unwrap_or(x).max(x);
        self.to.unwrap_or(x).min(x)
    }

    fn constrain(&self, other: &Range<T>) -> Range<T> {
        if let (Some(f), Some(t)) = (other.from, self.to) {
            if f >= t {
                return Range {
                    from: self.to,
                    to: self.to,
                };
            }
        }

        if let (Some(t), Some(f)) = (other.to, self.from) {
            if t <= f {
                return Range {
                    from: self.from,
                    to: self.from,
                };
            }
        }

        Range {
            from: match (self.from, other.from) {
                (Some(s), Some(o)) => Some(s.max(o)),
                (Some(s), None) => Some(s),
                (None, Some(o)) => Some(o),
                (None, None) => None,
            },
            to: match (self.to, other.to) {
                (Some(s), Some(o)) => Some(s.min(o)),
                (Some(s), None) => Some(s),
                (None, Some(o)) => Some(o),
                (None, None) => None,
            },
        }
    }
}

impl<T: Float> From<::std::ops::Range<T>> for Range<T> {
    fn from(range: ::std::ops::Range<T>) -> Range<T> {
        Range {
            from: Some(range.start),
            to: Some(range.end),
        }
    }
}

impl<T: Float> From<::std::ops::RangeFrom<T>> for Range<T> {
    fn from(range: ::std::ops::RangeFrom<T>) -> Range<T> {
        Range {
            from: Some(range.start),
            to: None,
        }
    }
}

impl<T: Float> From<::std::ops::RangeTo<T>> for Range<T> {
    fn from(range: ::std::ops::RangeTo<T>) -> Range<T> {
        Range {
            from: None,
            to: Some(range.end),
        }
    }
}

impl<T: Float> From<::std::ops::RangeFull> for Range<T> {
    fn from(_range: ::std::ops::RangeFull) -> Range<T> {
        Range {
            from: None,
            to: None,
        }
    }
}

impl<T> ApproxEq for Range<T> where
    T: ApproxEq + Float,
    T::Epsilon: Copy,
{
    type Epsilon = T::Epsilon;

    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    fn relative_eq(&self, other: &Range<T>, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
        let from = match (self.from, other.from) {
            (Some(s), Some(o)) => s.relative_eq(&o, epsilon, max_relative),
            (None, None) => true,
            _ => false,
        };

        let to = match (self.to, other.to) {
            (Some(s), Some(o)) => s.relative_eq(&o, epsilon, max_relative),
            (None, None) => true,
            _ => false,
        };

        from && to
    }

    fn ulps_eq(&self, other: &Range<T>, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
        let from = match (self.from, other.from) {
            (Some(s), Some(o)) => s.ulps_eq(&o, epsilon, max_ulps),
            (None, None) => true,
            _ => false,
        };

        let to = match (self.to, other.to) {
            (Some(s), Some(o)) => s.ulps_eq(&o, epsilon, max_ulps),
            (None, None) => true,
            _ => false,
        };

        from && to
    }
}

#[derive(Clone)]
enum MaybeSlice<'a, C: Mix + Clone + 'a> {
    NotSlice(&'a Gradient<C>),
    Slice(Slice<'a, C>),
}

impl<'a, C: Mix + Clone> MaybeSlice<'a, C> {
    fn get(&self, i: C::Scalar) -> C {
        match *self {
            MaybeSlice::NotSlice(g) => g.get(i),
            MaybeSlice::Slice(ref s) => s.get(i),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Range, Gradient};
    use Rgb;

    #[test]
    fn range_clamp() {
        let range: Range<f64> = (0.0..1.0).into();
        assert_eq!(range.clamp(-1.0), 0.0);
        assert_eq!(range.clamp(2.0), 1.0);
        assert_eq!(range.clamp(0.5), 0.5);
    }

    #[test]
    fn range_constrain() {
        let range: Range<f64> = (0.0..1.0).into();
        assert_eq!(range.constrain(&(-3.0..-5.0).into()), (0.0..0.0).into());
        assert_eq!(range.constrain(&(-3.0..0.8).into()), (0.0..0.8).into());

        assert_eq!(range.constrain(&(3.0..5.0).into()), (1.0..1.0).into());
        assert_eq!(range.constrain(&(0.2..5.0).into()), (0.2..1.0).into());

        assert_eq!(range.constrain(&(0.2..0.8).into()), (0.2..0.8).into());
    }

    #[test]
    fn simple_slice() {
        let g1 = Gradient::new(vec![Rgb::new(1.0, 0.0, 0.0), Rgb::new(0.0, 0.0, 1.0)]);
        let g2 = g1.slice(..0.5);

        let v1: Vec<_> = g1.take(10).take(5).collect();
        let v2: Vec<_> = g2.take(5).collect();
        for (t1, t2) in v1.iter().zip(v2.iter()){
            assert_relative_eq!(t1, t2);
        }
    }
}
<commit_msg>Fix linter error.<commit_after>//!Types for interpolation between multiple colors.

use num::{Float, One, Zero};
use std::cmp::max;
use approx::ApproxEq;

use flt;

use Mix;

///A linear interpolation between colors.
///
///It's used to smoothly transition between a series of colors, that can be
///either evenly spaced or have customized positions. The gradient is
///continuous between the control points, but it's possible to iterate over a
///number of evenly spaced points using the `take` method. Any point outside
///the domain of the gradient will have the same color as the closest control
///point.
#[derive(Clone, Debug)]
pub struct Gradient<C: Mix + Clone>(Vec<(C::Scalar, C)>);

impl<C: Mix + Clone> Gradient<C> {
    ///Create a gradient of evenly spaced colors with the domain [0.0, 1.0].
    ///There must be at least one color.
    pub fn new<I: IntoIterator<Item = C>>(colors: I) -> Gradient<C> {
        let mut points: Vec<_> = colors.into_iter().map(|c| (C::Scalar::zero(), c)).collect();
        assert!(points.len() > 0);
        let step_size = C::Scalar::one() / flt(max(points.len() - 1, 1) as f64);

        for (i, &mut (ref mut p, _)) in points.iter_mut().enumerate() {
            *p = flt::<C::Scalar, _>(i) * step_size;
        }

        Gradient(points)
    }

    ///Create a gradient of colors with custom spacing and domain. There must be
    ///at least one color and they are expected to be ordered by their
    ///position value.
    pub fn with_domain(colors: Vec<(C::Scalar, C)>) -> Gradient<C> {
        assert!(colors.len() > 0);

        //Maybe sort the colors?
        Gradient(colors)
    }

    ///Get a color from the gradient. The color of the closest control point
    ///will be returned if `i` is outside the domain.
    pub fn get(&self, i: C::Scalar) -> C {
        let &(mut min, ref min_color) = self.0.get(0).expect("a Gradient must contain at least one color");
        let mut min_color = min_color;
        let mut min_index = 0;

        if i <= min {
            return min_color.clone();
        }

        let &(mut max, ref max_color) = self.0.last().expect("a Gradient must contain at least one color");
        let mut max_color = max_color;
        let mut max_index = self.0.len() - 1;

        if i >= max {
            return max_color.clone();
        }

        while min_index < max_index - 1 {
            let index = min_index + (max_index - min_index) / 2;

            let (p, ref color) = self.0[index];

            if i <= p {
                max = p;
                max_color = color;
                max_index = index;
            } else {
                min = p;
                min_color = color;
                min_index = index;
            }
        }

        let factor = (i - min) / (max - min);

        min_color.mix(max_color, factor)
    }

    ///Take `n` evenly spaced colors from the gradient, as an iterator.
    pub fn take(&self, n: usize) -> Take<C> {
        let (min, max) = self.domain();

        Take {
            gradient: MaybeSlice::NotSlice(self),
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }

    ///Slice this gradient to limit its domain.
    pub fn slice<R: Into<Range<C::Scalar>>>(&self, range: R) -> Slice<C> {
        Slice {
            gradient: self,
            range: range.into(),
        }
    }

    ///Get the limits of this gradient's domain.
    pub fn domain(&self) -> (C::Scalar, C::Scalar) {
        let &(min, _) = self.0.get(0).expect("a Gradient must contain at least one color");
        let &(max, _) = self.0.last().expect("a Gradient must contain at least one color");
        (min, max)
    }
}

///An iterator over interpolated colors.
#[derive(Clone)]
pub struct Take<'a, C: Mix + Clone + 'a> {
    gradient: MaybeSlice<'a, C>,
    from: C::Scalar,
    diff: C::Scalar,
    len: usize,
    current: usize,
}

impl<'a, C: Mix + Clone> Iterator for Take<'a, C> {
    type Item = C;

    fn next(&mut self) -> Option<C> {
        if self.current < self.len {
            let i = self.from + (self.diff / flt(self.len)) * flt(self.current);
            self.current += 1;
            Some(self.gradient.get(i))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len - self.current, Some(self.len - self.current))
    }
}

impl<'a, C: Mix + Clone> ExactSizeIterator for Take<'a, C> {}

///A slice of a Gradient that limits its domain.
#[derive(Clone, Debug)]
pub struct Slice<'a, C: Mix + Clone + 'a> {
    gradient: &'a Gradient<C>,
    range: Range<C::Scalar>,
}

impl<'a, C: Mix + Clone> Slice<'a, C> {
    ///Get a color from the gradient slice. The color of the closest domain
    ///limit will be returned if `i` is outside the domain.
    pub fn get(&self, i: C::Scalar) -> C {
        self.gradient.get(self.range.clamp(i))
    }

    ///Take `n` evenly spaced colors from the gradient slice, as an iterator.
    pub fn take(&self, n: usize) -> Take<C> {
        let (min, max) = self.domain();

        Take {
            gradient: MaybeSlice::Slice(self.clone()),
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }

    ///Slice this gradient slice to further limit its domain. Ranges outside
    ///the domain will be clamped to the nearest domain limit.
    pub fn slice<R: Into<Range<C::Scalar>>>(&self, range: R) -> Slice<C> {
        Slice {
            gradient: self.gradient,
            range: self.range.constrain(&range.into())
        }
    }

    ///Get the limits of this gradient slice's domain.
    pub fn domain(&self) -> (C::Scalar, C::Scalar) {
        if let Range { from: Some(from), to: Some(to) } = self.range {
            (from, to)
        } else {
            let (from, to) = self.gradient.domain();
            (self.range.from.unwrap_or(from), self.range.to.unwrap_or(to))
        }
    }
}

///A domain range for gradient slices.
#[derive(Clone, Debug, PartialEq)]
pub struct Range<T: Float> {
    from: Option<T>,
    to: Option<T>,
}

impl<T: Float> Range<T> {
    fn clamp(&self, mut x: T) -> T {
        x = self.from.unwrap_or(x).max(x);
        self.to.unwrap_or(x).min(x)
    }

    fn constrain(&self, other: &Range<T>) -> Range<T> {
        if let (Some(f), Some(t)) = (other.from, self.to) {
            if f >= t {
                return Range {
                    from: self.to,
                    to: self.to,
                };
            }
        }

        if let (Some(t), Some(f)) = (other.to, self.from) {
            if t <= f {
                return Range {
                    from: self.from,
                    to: self.from,
                };
            }
        }

        Range {
            from: match (self.from, other.from) {
                (Some(s), Some(o)) => Some(s.max(o)),
                (Some(s), None) => Some(s),
                (None, Some(o)) => Some(o),
                (None, None) => None,
            },
            to: match (self.to, other.to) {
                (Some(s), Some(o)) => Some(s.min(o)),
                (Some(s), None) => Some(s),
                (None, Some(o)) => Some(o),
                (None, None) => None,
            },
        }
    }
}

impl<T: Float> From<::std::ops::Range<T>> for Range<T> {
    fn from(range: ::std::ops::Range<T>) -> Range<T> {
        Range {
            from: Some(range.start),
            to: Some(range.end),
        }
    }
}

impl<T: Float> From<::std::ops::RangeFrom<T>> for Range<T> {
    fn from(range: ::std::ops::RangeFrom<T>) -> Range<T> {
        Range {
            from: Some(range.start),
            to: None,
        }
    }
}

impl<T: Float> From<::std::ops::RangeTo<T>> for Range<T> {
    fn from(range: ::std::ops::RangeTo<T>) -> Range<T> {
        Range {
            from: None,
            to: Some(range.end),
        }
    }
}

impl<T: Float> From<::std::ops::RangeFull> for Range<T> {
    fn from(_range: ::std::ops::RangeFull) -> Range<T> {
        Range {
            from: None,
            to: None,
        }
    }
}

impl<T> ApproxEq for Range<T> where
    T: ApproxEq + Float,
    T::Epsilon: Copy,
{
    type Epsilon = T::Epsilon;

    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    fn relative_eq(&self, other: &Range<T>, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
        let from = match (self.from, other.from) {
            (Some(s), Some(o)) => s.relative_eq(&o, epsilon, max_relative),
            (None, None) => true,
            _ => false,
        };

        let to = match (self.to, other.to) {
            (Some(s), Some(o)) => s.relative_eq(&o, epsilon, max_relative),
            (None, None) => true,
            _ => false,
        };

        from && to
    }

    fn ulps_eq(&self, other: &Range<T>, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
        let from = match (self.from, other.from) {
            (Some(s), Some(o)) => s.ulps_eq(&o, epsilon, max_ulps),
            (None, None) => true,
            _ => false,
        };

        let to = match (self.to, other.to) {
            (Some(s), Some(o)) => s.ulps_eq(&o, epsilon, max_ulps),
            (None, None) => true,
            _ => false,
        };

        from && to
    }
}

#[derive(Clone)]
enum MaybeSlice<'a, C: Mix + Clone + 'a> {
    NotSlice(&'a Gradient<C>),
    Slice(Slice<'a, C>),
}

impl<'a, C: Mix + Clone> MaybeSlice<'a, C> {
    fn get(&self, i: C::Scalar) -> C {
        match *self {
            MaybeSlice::NotSlice(g) => g.get(i),
            MaybeSlice::Slice(ref s) => s.get(i),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Range, Gradient};
    use Rgb;

    #[test]
    fn range_clamp() {
        let range: Range<f64> = (0.0..1.0).into();
        assert_eq!(range.clamp(-1.0), 0.0);
        assert_eq!(range.clamp(2.0), 1.0);
        assert_eq!(range.clamp(0.5), 0.5);
    }

    #[test]
    fn range_constrain() {
        let range: Range<f64> = (0.0..1.0).into();
        assert_eq!(range.constrain(&(-3.0..-5.0).into()), (0.0..0.0).into());
        assert_eq!(range.constrain(&(-3.0..0.8).into()), (0.0..0.8).into());

        assert_eq!(range.constrain(&(3.0..5.0).into()), (1.0..1.0).into());
        assert_eq!(range.constrain(&(0.2..5.0).into()), (0.2..1.0).into());

        assert_eq!(range.constrain(&(0.2..0.8).into()), (0.2..0.8).into());
    }

    #[test]
    fn simple_slice() {
        let g1 = Gradient::new(vec![Rgb::new(1.0, 0.0, 0.0), Rgb::new(0.0, 0.0, 1.0)]);
        let g2 = g1.slice(..0.5);

        let v1: Vec<_> = g1.take(10).take(5).collect();
        let v2: Vec<_> = g2.take(5).collect();
        for (t1, t2) in v1.iter().zip(v2.iter()){
            assert_relative_eq!(t1, t2);
        }
    }
}
<|endoftext|>


<commit_before>
/// Implemented by all contexts that can add rectangle.
pub trait AddRectangle<'a, T> {
    /// Adds a rectangle.
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> T;

    /// Adds a square with coordinates of upper left corner.
    #[inline(always)]
    fn square(&'a self, x: f64, y: f64, w: f64) -> T {
        self.rect(x, y, w, w)
    }

    /// Adds a square with coordinates in the center.
    #[inline(always)]
    fn square_centered(&'a self, center_x: f64, center_y: f64, radius: f64) -> T {
        self.rect(center_x - radius,
                  center_y - radius,
                  2.0 * radius,
                  2.0 * radius)
    }
}
<commit_msg>Added rect_centered<commit_after>
/// Implemented by all contexts that can add rectangle.
pub trait AddRectangle<'a, T> {
    /// Adds a rectangle.
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> T;

    /// Adds a rectangle with coordinates in the center.
    #[inline(always)]
    fn rect_centered(&'a self, center_x: f64, center_y: f64, radius_width: f64, radius_height: f64) -> T {
        self.rect(
            center_x - radius_width,
            center_y - radius_height,
            2.0 * radius_width,
            2.0 * radius_height
       )
    }

    /// Adds a square with coordinates of upper left corner.
    #[inline(always)]
    fn square(&'a self, x: f64, y: f64, w: f64) -> T {
        self.rect(x, y, w, w)
    }

    /// Adds a square with coordinates in the center.
    #[inline(always)]
    fn square_centered(&'a self, center_x: f64, center_y: f64, radius: f64) -> T {
        self.rect(center_x - radius,
                  center_y - radius,
                  2.0 * radius,
                  2.0 * radius)
    }
}
<|endoftext|>


<commit_before>use std::u16;
use std::sync::mpsc;
use std::thread;
use num::traits::{Float};
use time;
use cpal;

/// A handle object for playing sounds.
pub struct Mixer {
    tx: mpsc::Sender<Rpc>,
}

impl Mixer {
    /// Create a new mixer and spawn a sound-playing thread that will persist
    /// for the lifetime of the mixer.
    pub fn new() -> Mixer {
        let (tx, rx) = mpsc::channel();

        thread::spawn(move || {
            let mut engine = Engine::new();
            let mut voice = cpal::Voice::new();

            loop {
                match rx.try_recv() {
                    Ok(rpc) => {
                        engine.recv(rpc);
                    }
                    // When Mixer is destroyed, the sender object will drop
                    // and trying to receive will get a disconnected error.
                    // This will kill the thread.
                    Err(mpsc::TryRecvError::Disconnected) => { break; }
                    Err(mpsc::TryRecvError::Empty) => {}
                }

                engine.fill_buffer(&mut voice);
                voice.play();
            }
        });

        Mixer {
            tx: tx,
        }
    }

    /// Play a sound described by the given wave function and with the given
    /// duration.
    pub fn add_wave(&mut self, f: Box<Fn(f64) -> f64 + Send>, duration: f64) {
        assert!(duration >= 0.0);
        self.tx.send(Rpc::Wave((f, duration))).unwrap();
    }
}

enum Rpc {
    Wave((Box<Fn(f64) -> f64 + Send>, f64)),
}

/// State in the thread
struct Engine {
    waves: Vec<Wave>,
    t: f64,
    rate: u32,
}

struct Wave {
    f: Box<Fn(f64) -> f64 + Send>,
    begin_t: f64,
    end_t: f64,
}

impl Engine {
    fn new() -> Engine {
        Engine {
            waves: Vec::new(),
            t: time::precise_time_s(),
            rate: 44100,
        }
    }

    fn recv(&mut self, rpc: Rpc) {
        match rpc {
            Rpc::Wave((f, duration)) => {
                let t = time::precise_time_s();
                self.waves.push(Wave {
                    f: f,
                    begin_t: t,
                    end_t: t + duration
                });
            }
        }
    }

    fn fill_buffer(&mut self, voice: &mut cpal::Voice) {
        let mut buffer =
            voice.append_data(1, cpal::SamplesRate(self.rate), 32768);

        for sample in buffer.iter_mut() {
            *sample = self.tick();
        }
    }

    fn tick(&mut self) -> u16 {
        let local_t = self.t;
        // Advance internal time by the length of the sample interval.
        self.t += 1.0 / self.rate as f64;

        // Remove expired waves.
        self.waves.retain(|w| w.end_t > local_t);

        let mut mixed = 0.0;

        for wave in self.waves.iter() {
            let wave_t = self.t - wave.begin_t;
            if wave_t < 0.0 { continue; }

            let a = (wave.f)(wave_t);
            assert!(-1.0 <= a && a <= 1.0);
            // Do some hacky equalization to keep summed waves from
            // going outside the wave envelope.
            mixed = a + mixed - a.signum() * 0.0.max(a * mixed);
            assert!(-1.0 <= mixed && mixed <= 1.0);
        }

        // FIXME: https://github.com/tomaka/cpal/issues/39
        // CPAL samples operate in the i16 space but must be cast to u16.
        (mixed * 0.5 * u16::MAX as f64) as u16
    }
}
<commit_msg>Mixer handle is Arc-Mutex, can be shared by threads<commit_after>use std::u16;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::thread;
use num::traits::{Float};
use time;
use cpal;

/// A handle object for playing sounds.
#[derive(Clone)]
pub struct Mixer {
    tx: Arc<Mutex<mpsc::Sender<Rpc>>>,
}

impl Mixer {
    /// Create a new mixer and spawn a sound-playing thread that will persist
    /// for the lifetime of the mixer.
    pub fn new() -> Mixer {
        let (tx, rx) = mpsc::channel();

        thread::spawn(move || {
            let mut engine = Engine::new();
            let mut voice = cpal::Voice::new();

            loop {
                match rx.try_recv() {
                    Ok(rpc) => {
                        engine.recv(rpc);
                    }
                    // When Mixer is destroyed, the sender object will drop
                    // and trying to receive will get a disconnected error.
                    // This will kill the thread.
                    Err(mpsc::TryRecvError::Disconnected) => { break; }
                    Err(mpsc::TryRecvError::Empty) => {}
                }

                engine.fill_buffer(&mut voice);
                voice.play();
            }
        });

        Mixer {
            tx: Arc::new(Mutex::new(tx)),
        }
    }

    /// Play a sound described by the given wave function and with the given
    /// duration.
    pub fn add_wave(&mut self, f: Box<Fn(f64) -> f64 + Send>, duration: f64) {
        assert!(duration >= 0.0);
        let tx = self.tx.lock().unwrap();
        tx.send(Rpc::Wave((f, duration))).unwrap();
    }
}

enum Rpc {
    Wave((Box<Fn(f64) -> f64 + Send>, f64)),
}

/// State in the thread
struct Engine {
    waves: Vec<Wave>,
    t: f64,
    rate: u32,
}

struct Wave {
    f: Box<Fn(f64) -> f64 + Send>,
    begin_t: f64,
    end_t: f64,
}

impl Engine {
    fn new() -> Engine {
        Engine {
            waves: Vec::new(),
            t: time::precise_time_s(),
            rate: 44100,
        }
    }

    fn recv(&mut self, rpc: Rpc) {
        match rpc {
            Rpc::Wave((f, duration)) => {
                let t = time::precise_time_s();
                self.waves.push(Wave {
                    f: f,
                    begin_t: t,
                    end_t: t + duration
                });
            }
        }
    }

    fn fill_buffer(&mut self, voice: &mut cpal::Voice) {
        let mut buffer =
            voice.append_data(1, cpal::SamplesRate(self.rate), 32768);

        for sample in buffer.iter_mut() {
            *sample = self.tick();
        }
    }

    fn tick(&mut self) -> u16 {
        let local_t = self.t;
        // Advance internal time by the length of the sample interval.
        self.t += 1.0 / self.rate as f64;

        // Remove expired waves.
        self.waves.retain(|w| w.end_t > local_t);

        let mut mixed = 0.0;

        for wave in self.waves.iter() {
            let wave_t = self.t - wave.begin_t;
            if wave_t < 0.0 { continue; }

            let a = (wave.f)(wave_t);
            assert!(-1.0 <= a && a <= 1.0);
            // Do some hacky equalization to keep summed waves from
            // going outside the wave envelope.
            mixed = a + mixed - a.signum() * 0.0.max(a * mixed);
            assert!(-1.0 <= mixed && mixed <= 1.0);
        }

        // FIXME: https://github.com/tomaka/cpal/issues/39
        // CPAL samples operate in the i16 space but must be cast to u16.
        (mixed * 0.5 * u16::MAX as f64) as u16
    }
}
<|endoftext|>


<commit_before>use std::borrow::{Borrow, Cow};
use std::ffi::{CStr, CString};
use std::fmt;
use std::mem;
use std::ops;
use std::os::raw::c_char;
use std::ptr;

const STRING_SIZE: usize = 512;

/// This is a C String abstractions that presents a CStr like
/// interface for interop purposes but tries to be little nicer
/// by avoiding heap allocations if the string is within the
/// generous bounds (512 bytes) of the statically sized buffer.
/// Strings over this limit will be heap allocated, but the
/// interface outside of this abstraction remains the same.
pub enum CFixedString {
    Local{ s: [c_char; STRING_SIZE], len: usize },
    Heap{ s: CString, len: usize },
}

impl CFixedString {
    /// Creates an empty CFixedString, this is intended to be
    /// used with write! or the `fmt::Write` trait
    pub fn new() -> Self {
        unsafe {
            CFixedString::Local {
                s: mem::uninitialized(),
                len: 0,
            }
        }
    }

    pub fn from_str<S: AsRef<str>>(s: S) -> Self {
        Self::from(s.as_ref())
    }

    pub fn as_ptr(&self) -> *const c_char {
        match *self {
            CFixedString::Local{ref s, ..} => s.as_ptr(),
            CFixedString::Heap{ref s, ..} => s.as_ptr(),
        }
    }

    /// Returns true if the string has been heap allocated
    pub fn is_allocated(&self) -> bool {
        match *self {
            CFixedString::Local{..} => false,
            _ => true,
        }
    }

    /// Converts a `CFixedString` into a `Cow<str>`.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
    /// with `U+FFFD REPLACEMENT CHARACTER`. If there are no invalid UTF-8
    /// sequences, this will merely return a borrowed slice.
    pub fn to_string(&self) -> Cow<str> {
        String::from_utf8_lossy(&self.to_bytes())
    }

    pub unsafe fn as_str(&self) -> &str {
        use std::slice;
        use std::str;

        match *self {
            CFixedString::Local{ref s, len} => str::from_utf8_unchecked(slice::from_raw_parts(s.as_ptr() as *const u8, len)),
            CFixedString::Heap{ref s, len} => str::from_utf8_unchecked(slice::from_raw_parts(s.as_ptr() as *const u8, len)),
        }
    }
}

impl<'a> From<&'a str> for CFixedString {
    fn from(s: &'a str) -> Self {
        use std::fmt::Write;

        let mut string = CFixedString::new();

        string.write_str(s).unwrap();

        string
    }
}

impl fmt::Write for CFixedString {
    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
        use std::fmt::Write;

        unsafe {
            let cur_len = self.as_str().len();

            match cur_len + s.len() {
                len if len <= STRING_SIZE - 1 => {
                    match *self {
                        CFixedString::Local{ s: ref mut ls, len: ref mut lslen } => {
                            let ptr = ls.as_mut_ptr() as *mut u8;
                            ptr::copy(s.as_ptr(), ptr.offset(cur_len as isize), s.len());
                            *ptr.offset(len as isize) = 0;
                            *lslen = len;
                        },
                        _ => unreachable!(),
                    }
                },
                len => {
                    let mut heapstring = String::with_capacity(len + 1);

                    heapstring.write_str(self.as_str()).unwrap();
                    heapstring.write_str(s).unwrap();

                    *self = CFixedString::Heap {
                        s: CString::new(heapstring).unwrap(),
                        len: len,
                    };
                }
            }
        }

        // Yah....we should do error handling
        Ok(())
    }
}

impl From<CFixedString> for String {
    fn from(s: CFixedString) -> Self {
        String::from_utf8_lossy(&s.to_bytes()).into_owned()
    }
}

impl ops::Deref for CFixedString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        use std::slice;

        match *self {
            CFixedString::Local{ref s, len} => unsafe {
                mem::transmute(slice::from_raw_parts(s.as_ptr(), len + 1))
            },
            CFixedString::Heap{ref s, ..} => s,
        }
    }
}

impl Borrow<CStr> for CFixedString {
    fn borrow(&self) -> &CStr { self }
}

impl AsRef<CStr> for CFixedString {
    fn as_ref(&self) -> &CStr { self }
}

impl Borrow<str> for CFixedString {
    fn borrow(&self) -> &str { unsafe { self.as_str() } }
}

impl AsRef<str> for CFixedString {
    fn as_ref(&self) -> &str { unsafe { self.as_str() } }
}

macro_rules! format_c {
    // This does not work on stable, to change the * to a + and
    // have this arm be used when there are no arguments :(
    // ($fmt:expr) => {
    //     use std::fmt::Write;

    //     let mut fixed = CFixedString::new();
    //     write!(&mut fixed, $fmt).unwrap();
    //     fixed
    // }

    ($fmt:expr, $($args:tt)*) => ({
        use std::fmt::Write;

        let mut fixed = CFixedString::new();
        write!(&mut fixed, $fmt, $($args)*).unwrap();
        fixed
    })
}

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

    fn gen_string(len: usize) -> String {
        let mut out = String::with_capacity(len);

        for _ in 0..len / 16 {
            out.write_str("zyxvutabcdef9876").unwrap();
        }

        for i in 0..len % 16 {
            out.write_char((i as u8 + 'A' as u8) as char).unwrap();
        }

        assert_eq!(out.len(), len);
        out
    }

    #[test]
    fn test_empty_handler() {
        let short_string = "";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_short_1() {
        let short_string = "test_local";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_short_2() {
        let short_string = "test_local stoheusthsotheost";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_511() {
        // this string (width 511) buffer should just fit
        let test_511_string = gen_string(511);

        let t = CFixedString::from_str(&test_511_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), &test_511_string);
    }

    #[test]
    fn test_512() {
        // this string (width 512) buffer should not fit
        let test_512_string = gen_string(512);

        let t = CFixedString::from_str(&test_512_string);

        assert!(t.is_allocated());
        assert_eq!(&t.to_string(), &test_512_string);
    }

    #[test]
    fn test_513() {
        // this string (width 513) buffer should not fit
        let test_513_string = gen_string(513);

        let t = CFixedString::from_str(&test_513_string);

        assert!(t.is_allocated());
        assert_eq!(&t.to_string(), &test_513_string);
    }

    #[test]
    fn test_to_owned() {
        let short = "this is an amazing string";

        let t = CFixedString::from_str(short);

        assert!(!t.is_allocated());
        assert_eq!(&String::from(t), short);

        let long = gen_string(1025);

        let t = CFixedString::from_str(&long);

        assert!(t.is_allocated());
        assert_eq!(&String::from(t), &long);
    }

    #[test]
    fn test_short_format() {
        let mut fixed = CFixedString::new();

        write!(&mut fixed, "one_{}", 1).unwrap();
        write!(&mut fixed, "_two_{}", "two").unwrap();
        write!(&mut fixed, "_three_{}-{}-{:.3}", 23, "some string data", 56.789).unwrap();

        assert!(!fixed.is_allocated());
        assert_eq!(&fixed.to_string(), "one_1_two_two_three_23-some string data-56.789");
    }

    #[test]
    fn test_long_format() {
        let mut fixed = CFixedString::new();
        let mut string = String::new();

        for i in 1..30 {
            let genned = gen_string(i * i);

            write!(&mut fixed, "{}_{}", i, genned).unwrap();
            write!(&mut string, "{}_{}", i, genned).unwrap();
        }

        assert!(fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &string);
    }

    /*
    TODO: Reenable this test once the empty match arm is allowed
    by the compiler
    #[test]
    fn test_empty_fmt_macro() {
        let empty = format_c!("");
        let no_args = format_c!("there are no format args");

        assert!(!empty.is_allocated());
        assert_eq!(&empty.to_string(), "");

        assert!(!no_args.is_allocated());
        assert_eq!(&no_args.to_string(), "there are no format args");
    }*/

    #[test]
    fn test_short_fmt_macro() {
        let first = 23;
        let second = "#@!*()&^%_-+={}[]|\\/?><,.:;~`";
        let third = u32::max_value();
        let fourth = gen_string(512 - 45);

        let fixed = format_c!("{}_{}_0x{:x}_{}", first, second, third, fourth);
        let heaped = format!("{}_{}_0x{:x}_{}", first, second, third, fourth);

        assert!(!fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &heaped);
    }

    #[test]
    fn test_long_fmt_macro() {
        let first = "";
        let second = gen_string(510);
        let third = 3;
        let fourth = gen_string(513 * 8);

        let fixed = format_c!("{}_{}{}{}", first, second, third, fourth);
        let heaped = format!("{}_{}{}{}", first, second, third, fourth);

        assert!(fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &heaped);
    }
}<commit_msg>Removed warning<commit_after>use std::borrow::{Borrow, Cow};
use std::ffi::{CStr, CString};
use std::fmt;
use std::mem;
use std::ops;
use std::os::raw::c_char;
use std::ptr;

const STRING_SIZE: usize = 512;

/// This is a C String abstractions that presents a CStr like
/// interface for interop purposes but tries to be little nicer
/// by avoiding heap allocations if the string is within the
/// generous bounds (512 bytes) of the statically sized buffer.
/// Strings over this limit will be heap allocated, but the
/// interface outside of this abstraction remains the same.
pub enum CFixedString {
    Local{ s: [c_char; STRING_SIZE], len: usize },
    Heap{ s: CString, len: usize },
}

impl CFixedString {
    /// Creates an empty CFixedString, this is intended to be
    /// used with write! or the `fmt::Write` trait
    pub fn new() -> Self {
        unsafe {
            CFixedString::Local {
                s: mem::uninitialized(),
                len: 0,
            }
        }
    }

    pub fn from_str<S: AsRef<str>>(s: S) -> Self {
        Self::from(s.as_ref())
    }

    pub fn as_ptr(&self) -> *const c_char {
        match *self {
            CFixedString::Local{ref s, ..} => s.as_ptr(),
            CFixedString::Heap{ref s, ..} => s.as_ptr(),
        }
    }

    /// Returns true if the string has been heap allocated
    pub fn is_allocated(&self) -> bool {
        match *self {
            CFixedString::Local{..} => false,
            _ => true,
        }
    }

    /// Converts a `CFixedString` into a `Cow<str>`.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
    /// with `U+FFFD REPLACEMENT CHARACTER`. If there are no invalid UTF-8
    /// sequences, this will merely return a borrowed slice.
    pub fn to_string(&self) -> Cow<str> {
        String::from_utf8_lossy(&self.to_bytes())
    }

    pub unsafe fn as_str(&self) -> &str {
        use std::slice;
        use std::str;

        match *self {
            CFixedString::Local{ref s, len} => str::from_utf8_unchecked(slice::from_raw_parts(s.as_ptr() as *const u8, len)),
            CFixedString::Heap{ref s, len} => str::from_utf8_unchecked(slice::from_raw_parts(s.as_ptr() as *const u8, len)),
        }
    }
}

impl<'a> From<&'a str> for CFixedString {
    fn from(s: &'a str) -> Self {
        use std::fmt::Write;

        let mut string = CFixedString::new();

        string.write_str(s).unwrap();

        string
    }
}

impl fmt::Write for CFixedString {
    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
        //use std::fmt::Write;

        unsafe {
            let cur_len = self.as_str().len();

            match cur_len + s.len() {
                len if len <= STRING_SIZE - 1 => {
                    match *self {
                        CFixedString::Local{ s: ref mut ls, len: ref mut lslen } => {
                            let ptr = ls.as_mut_ptr() as *mut u8;
                            ptr::copy(s.as_ptr(), ptr.offset(cur_len as isize), s.len());
                            *ptr.offset(len as isize) = 0;
                            *lslen = len;
                        },
                        _ => unreachable!(),
                    }
                },
                len => {
                    let mut heapstring = String::with_capacity(len + 1);

                    heapstring.write_str(self.as_str()).unwrap();
                    heapstring.write_str(s).unwrap();

                    *self = CFixedString::Heap {
                        s: CString::new(heapstring).unwrap(),
                        len: len,
                    };
                }
            }
        }

        // Yah....we should do error handling
        Ok(())
    }
}

impl From<CFixedString> for String {
    fn from(s: CFixedString) -> Self {
        String::from_utf8_lossy(&s.to_bytes()).into_owned()
    }
}

impl ops::Deref for CFixedString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        use std::slice;

        match *self {
            CFixedString::Local{ref s, len} => unsafe {
                mem::transmute(slice::from_raw_parts(s.as_ptr(), len + 1))
            },
            CFixedString::Heap{ref s, ..} => s,
        }
    }
}

impl Borrow<CStr> for CFixedString {
    fn borrow(&self) -> &CStr { self }
}

impl AsRef<CStr> for CFixedString {
    fn as_ref(&self) -> &CStr { self }
}

impl Borrow<str> for CFixedString {
    fn borrow(&self) -> &str { unsafe { self.as_str() } }
}

impl AsRef<str> for CFixedString {
    fn as_ref(&self) -> &str { unsafe { self.as_str() } }
}

macro_rules! format_c {
    // This does not work on stable, to change the * to a + and
    // have this arm be used when there are no arguments :(
    // ($fmt:expr) => {
    //     use std::fmt::Write;

    //     let mut fixed = CFixedString::new();
    //     write!(&mut fixed, $fmt).unwrap();
    //     fixed
    // }

    ($fmt:expr, $($args:tt)*) => ({
        use std::fmt::Write;

        let mut fixed = CFixedString::new();
        write!(&mut fixed, $fmt, $($args)*).unwrap();
        fixed
    })
}

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

    fn gen_string(len: usize) -> String {
        let mut out = String::with_capacity(len);

        for _ in 0..len / 16 {
            out.write_str("zyxvutabcdef9876").unwrap();
        }

        for i in 0..len % 16 {
            out.write_char((i as u8 + 'A' as u8) as char).unwrap();
        }

        assert_eq!(out.len(), len);
        out
    }

    #[test]
    fn test_empty_handler() {
        let short_string = "";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_short_1() {
        let short_string = "test_local";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_short_2() {
        let short_string = "test_local stoheusthsotheost";

        let t = CFixedString::from_str(short_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), short_string);
    }

    #[test]
    fn test_511() {
        // this string (width 511) buffer should just fit
        let test_511_string = gen_string(511);

        let t = CFixedString::from_str(&test_511_string);

        assert!(!t.is_allocated());
        assert_eq!(&t.to_string(), &test_511_string);
    }

    #[test]
    fn test_512() {
        // this string (width 512) buffer should not fit
        let test_512_string = gen_string(512);

        let t = CFixedString::from_str(&test_512_string);

        assert!(t.is_allocated());
        assert_eq!(&t.to_string(), &test_512_string);
    }

    #[test]
    fn test_513() {
        // this string (width 513) buffer should not fit
        let test_513_string = gen_string(513);

        let t = CFixedString::from_str(&test_513_string);

        assert!(t.is_allocated());
        assert_eq!(&t.to_string(), &test_513_string);
    }

    #[test]
    fn test_to_owned() {
        let short = "this is an amazing string";

        let t = CFixedString::from_str(short);

        assert!(!t.is_allocated());
        assert_eq!(&String::from(t), short);

        let long = gen_string(1025);

        let t = CFixedString::from_str(&long);

        assert!(t.is_allocated());
        assert_eq!(&String::from(t), &long);
    }

    #[test]
    fn test_short_format() {
        let mut fixed = CFixedString::new();

        write!(&mut fixed, "one_{}", 1).unwrap();
        write!(&mut fixed, "_two_{}", "two").unwrap();
        write!(&mut fixed, "_three_{}-{}-{:.3}", 23, "some string data", 56.789).unwrap();

        assert!(!fixed.is_allocated());
        assert_eq!(&fixed.to_string(), "one_1_two_two_three_23-some string data-56.789");
    }

    #[test]
    fn test_long_format() {
        let mut fixed = CFixedString::new();
        let mut string = String::new();

        for i in 1..30 {
            let genned = gen_string(i * i);

            write!(&mut fixed, "{}_{}", i, genned).unwrap();
            write!(&mut string, "{}_{}", i, genned).unwrap();
        }

        assert!(fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &string);
    }

    /*
    TODO: Reenable this test once the empty match arm is allowed
    by the compiler
    #[test]
    fn test_empty_fmt_macro() {
        let empty = format_c!("");
        let no_args = format_c!("there are no format args");

        assert!(!empty.is_allocated());
        assert_eq!(&empty.to_string(), "");

        assert!(!no_args.is_allocated());
        assert_eq!(&no_args.to_string(), "there are no format args");
    }*/

    #[test]
    fn test_short_fmt_macro() {
        let first = 23;
        let second = "#@!*()&^%_-+={}[]|\\/?><,.:;~`";
        let third = u32::max_value();
        let fourth = gen_string(512 - 45);

        let fixed = format_c!("{}_{}_0x{:x}_{}", first, second, third, fourth);
        let heaped = format!("{}_{}_0x{:x}_{}", first, second, third, fourth);

        assert!(!fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &heaped);
    }

    #[test]
    fn test_long_fmt_macro() {
        let first = "";
        let second = gen_string(510);
        let third = 3;
        let fourth = gen_string(513 * 8);

        let fixed = format_c!("{}_{}{}{}", first, second, third, fourth);
        let heaped = format!("{}_{}{}{}", first, second, third, fourth);

        assert!(fixed.is_allocated());
        assert_eq!(&fixed.to_string(), &heaped);
    }
}
<|endoftext|>