<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.
"##,

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,
    E0054,
    E0055,
    E0057,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    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>Add long diagnostic for E0054<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;
```
"##,

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,
    E0062,
    E0063,
    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>// ignore-tidy-cr ignore-license
// ignore-tidy-cr (repeated again because of tidy bug)
// license is ignored because tidy can't handle the CRLF here properly.

// 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.

// NB: this file needs CRLF line endings. The .gitattributes file in
// this directory should enforce it.

// ignore-pretty

/// Doc comment that ends in CRLF
pub fn foo() {}

/** Block doc comment that
 *  contains CRLF characters
 */
pub fn bar() {}

fn main() {
    let s = "string
literal";
    assert_eq!(s, "string\nliteral");

    let s = "literal with \
             escaped newline";
    assert_eq!(s, "literal with escaped newline");

    let s = r"string
literal";
    assert_eq!(s, "string\nliteral");

    // validate that our source file has CRLF endings
    let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs");
    assert!(source.contains("string\r\nliteral"));
}
<commit_msg>Rollup merge of #28876 - steveklabnik:oops, r=Gankro<commit_after>// ignore-tidy-cr ignore-license
// ignore-tidy-cr (repeated again because of tidy bug)
// license is ignored because tidy can't handle the CRLF here properly.

// 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.

// NB: this file needs CRLF line endings. The .gitattributes file in
// this directory should enforce it.

// ignore-pretty

/// Doc comment that ends in CRLF
pub fn foo() {}

/** Block doc comment that
 *  contains CRLF characters
 */
pub fn bar() {}

fn main() {
    let s = "string
literal";
    assert_eq!(s, "string\nliteral");

    let s = "literal with \
             escaped newline";
    assert_eq!(s, "literal with escaped newline");

    let s = r"string
literal";
    assert_eq!(s, "string\nliteral");

    // validate that our source file has CRLF endings
    let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs");
    assert!(source.contains("string\r\nliteral"));
}
<|endoftext|>


<commit_before><commit_msg>add support for +=<commit_after><|endoftext|>


<commit_before>use std::net::{TcpStream};

use std::io::prelude::*;

extern crate byteorder;

use self::byteorder::{BigEndian,ByteOrder};

pub const MAX_TEXT_LEN: usize = 2048;

#[allow(unused_must_use)]
pub fn read_text<S:Read> (mut s: &mut S) -> Option<String> {
    let mut size = [0;2];

    if let Ok(_) = s.read_exact(&mut size) {
        let size = BigEndian::read_u16(&size);

        if size > MAX_TEXT_LEN as u16 { panic!("unbounded chat size reached") }

        let mut v = vec![0;size as usize];

        if let Ok(_) = s.read_exact(&mut v) {
            if let Ok(text) = String::from_utf8(v) {
                return Some(text)
            }
        }
    }

    return None
}

#[allow(unused_must_use)]
/// defaults to CHAT opcode
pub fn write_text (mut s: &mut TcpStream, text: &str) {
    let (data, bytes) = text_as_bytes(text);
    s.write_all(&data);
    s.write_all(&bytes);
}

pub fn text_as_bytes (text: &str) -> (Vec<u8>, &[u8]) {
    let bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    (vec![2, size[0],size[1]], &bytes[0..len])
}
<commit_msg>remove panic<commit_after>use std::net::{TcpStream};

use std::io::prelude::*;

extern crate byteorder;

use self::byteorder::{BigEndian,ByteOrder};

pub const MAX_TEXT_LEN: usize = 2048;

#[allow(unused_must_use)]
pub fn read_text<S:Read> (mut s: &mut S) -> Option<String> {
    let mut size = [0;2];

    if let Ok(_) = s.read_exact(&mut size) {
        let size = BigEndian::read_u16(&size);

        if size > MAX_TEXT_LEN as u16 { return None } //unbounded chat size reached

        let mut v = vec![0;size as usize];

        if let Ok(_) = s.read_exact(&mut v) {
            if let Ok(text) = String::from_utf8(v) {
                return Some(text)
            }
        }
    }

    return None
}

#[allow(unused_must_use)]
/// defaults to CHAT opcode
pub fn write_text (mut s: &mut TcpStream, text: &str) {
    let (data, bytes) = text_as_bytes(text);
    s.write_all(&data);
    s.write_all(&bytes);
}

pub fn text_as_bytes (text: &str) -> (Vec<u8>, &[u8]) {
    let bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    (vec![2, size[0],size[1]], &bytes[0..len])
}
<|endoftext|>


<commit_before>#![cfg(test)]
#![allow(unused_assignments)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use super::Collect;
use iter::plumbing::*;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces fewer items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "expected 5 total writes, but got 2")]
fn produce_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 5);
    {
        let consumer = collect.as_consumer();
        let mut folder = consumer.into_folder();
        folder = folder.consume(22);
        folder = folder.consume(23);
        folder.complete();
    }
    collect.complete();
}

// Complete is not called by the consumer.Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn left_produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3);
        right_folder.complete();
    }
    collect.complete();
}

// Complete is not called by the right consumer. Hence,the
// collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn right_produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3);
        left_folder.complete();
    }
    collect.complete();
}

// Complete is not called by the consumer. Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 2 total writes, but got 0")]
fn produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    {
        let consumer = collect.as_consumer();
        let mut folder = consumer.into_folder();
        folder = folder.consume(22);
        folder = folder.consume(23);
    }
    collect.complete();
}

// The left consumer produces too many items while the right
// consumer produces correct number.
#[test]
#[should_panic(expected = "too many values")]
fn left_produces_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1).consume(2);
        right_folder = right_folder.consume(2).consume(3);
        right_folder.complete();
    }
    collect.complete();
}

// The right consumer produces too many items while the left
// consumer produces correct number.
#[test]
#[should_panic(expected = "too many values")]
fn right_produces_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3).consume(4);
        left_folder.complete();
    }
    collect.complete();
}

// The left consumer produces fewer items while the right
// consumer produces correct number.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 3")]
fn left_produces_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0);
        right_folder = right_folder.consume(2).consume(3);
        left_folder.complete();
        right_folder.complete();
    }
    collect.complete();
}

// The right consumer produces fewer items while the left
// consumer produces correct number.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 3")]
fn right_produces_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2);
        left_folder.complete();
        right_folder.complete();
    }
    collect.complete();
}
<commit_msg>Add tests of panicking collect shortfalls, like `panic_fuse()`<commit_after>#![cfg(test)]
#![allow(unused_assignments)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use super::Collect;
use iter::plumbing::*;
use rayon_core::join;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces fewer items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "expected 5 total writes, but got 2")]
fn produce_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 5);
    {
        let consumer = collect.as_consumer();
        let mut folder = consumer.into_folder();
        folder = folder.consume(22);
        folder = folder.consume(23);
        folder.complete();
    }
    collect.complete();
}

// Complete is not called by the consumer.Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn left_produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3);
        right_folder.complete();
    }
    collect.complete();
}

// Complete is not called by the right consumer. Hence,the
// collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn right_produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3);
        left_folder.complete();
    }
    collect.complete();
}

// Complete is not called by the consumer. Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 2 total writes, but got 0")]
fn produces_items_with_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    {
        let consumer = collect.as_consumer();
        let mut folder = consumer.into_folder();
        folder = folder.consume(22);
        folder = folder.consume(23);
    }
    collect.complete();
}

// The left consumer produces too many items while the right
// consumer produces correct number.
#[test]
#[should_panic(expected = "too many values")]
fn left_produces_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1).consume(2);
        right_folder = right_folder.consume(2).consume(3);
        right_folder.complete();
    }
    collect.complete();
}

// The right consumer produces too many items while the left
// consumer produces correct number.
#[test]
#[should_panic(expected = "too many values")]
fn right_produces_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3).consume(4);
        left_folder.complete();
    }
    collect.complete();
}

// The left consumer produces fewer items while the right
// consumer produces correct number.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 3")]
fn left_produces_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0);
        right_folder = right_folder.consume(2).consume(3);
        left_folder.complete();
        right_folder.complete();
    }
    collect.complete();
}

// The right consumer produces fewer items while the left
// consumer produces correct number.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 3")]
fn right_produces_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2);
        left_folder.complete();
        right_folder.complete();
    }
    collect.complete();
}

// The left consumer panics and the right stops short, like `panic_fuse()`.
// We should get the left panic without ever reaching `Collect::complete()`.
#[test]
#[should_panic(expected = "left consumer panic")]
fn left_panics() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        join(
            || {
                let mut left_folder = left_consumer.into_folder();
                left_folder = left_folder.consume(0);
                panic!("left consumer panic");
            },
            || {
                let mut right_folder = right_consumer.into_folder();
                right_folder = right_folder.consume(2);
                right_folder.complete() // early return
            },
        );
    }
    collect.complete();
}

// The right consumer panics and the left stops short, like `panic_fuse()`.
// We should get the right panic without ever reaching `Collect::complete()`.
#[test]
#[should_panic(expected = "right consumer panic")]
fn right_panics() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, _) = consumer.split_at(2);
        join(
            || {
                let mut left_folder = left_consumer.into_folder();
                left_folder = left_folder.consume(0);
                left_folder.complete() // early return
            },
            || {
                let mut right_folder = right_consumer.into_folder();
                right_folder = right_folder.consume(2);
                panic!("right consumer panic");
            },
        );
    }
    collect.complete();
}
<|endoftext|>


<commit_before>use parser;

use super::expand_macros;

#[test]
fn test_comma() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Comma<E>: Vec<E> =
       ~v:(~E \",\")* ~e:E? =>
           v.into_iter().chain(e.into_iter()).collect();

    Ids = Comma<\"Id\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Ids = `Comma<\"Id\">`;

    `Comma<\"Id\">`: Vec<`\"Id\"`> =
        ~v:`(~\"Id\" \",\")`* ~e:\"Id\"? =>
           v.into_iter().chain(e.into_iter()).collect();

    `(~\"Id\" \",\")` = ~\"Id\" \",\";
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    assert_eq!(actual, expected);
}

#[test]
fn test_if_match() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Expr<E> = {
       A if E == \"A*C\";
       B if E ~~ \"^A*C$\";
       C if E != \"A*C\";
       D if E !~ \"^A*C$\";
    };

    Expr1 = Expr<\"A*C\">;
    Expr2 = Expr<\"AAC\">;
    Expr3 = Expr<\"ABC\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Expr1 = `Expr<\"A*C\">`;
    Expr2 = `Expr<\"AAC\">`;
    Expr3 = `Expr<\"ABC\">`;

    `Expr<\"ABC\">` = { C; D; };
    `Expr<\"AAC\">` = { B; C; };
    `Expr<\"A*C\">` = { A; D; };
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    assert_eq!(actual, expected);
}
<commit_msg>Fix macro tests to hide spans<commit_after>use regex::Regex;
use parser;
use std::fmt::Debug;

use super::expand_macros;

thread_local! {
    static SPAN: Regex =
        Regex::new(r"Span\([0-9 ,]*\)").unwrap()
}

fn compare<D:Debug>(actual: D, expected: D) {
    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    let actual = format!("{:?}", actual);
    let expected = format!("{:?}", expected);

    SPAN.with(|span| {
        let actual = span.replace_all(&actual, "Span(..)");
        let expected = span.replace_all(&expected, "Span(..)");
        assert_eq!(actual, expected);
    });
}

#[test]
fn test_comma() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Comma<E>: Vec<E> =
       ~v:(~E \",\")* ~e:E? =>
           v.into_iter().chain(e.into_iter()).collect();

    Ids = Comma<\"Id\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Ids = `Comma<\"Id\">`;

    `Comma<\"Id\">`: Vec<`\"Id\"`> =
        ~v:`(~\"Id\" \",\")`* ~e:\"Id\"? =>
           v.into_iter().chain(e.into_iter()).collect();

    `(~\"Id\" \",\")` = ~\"Id\" \",\";
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    compare(actual, expected);
}

#[test]
fn test_if_match() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Expr<E> = {
       A if E == \"A*C\";
       B if E ~~ \"^A*C$\";
       C if E != \"A*C\";
       D if E !~ \"^A*C$\";
    };

    Expr1 = Expr<\"A*C\">;
    Expr2 = Expr<\"AAC\">;
    Expr3 = Expr<\"ABC\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Expr1 = `Expr<\"A*C\">`;
    Expr2 = `Expr<\"AAC\">`;
    Expr3 = `Expr<\"ABC\">`;

    `Expr<\"ABC\">` = { C; D; };
    `Expr<\"AAC\">` = { B; C; };
    `Expr<\"A*C\">` = { A; D; };
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    compare(actual, expected);
}
<|endoftext|>


<commit_before>use chrono::{Local, NaiveDate};
use config::Config;
use error::BackendError;
use std::borrow::Cow;

pub mod anilist;

pub trait SyncBackend
where
    Self: Sized + ScoreParser,
{
    fn name() -> &'static str;

    fn init(offline_mode: bool, config: &mut Config) -> Result<Self, BackendError>;

    fn search_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError>;
    fn get_series_info_by_id(&self, id: u32) -> Result<AnimeInfo, BackendError>;

    fn get_list_entry(&self, info: AnimeInfo) -> Result<Option<AnimeEntry>, BackendError>;
    fn update_list_entry(&self, entry: &AnimeEntry) -> Result<(), BackendError>;
}

pub trait ScoreParser {
    fn formatted_score_range(&self) -> (Cow<str>, Cow<str>);
    fn parse_score(&self, input: &str) -> Result<f32, BackendError>;
    fn format_score(&self, raw_score: f32) -> Result<String, BackendError>;
}

#[derive(Clone, Serialize, Deserialize)]
pub struct AnimeInfo {
    pub id: u32,
    pub title: String,
    pub episodes: Option<u32>,
}

impl Default for AnimeInfo {
    fn default() -> AnimeInfo {
        AnimeInfo {
            id: 0,
            title: String::new(),
            episodes: None,
        }
    }
}

#[derive(Clone, Serialize, Deserialize)]
pub struct AnimeEntry {
    #[serde(flatten)]
    pub info: AnimeInfo,
    pub watched_episodes: u32,
    pub score: Option<f32>,
    pub status: Status,
    pub start_date: Option<NaiveDate>,
    pub finish_date: Option<NaiveDate>,
}

impl AnimeEntry {
    pub fn new(info: AnimeInfo) -> AnimeEntry {
        AnimeEntry {
            info,
            watched_episodes: 0,
            score: None,
            status: Status::PlanToWatch,
            start_date: Some(Local::today().naive_local()),
            finish_date: None,
        }
    }
}

#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum Status {
    Watching,
    Completed,
    OnHold,
    Dropped,
    PlanToWatch,
    Rewatching,
}
<commit_msg>[backend] Don't set the start date when creating a new AnimeEntry<commit_after>use chrono::NaiveDate;
use config::Config;
use error::BackendError;
use std::borrow::Cow;

pub mod anilist;

pub trait SyncBackend
where
    Self: Sized + ScoreParser,
{
    fn name() -> &'static str;

    fn init(offline_mode: bool, config: &mut Config) -> Result<Self, BackendError>;

    fn search_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError>;
    fn get_series_info_by_id(&self, id: u32) -> Result<AnimeInfo, BackendError>;

    fn get_list_entry(&self, info: AnimeInfo) -> Result<Option<AnimeEntry>, BackendError>;
    fn update_list_entry(&self, entry: &AnimeEntry) -> Result<(), BackendError>;
}

pub trait ScoreParser {
    fn formatted_score_range(&self) -> (Cow<str>, Cow<str>);
    fn parse_score(&self, input: &str) -> Result<f32, BackendError>;
    fn format_score(&self, raw_score: f32) -> Result<String, BackendError>;
}

#[derive(Clone, Serialize, Deserialize)]
pub struct AnimeInfo {
    pub id: u32,
    pub title: String,
    pub episodes: Option<u32>,
}

impl Default for AnimeInfo {
    fn default() -> AnimeInfo {
        AnimeInfo {
            id: 0,
            title: String::new(),
            episodes: None,
        }
    }
}

#[derive(Clone, Serialize, Deserialize)]
pub struct AnimeEntry {
    #[serde(flatten)]
    pub info: AnimeInfo,
    pub watched_episodes: u32,
    pub score: Option<f32>,
    pub status: Status,
    pub start_date: Option<NaiveDate>,
    pub finish_date: Option<NaiveDate>,
}

impl AnimeEntry {
    pub fn new(info: AnimeInfo) -> AnimeEntry {
        AnimeEntry {
            info,
            watched_episodes: 0,
            score: None,
            status: Status::PlanToWatch,
            start_date: None,
            finish_date: None,
        }
    }
}

#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum Status {
    Watching,
    Completed,
    OnHold,
    Dropped,
    PlanToWatch,
    Rewatching,
}
<|endoftext|>


<commit_before>use std::{env, process::Command};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};

fn main() {
    let git_rev = env::var("DITTO_BUILD_GIT_REV").unwrap_or_else(|_| {
        let output = Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .unwrap();
        String::from_utf8(output.stdout).unwrap()
    });
    println!("cargo:rustc-env=GIT_REV={}", git_rev);

    let git_describe = env::var("DITTO_BUILD_GIT_DESCRIBE").unwrap_or_else(|_| {
        let output = Command::new("git").arg("describe").output().unwrap();
        String::from_utf8(output.stdout).unwrap()
    });
    println!("cargo:rustc-env=GIT_DESCRIBE={}", git_describe);

    let git_dirty = env::var("DITTO_BUILD_GIT_DIRTY").unwrap_or_else(|_| {
        let output = Command::new("git")
            .args(&["diff-index", "--quiet", "HEAD"])
            .output()
            .unwrap();
        if output.status.success() {
            "no".to_string()
        } else {
            "yes".to_string()
        }
    });
    println!("cargo:rustc-env=GIT_DIRTY={}", git_dirty);

    let build_time = env::var("DITTO_BUILD_TIME")
        .unwrap_or_else(|_| OffsetDateTime::now_utc().format(&Rfc3339).unwrap());
    println!("cargo:rustc-env=BUILD_TIME={}", build_time);

    println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
}
<commit_msg>Need to pass `--tags` to git describe<commit_after>use std::{env, process::Command};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};

fn main() {
    let git_rev = env::var("DITTO_BUILD_GIT_REV").unwrap_or_else(|_| {
        let output = Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .unwrap();
        String::from_utf8(output.stdout).unwrap()
    });
    println!("cargo:rustc-env=GIT_REV={}", git_rev);

    let git_describe = env::var("DITTO_BUILD_GIT_DESCRIBE").unwrap_or_else(|_| {
        let output = Command::new("git")
            .arg("describe")
            .arg("--tags")
            .output()
            .unwrap();
        String::from_utf8(output.stdout).unwrap()
    });
    println!("cargo:rustc-env=GIT_DESCRIBE={}", git_describe);

    let git_dirty = env::var("DITTO_BUILD_GIT_DIRTY").unwrap_or_else(|_| {
        let output = Command::new("git")
            .args(&["diff-index", "--quiet", "HEAD"])
            .output()
            .unwrap();
        if output.status.success() {
            "no".to_string()
        } else {
            "yes".to_string()
        }
    });
    println!("cargo:rustc-env=GIT_DIRTY={}", git_dirty);

    let build_time = env::var("DITTO_BUILD_TIME")
        .unwrap_or_else(|_| OffsetDateTime::now_utc().format(&Rfc3339).unwrap());
    println!("cargo:rustc-env=BUILD_TIME={}", build_time);

    println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
}
<|endoftext|>


<commit_before><commit_msg>Top level module API docs for the `neon::context` module.<commit_after><|endoftext|>


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

use std::f64::consts::PI;
use ::structs::{ECEF, LLA};

// Conversion formulas from https://microem.ru/files/2012/08/GPS.G1-X-00006.pdf

// Semi-major axis of the Earth in meters
const WGS84_A: f64 = 6378137.0;
// Inverse flattening of the Earth
const WGS84_IF: f64 = 298.257223563;
// Flattening of the Earth
const WGS84_F: f64 = 1./WGS84_IF;
// Semi-minor axis of the Earth in meters
const WGS84_B: f64 = WGS84_A*(1.-WGS84_F);

lazy_static! {
    // Eccentricity of the Earth
    // static ref WGS84_E:  f64 = (2.*WGS84_F - WGS84_F*WGS84_F).sqrt();
    static ref WGS84_E:  f64 = ((WGS84_A*WGS84_A-WGS84_B*WGS84_B)/(WGS84_A*WGS84_A)).sqrt();
    // Second eccentricity of the Earth
    static ref WGS84_SE: f64 = ((WGS84_A*WGS84_A-WGS84_B*WGS84_B)/(WGS84_B*WGS84_B)).sqrt();
}

pub fn lla_to_ecef(lla: &LLA) -> ECEF {
    let d = *WGS84_E * to_rad(lla.lat_deg).sin();
    let n = WGS84_A / (1. - d*d).sqrt();
    let tmp = (n + lla.alt_m) * to_rad(lla.lat_deg).cos();
    ECEF {
        x: tmp * to_rad(lla.lon_deg).cos(),
        y: tmp * to_rad(lla.lon_deg).sin(),
        z: ((1. - *WGS84_E*(*WGS84_E))*n + lla.alt_m) * to_rad(lla.lat_deg).sin(),
    }
}

pub fn ecef_to_lla(ecef: &ECEF) -> LLA {
    let p = (ecef.x*ecef.x+ecef.y*ecef.y).sqrt();
    let phi = ((ecef.z*WGS84_A)/(p*WGS84_B)).atan();
    let (sin_phi, cos_phi) = phi.sin_cos();

    let lat_rad = ((    ecef.z + (*WGS84_SE)*(*WGS84_SE) * WGS84_B * sin_phi*sin_phi*sin_phi
                   ) / (
                        p      - (*WGS84_E)*(*WGS84_E)   * WGS84_A * cos_phi*cos_phi*cos_phi
                   )).atan();

    let d = *WGS84_E * lat_rad.sin();
    let n = WGS84_A / (1. - d*d).sqrt();

    LLA {
        lat_deg: to_deg(lat_rad),
        lon_deg: to_deg((ecef.y/ecef.x).atan()),
        alt_m:   (p/lat_rad.cos())-n,
    }
}

fn to_rad(deg: f64) -> f64 {
    (deg/180.)*PI
}

fn to_deg(rad: f64) -> f64 {
    (rad/PI)*180.
}
<commit_msg>use std lib angle conversion<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Mattis Marjak (mattis.marjak@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ::structs::{ECEF, LLA};

// Conversion formulas from https://microem.ru/files/2012/08/GPS.G1-X-00006.pdf

// Semi-major axis of the Earth in meters
const WGS84_A: f64 = 6378137.0;
// Inverse flattening of the Earth
const WGS84_IF: f64 = 298.257223563;
// Flattening of the Earth
const WGS84_F: f64 = 1./WGS84_IF;
// Semi-minor axis of the Earth in meters
const WGS84_B: f64 = WGS84_A*(1.-WGS84_F);

lazy_static! {
    // Eccentricity of the Earth
    // static ref WGS84_E:  f64 = (2.*WGS84_F - WGS84_F*WGS84_F).sqrt();
    static ref WGS84_E:  f64 = ((WGS84_A*WGS84_A-WGS84_B*WGS84_B)/(WGS84_A*WGS84_A)).sqrt();
    // Second eccentricity of the Earth
    static ref WGS84_SE: f64 = ((WGS84_A*WGS84_A-WGS84_B*WGS84_B)/(WGS84_B*WGS84_B)).sqrt();
}

pub fn lla_to_ecef(lla: &LLA) -> ECEF {
    let d = *WGS84_E * lla.lat_deg.to_radians().sin();
    let n = WGS84_A / (1. - d*d).sqrt();
    let tmp = (n + lla.alt_m) * lla.lat_deg.to_radians().cos();
    ECEF {
        x: tmp * lla.lon_deg.to_radians().cos(),
        y: tmp * lla.lon_deg.to_radians().sin(),
        z: ((1. - *WGS84_E*(*WGS84_E))*n + lla.alt_m) * lla.lat_deg.to_radians().sin(),
    }
}

pub fn ecef_to_lla(ecef: &ECEF) -> LLA {
    let p = (ecef.x*ecef.x+ecef.y*ecef.y).sqrt();
    let phi = ((ecef.z*WGS84_A)/(p*WGS84_B)).atan();
    let (sin_phi, cos_phi) = phi.sin_cos();

    let lat_rad = ((    ecef.z + (*WGS84_SE)*(*WGS84_SE) * WGS84_B * sin_phi*sin_phi*sin_phi
                   ) / (
                        p      - (*WGS84_E)*(*WGS84_E)   * WGS84_A * cos_phi*cos_phi*cos_phi
                   )).atan();

    let d = *WGS84_E * lat_rad.sin();
    let n = WGS84_A / (1. - d*d).sqrt();

    LLA {
        lat_deg: lat_rad.to_degrees(),
        lon_deg: (ecef.y/ecef.x).atan().to_degrees(),
        alt_m:   (p/lat_rad.cos())-n,
    }
}
<|endoftext|>


<commit_before>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

use std::sync::Arc;

extern crate bytes;
extern crate futures;
extern crate httpbis;
extern crate test;

use httpbis::*;

use futures::future::Future;
use futures::stream;
use futures::stream::Stream;

use bytes::Bytes;

use test::Bencher;

#[bench]
fn download_megabyte_in_kb_chunks(b: &mut Bencher) {
    struct Megabyte;

    impl ServerHandler for Megabyte {
        fn start_request(
            &self,
            _context: ServerHandlerContext,
            _headers: Headers,
            _req: HttpStreamAfterHeaders,
            mut resp: ServerResponse,
        ) -> httpbis::Result<()> {
            resp.send_headers(Headers::ok_200())?;
            resp.pull_bytes_from_stream(stream::iter_ok(
                (0..1024).map(|i| Bytes::from(vec![(i % 0xff) as u8; 1024])),
            ))?;
            Ok(())
        }
    }

    let mut server = ServerBuilder::new_plain();
    server.set_port(0);
    server.service.set_service("/", Arc::new(Megabyte));
    let server = server.build().expect("server");

    let client = Client::new_plain(
        "127.0.0.1",
        server.local_addr().port().unwrap(),
        Default::default(),
    ).expect("client");

    fn iter(client: &Client) {
        let (header, body) = client
            .start_get("/any", "localhost")
            .0
            .wait()
            .expect("headers");
        assert_eq!(200, header.status());

        let mut s = 0;
        for p in body.wait() {
            match p.expect("part") {
                DataOrTrailers::Data(d, ..) => s += d.len(),
                _ => panic!("unexpected headers"),
            }
        }

        assert_eq!(1024 * 1024, s);
    }

    // Warm-up
    iter(&client);

    b.iter(|| iter(&client))
}

#[bench]
fn small_requests(b: &mut Bencher) {
    struct My;

    impl ServerHandler for My {
        fn start_request(
            &self,
            _context: ServerHandlerContext,
            _headers: Headers,
            _req: HttpStreamAfterHeaders,
            mut resp: ServerResponse,
        ) -> httpbis::Result<()> {
            resp.send_found_200_plain_text("hello there")?;
            Ok(())
        }
    }

    let mut server = ServerBuilder::new_plain();
    server.set_port(0);
    server.service.set_service("/", Arc::new(My));
    let server = server.build().expect("server");

    let client = Client::new_plain(
        "127.0.0.1",
        server.local_addr().port().unwrap(),
        Default::default(),
    ).expect("client");

    b.iter(|| {
        let (header, body) = client
            .start_get("/any", "localhost")
            .0
            .wait()
            .expect("headers");
        assert_eq!(200, header.status());

        // TODO: check content
        body.collect().wait().expect("body")
    })
}
<commit_msg>Fix bench build<commit_after>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

use std::sync::Arc;

extern crate bytes;
extern crate futures;
extern crate httpbis;
extern crate test;

use httpbis::*;

use futures::future::Future;
use futures::stream;
use futures::stream::Stream;

use bytes::Bytes;

use test::Bencher;

#[bench]
fn download_megabyte_in_kb_chunks(b: &mut Bencher) {
    struct Megabyte;

    impl ServerHandler for Megabyte {
        fn start_request(
            &self,
            _context: ServerHandlerContext,
            _req: ServerRequest,
            mut resp: ServerResponse,
        ) -> httpbis::Result<()> {
            resp.send_headers(Headers::ok_200())?;
            resp.pull_bytes_from_stream(stream::iter_ok(
                (0..1024).map(|i| Bytes::from(vec![(i % 0xff) as u8; 1024])),
            ))?;
            Ok(())
        }
    }

    let mut server = ServerBuilder::new_plain();
    server.set_port(0);
    server.service.set_service("/", Arc::new(Megabyte));
    let server = server.build().expect("server");

    let client = Client::new_plain(
        "127.0.0.1",
        server.local_addr().port().unwrap(),
        Default::default(),
    ).expect("client");

    fn iter(client: &Client) {
        let (header, body) = client
            .start_get("/any", "localhost")
            .0
            .wait()
            .expect("headers");
        assert_eq!(200, header.status());

        let mut s = 0;
        for p in body.wait() {
            match p.expect("part") {
                DataOrTrailers::Data(d, ..) => s += d.len(),
                _ => panic!("unexpected headers"),
            }
        }

        assert_eq!(1024 * 1024, s);
    }

    // Warm-up
    iter(&client);

    b.iter(|| iter(&client))
}

#[bench]
fn small_requests(b: &mut Bencher) {
    struct My;

    impl ServerHandler for My {
        fn start_request(
            &self,
            _context: ServerHandlerContext,
            _req: ServerRequest,
            mut resp: ServerResponse,
        ) -> httpbis::Result<()> {
            resp.send_found_200_plain_text("hello there")?;
            Ok(())
        }
    }

    let mut server = ServerBuilder::new_plain();
    server.set_port(0);
    server.service.set_service("/", Arc::new(My));
    let server = server.build().expect("server");

    let client = Client::new_plain(
        "127.0.0.1",
        server.local_addr().port().unwrap(),
        Default::default(),
    ).expect("client");

    b.iter(|| {
        let (header, body) = client
            .start_get("/any", "localhost")
            .0
            .wait()
            .expect("headers");
        assert_eq!(200, header.status());

        // TODO: check content
        body.collect().wait().expect("body")
    })
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;

extern crate gluon;

use gluon::{Compiler, new_vm};
use gluon::vm::api::FunctionRef;

// Benchmarks function calls
#[bench]
fn factorial(b: &mut ::test::Bencher) {
    let vm = new_vm();
    let text = r#"
    let factorial n =
        if n < 2
        then 1
        else n * factorial (n - 1)
    factorial
    "#;
    Compiler::new()
        .load_script(&vm, "factorial", text)
        .unwrap();
    let mut factorial: FunctionRef<fn (i32) -> i32> = vm.get_global("factorial").unwrap();
    b.iter(|| {
        let result = factorial.call(100).unwrap();
        ::test::black_box(result)
    })
}

#[bench]
fn factorial_tail_call(b: &mut ::test::Bencher) {
    let vm = new_vm();
    let text = r#"
    let factorial a n =
        if n < 2
        then a
        else factorial (a * n) (n - 1)
    factorial 1
    "#;
    Compiler::new()
        .load_script(&vm, "factorial", text)
        .unwrap();
    let mut factorial: FunctionRef<fn (i32) -> i32> = vm.get_global("factorial").unwrap();
    b.iter(|| {
        let result = factorial.call(100).unwrap();
        ::test::black_box(result)
    })
}

#[bench]
fn gluon_rust_boundary_overhead(b: &mut ::test::Bencher) {
    let vm = new_vm();
    let text = r#"
    let { trim } = import "std/string.glu"
    let for n f =
        if n #Int== 0 then
            ()
        else
            f n
            for (n #Int- 10) f
    \n -> for n \_ -> trim ""
    "#;
    Compiler::new()
        .load_script(&vm, "test", text)
        .unwrap();
    let mut factorial: FunctionRef<fn (i32) -> ()> = vm.get_global("test").unwrap();
    b.iter(|| {
        let result = factorial.call(1000).unwrap();
        ::test::black_box(result)
    })
}
<commit_msg>test: Replace gluon_rust_boundary_overhead with the update function from issue #75<commit_after>#![feature(test)]

extern crate test;

extern crate gluon;

use gluon::{Compiler, new_vm};
use gluon::vm::thread::{Status, Thread};
use gluon::vm::api::{FunctionRef, primitive};

// Benchmarks function calls
#[bench]
fn factorial(b: &mut ::test::Bencher) {
    let vm = new_vm();
    let text = r#"
    let factorial n =
        if n < 2
        then 1
        else n * factorial (n - 1)
    factorial
    "#;
    Compiler::new()
        .load_script(&vm, "factorial", text)
        .unwrap();
    let mut factorial: FunctionRef<fn (i32) -> i32> = vm.get_global("factorial").unwrap();
    b.iter(|| {
        let result = factorial.call(100).unwrap();
        ::test::black_box(result)
    })
}

#[bench]
fn factorial_tail_call(b: &mut ::test::Bencher) {
    let vm = new_vm();
    let text = r#"
    let factorial a n =
        if n < 2
        then a
        else factorial (a * n) (n - 1)
    factorial 1
    "#;
    Compiler::new()
        .load_script(&vm, "factorial", text)
        .unwrap();
    let mut factorial: FunctionRef<fn (i32) -> i32> = vm.get_global("factorial").unwrap();
    b.iter(|| {
        let result = factorial.call(100).unwrap();
        ::test::black_box(result)
    })
}

#[bench]
fn gluon_rust_boundary_overhead(b: &mut ::test::Bencher) {
    let vm = new_vm();

    fn test_fn(_: &Thread) -> Status { Status::Ok }
    vm.define_global("test_fn", primitive::<fn (i32)>("test_fn", test_fn)).unwrap();

    let text = r#"
    let for n f =
        if n #Int== 0 then
            ()
        else
            f n
            f n
            f n
            f n
            f n
            f n
            f n
            f n
            f n
            f n
            for (n #Int- 10) f
    \n -> for n test_fn
    "#;
    Compiler::new()
        .load_script(&vm, "test", text)
        .unwrap();

    let mut test: FunctionRef<fn (i32) -> ()> = vm.get_global("test").unwrap();
    b.iter(|| {
        let result = test.call(1000).unwrap();
        ::test::black_box(result)
    })
}
<|endoftext|>


<commit_before>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation matrix
    /// Based on Shoemake 1991
    pub fn from_matrix(m: &Matrix4) -> Quaternion {
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Construct the quaternion from the transform
    pub fn from_transform(t: &Transform) -> Quaternion {
        Quaternion::from_matrix(&t.mat)
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_matrix(&self) -> Matrix4 {
        Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ]).transpose()
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&self.to_matrix())
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v / rhs, w: self. w / rhs }
    }
}

<commit_msg>Add negation operator for Quaternion<commit_after>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div, Neg};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation matrix
    /// Based on Shoemake 1991
    pub fn from_matrix(m: &Matrix4) -> Quaternion {
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Construct the quaternion from the transform
    pub fn from_transform(t: &Transform) -> Quaternion {
        Quaternion::from_matrix(&t.mat)
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_matrix(&self) -> Matrix4 {
        Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ]).transpose()
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&self.to_matrix())
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v / rhs, w: self. w / rhs }
    }
}

impl Neg for Quaternion {
    type Output = Quaternion;
    /// Negate the quaternion
    fn neg(self) -> Quaternion {
        Quaternion { v: -self.v, w: -self. w }
    }
}

<|endoftext|>


<commit_before>
use super::es;
use std::env;
use std::path::{Path,PathBuf};

use es::traits::*;

lazy_static! {
    pub static ref RUSTUP_LIB: String = es::shell("rustc --print sysroot") + "/lib";
    pub static ref UNSTABLE: bool = RUSTUP_LIB.find("stable").is_none();
}

pub fn proper_crate_name(crate_name: &str) -> String {
    crate_name.replace('-',"_")
}

pub fn plain_name(name: &str) -> bool {
    name.find(|c:char| c=='/' || c=='\\' || c=='.').is_none()
}

pub fn path_file_name(p: &Path) -> String {
    if let Some(file_name) = p.file_name() {
        file_name.to_string_lossy().to_string()
    } else
    if let Ok(full_path) = p.canonicalize() {
        path_file_name(&full_path)
    } else {
        p.to_string_lossy().to_string()
    }
}

pub fn cargo_home() -> PathBuf {
    if let Ok(home) = env::var("CARGO_HOME") { // set in cargo runs
        home.into()
    } else {
        env::home_dir().or_die("no home!").join(".cargo")
    }
}

pub fn cargo_dir(dir: &Path) -> Result<(PathBuf,PathBuf),String> {
    let mut path = dir.to_path_buf();
    let mut ok = true;
    while ok {
        let cargo_toml = path.join("Cargo.toml");
        if cargo_toml.exists() {
            return Ok((path,cargo_toml));
        }
        ok = path.pop();
    }
    Err("No Cargo project in this path".into())
}

// Very hacky stuff - we want the ACTUAL crate name, not the directory/repo name
// So look just past [package] and scrape the name...
pub fn crate_name(cargo_toml: &Path) -> String {
    let name_line = es::lines(es::open(cargo_toml))
        .skip_while(|line| line.trim() != "[package]")
        .skip(1)
        .skip_while(|line| ! line.starts_with("name "))
        .next().or_die("totally fked Cargo.toml");
    let idx = name_line.find('"').or_die("no name?");
    (&name_line[(idx+1)..(name_line.len()-1)]).into()
}

<commit_msg>use 'nightly' to detect 'unstable'<commit_after>
use super::es;
use std::env;
use std::path::{Path,PathBuf};

use es::traits::*;

lazy_static! {
    pub static ref RUSTUP_LIB: String = es::shell("rustc --print sysroot") + "/lib";
    pub static ref UNSTABLE: bool = RUSTUP_LIB.find("nightly").is_some();
}

pub fn proper_crate_name(crate_name: &str) -> String {
    crate_name.replace('-',"_")
}

pub fn plain_name(name: &str) -> bool {
    name.find(|c:char| c=='/' || c=='\\' || c=='.').is_none()
}

pub fn path_file_name(p: &Path) -> String {
    if let Some(file_name) = p.file_name() {
        file_name.to_string_lossy().to_string()
    } else
    if let Ok(full_path) = p.canonicalize() {
        path_file_name(&full_path)
    } else {
        p.to_string_lossy().to_string()
    }
}

pub fn cargo_home() -> PathBuf {
    if let Ok(home) = env::var("CARGO_HOME") { // set in cargo runs
        home.into()
    } else {
        env::home_dir().or_die("no home!").join(".cargo")
    }
}

pub fn cargo_dir(dir: &Path) -> Result<(PathBuf,PathBuf),String> {
    let mut path = dir.to_path_buf();
    let mut ok = true;
    while ok {
        let cargo_toml = path.join("Cargo.toml");
        if cargo_toml.exists() {
            return Ok((path,cargo_toml));
        }
        ok = path.pop();
    }
    Err("No Cargo project in this path".into())
}

// Very hacky stuff - we want the ACTUAL crate name, not the directory/repo name
// So look just past [package] and scrape the name...
pub fn crate_name(cargo_toml: &Path) -> String {
    let name_line = es::lines(es::open(cargo_toml))
        .skip_while(|line| line.trim() != "[package]")
        .skip(1)
        .skip_while(|line| ! line.starts_with("name "))
        .next().or_die("totally fked Cargo.toml");
    let idx = name_line.find('"').or_die("no name?");
    (&name_line[(idx+1)..(name_line.len()-1)]).into()
}

<|endoftext|>


<commit_before>use egui::{plot::Bar, Color32, Context, Grid, Ui, Visuals};
use gba::Gba;
use parking_lot::Mutex;
use pyrite::{CallbackId, GbaHandle, GbaThreadState};
use std::{sync::Arc, time::Duration};
use util::circular::CircularBuffer;

#[derive(Default)]
pub struct Debugger {
    performance_pane: PerformancePane,
    has_initialized: bool,

    gba_data: GbaData,
    gba_data_buffer: Arc<Mutex<GbaData>>,
    frame_callback: Option<CallbackId>,
}

impl Debugger {
    pub fn render(&mut self, ctx: &Context, gba: &GbaHandle) {
        if !self.has_initialized {
            self.init(ctx, gba);
            self.has_initialized = true;
        } else {
            self.fetch_updated_data();
        }

        egui::CentralPanel::default().show(ctx, |ui| {
            self.performance_pane.render(ctx, ui, &mut self.gba_data);
        });
    }

    fn fetch_updated_data(&mut self) {
        let mut locked = self.gba_data_buffer.lock();
        self.gba_data.copy_data(&mut *locked);
    }

    #[cold]
    pub fn init(&mut self, ctx: &Context, gba: &GbaHandle) {
        let mut visuals = Visuals::dark();
        visuals.override_text_color = Some(Color32::from_rgb(0xe9, 0xec, 0xef));
        ctx.set_visuals(visuals);

        let gba_data_buffer = Arc::clone(&self.gba_data_buffer);
        let callback_id = gba.on_frame(move |gba, state| {
            let mut locked = gba_data_buffer.lock();
            pull_data_from_gba(&mut *locked, gba, state);
        });

        self.frame_callback = Some(callback_id);
    }

    pub fn destroy(&mut self, gba: &GbaHandle) {
        if let Some(cb) = self.frame_callback.take() {
            gba.remove_on_frame(cb);
        }
    }
}

#[derive(Default)]
struct AudioPane {}

#[derive(Default)]
struct PerformancePane {
    frame_times: CircularBuffer<f64, 32>,
    frame_processing_times: CircularBuffer<f64, 32>,
}

impl PerformancePane {
    const GBA_MAX_FRAME_DUR: f64 = 1000.0 / 60.0;

    fn render(&mut self, ctx: &Context, ui: &mut Ui, data: &mut GbaData) {
        if let Some(duration) = data.frame_duration.take() {
            self.frame_times.push(duration.as_secs_f64() * 1000.0);
            ctx.request_repaint();
        }

        if let Some(duration) = data.frame_processing_duration.take() {
            self.frame_processing_times
                .push(duration.as_secs_f64() * 1000.0);
            ctx.request_repaint();
        }

        self.render_frame_times(ui);
        data.requests.frame_duration = true;
    }

    fn render_frame_times_text(&mut self, ui: &mut Ui) {
        let average_dur =
            self.frame_times.iter().copied().sum::<f64>() / self.frame_times.len() as f64;
        ui.label("Average GBA Frame Duration");
        ui.label(format!("{average_dur:0.2}ms"));
        ui.end_row();

        let average_fps = 1000.0 / average_dur;
        ui.label("Average GBA FPS");
        ui.label(format!("{average_fps:0.2}"));
        ui.end_row();

        let average_perf = (Self::GBA_MAX_FRAME_DUR / average_dur) * 100.0;
        ui.label("Average GBA Performance");
        ui.label(format!("{average_perf:0.2}%"));
        ui.end_row();
    }

    fn render_processing_times_plot(&mut self, ui: &mut Ui) {
        use egui::plot::{BarChart, Plot};
        const PROCESSING_COLOR: Color32 = Color32::from_rgb(0x1c, 0x7e, 0xd6);
        let mut bars = Vec::with_capacity(self.frame_processing_times.len());
        for (idx, &t) in self.frame_processing_times.iter().skip(1).enumerate() {
            bars.push(Bar::new(idx as f64, t).fill(PROCESSING_COLOR));
        }

        if !self.frame_processing_times.is_empty() {
            bars.push(Bar::new(bars.len() as f64, 0.0));
        }

        let chart = BarChart::new(bars).name("GBA Frame Processing Duration");
        Plot::new("GBA Processing Durations")
            .show_x(false)
            .show_axes([false, false])
            .allow_drag(false)
            .allow_zoom(false)
            .include_y(Self::GBA_MAX_FRAME_DUR)
            .show(ui, |plot_ui| plot_ui.bar_chart(chart));
    }

    fn render_frame_times_plot(&mut self, ui: &mut Ui) {
        use egui::plot::{BarChart, Plot};

        const GOOD_FRAME_COLOR: Color32 = Color32::from_rgb(0x37, 0xb2, 0x4d);
        const BAD_FRAME_COLOR: Color32 = Color32::from_rgb(0xf0, 0x3e, 0x3e);

        let bar_color = |t: f64| -> Color32 {
            if t > 4.0 {
                BAD_FRAME_COLOR
            } else {
                GOOD_FRAME_COLOR
            }
        };

        let bars = self
            .frame_times
            .iter()
            .enumerate()
            .map(|(idx, &t)| Bar::new(idx as f64, t).fill(bar_color(t)))
            .collect();
        let chart = BarChart::new(bars).name("GBA Frame Processing Duration");
        Plot::new("GBA Frame Durations")
            .show_x(false)
            .show_axes([false, false])
            .allow_drag(false)
            .allow_zoom(false)
            .include_y(Self::GBA_MAX_FRAME_DUR)
            .show(ui, |plot_ui| plot_ui.bar_chart(chart));
    }

    fn render_frame_times(&mut self, ui: &mut Ui) {
        Grid::new("GBA Frame Durations Grid")
            .num_columns(2)
            .striped(true)
            .show(ui, |ui| {
                self.render_frame_times_text(ui);

                ui.label("GBA Frame Durations");
                self.render_frame_times_plot(ui);
                ui.end_row();

                ui.label("GBA Processing Durations");
                self.render_processing_times_plot(ui);
                ui.end_row();
            });
    }
}

#[derive(Default)]
struct GbaData {
    frame_duration: Option<Duration>,
    frame_processing_duration: Option<Duration>,

    updated: bool,
    requests: GbaDataRequests,
}

impl GbaData {
    fn copy_data(&mut self, source: &mut GbaData) {
        if !source.updated {
            self.updated = false;
            return;
        }
        self.updated = true;
        source.updated = false;

        self.frame_duration = source.frame_duration.take();
        self.frame_processing_duration = source.frame_processing_duration.take();

        source.requests = std::mem::take(&mut self.requests);
    }
}

#[derive(Default)]
struct GbaDataRequests {
    frame_duration: bool,
}

fn pull_data_from_gba(data: &mut GbaData, _gba: &mut Gba, state: &mut GbaThreadState) {
    if data.requests.frame_duration {
        data.frame_duration = Some(state.frame_duration());
        data.frame_processing_duration = Some(state.frame_processing_duration());
    }
    data.updated = true;
}
<commit_msg>Add audio pane to debugger.<commit_after>use egui::{
    plot::{Bar, BarChart, Line, Plot, Value, Values},
    Color32, Context, Grid, Ui, Visuals,
};
use gba::{Command, Gba, GbaAudioSampler};
use parking_lot::Mutex;
use pyrite::{CallbackId, GbaHandle, GbaThreadState};
use std::{sync::Arc, time::Duration};
use util::circular::CircularBuffer;

#[derive(Default)]
pub struct Debugger {
    performance_pane: PerformancePane,
    audio_pane: AudioPane,

    has_initialized: bool,

    gba_data: GbaData,
    gba_data_buffer: Arc<Mutex<GbaData>>,
    frame_callback: Option<CallbackId>,
}

impl Debugger {
    pub fn render(&mut self, ctx: &Context, gba: &GbaHandle) {
        if !self.has_initialized {
            self.init(ctx, gba);
            self.has_initialized = true;
        } else {
            self.fetch_updated_data();

            if self.gba_data.updated {
                ctx.request_repaint();
            }
        }

        egui::CentralPanel::default().show(ctx, |ui| {
            // self.performance_pane.render(ui, &mut self.gba_data);
            self.audio_pane.render(ui, &mut self.gba_data);
        });
    }

    fn fetch_updated_data(&mut self) {
        let mut locked = self.gba_data_buffer.lock();
        self.gba_data.copy_data(&mut *locked);
    }

    #[cold]
    pub fn init(&mut self, ctx: &Context, gba: &GbaHandle) {
        let mut visuals = Visuals::dark();
        visuals.override_text_color = Some(Color32::from_rgb(0xe9, 0xec, 0xef));
        ctx.set_visuals(visuals);

        let gba_data_buffer = Arc::clone(&self.gba_data_buffer);
        let callback_id = gba.on_frame(move |gba, state| {
            let mut locked = gba_data_buffer.lock();
            pull_data_from_gba(&mut *locked, gba, state);
        });

        self.frame_callback = Some(callback_id);
    }

    pub fn destroy(&mut self, gba: &GbaHandle) {
        if let Some(cb) = self.frame_callback.take() {
            gba.remove_on_frame(cb);
        }
    }
}

#[derive(Default)]
struct AudioPane {
    samples_l: CircularBuffer<f32, { Self::BUFFER_SIZE }>,
    samples_r: CircularBuffer<f32, { Self::BUFFER_SIZE }>,
    commands_buffer_sizes: CircularBuffer<u32, { Self::FRAMES }>,
}

impl AudioPane {
    const RENDER_SAMPLES: u32 = 1024;
    const FRAMES: usize = 16;
    const BUFFER_SIZE: usize = Self::FRAMES * Self::RENDER_SAMPLES as usize;

    fn render(&mut self, ui: &mut Ui, data: &mut GbaData) {
        self.get_data(data);
        Grid::new("GBA Frame Durations Grid")
            .num_columns(2)
            .striped(true)
            .show(ui, |ui| {
                ui.label("Output");
                self.render_samples_plot(ui);
                ui.end_row();

                ui.label("Commands");
                self.render_commands_buffer_plot(ui);
                ui.end_row();
            });
    }

    fn render_commands_buffer_plot(&mut self, ui: &mut Ui) {
        let mut bars = Vec::with_capacity(self.commands_buffer_sizes.len());
        for (idx, &size) in self.commands_buffer_sizes.iter().enumerate() {
            bars.push(Bar::new(idx as f64, size as f64));
        }

        let chart = BarChart::new(bars).name("GBA Frame Processing Duration");
        Plot::new("Command Buffer Sizes")
            .allow_drag(false)
            .allow_zoom(false)
            .show(ui, |plot_ui| {
                plot_ui.bar_chart(chart);
            });
    }

    fn render_samples_plot(&mut self, ui: &mut Ui) {
        let samples_l = self
            .samples_l
            .iter()
            .enumerate()
            .map(|(idx, &s)| Value::new(idx as f64, s));
        let samples_r = self
            .samples_r
            .iter()
            .enumerate()
            .map(|(idx, &s)| Value::new(idx as f64, s));

        let line_l = Line::new(Values::from_values_iter(samples_l)).color(rgb(0x228be6));
        let line_r = Line::new(Values::from_values_iter(samples_r)).color(rgb(0xae3ec9));

        Plot::new("Samples")
            .allow_drag(true)
            .allow_zoom(true)
            .include_y(1.0)
            .include_y(-1.0)
            .show(ui, |plot_ui| {
                plot_ui.line(line_l);
                plot_ui.line(line_r);
            });
    }

    fn get_data(&mut self, data: &mut GbaData) {
        if std::mem::take(&mut data.has_audio_commands) {
            self.commands_buffer_sizes
                .push(data.audio_commands.len() as u32);
            let mut sampler = GbaAudioSampler::new(Self::RENDER_SAMPLES);
            for _ in 0..Self::RENDER_SAMPLES {
                while sampler.needs_commands() {
                    if let Some(command) = data.audio_commands.pop() {
                        sampler.command(command);
                    } else {
                        break;
                    }
                }

                let (l, r) = sampler.frame(1.0);
                self.samples_l.push(l);
                self.samples_r.push(r);
            }
        }
        data.requests.audio_data = true;
    }
}

#[derive(Default)]
struct PerformancePane {
    frame_times: CircularBuffer<f64, 32>,
    frame_processing_times: CircularBuffer<f64, 32>,
}

impl PerformancePane {
    const GBA_MAX_FRAME_DUR: f64 = 1000.0 / 60.0;

    const GOOD_FRAME_COLOR: Color32 = Color32::from_rgb(0x37, 0xb2, 0x4d);
    const BAD_FRAME_COLOR: Color32 = Color32::from_rgb(0xf0, 0x3e, 0x3e);

    fn render(&mut self, ui: &mut Ui, data: &mut GbaData) {
        if let Some(duration) = data.frame_duration.take() {
            self.frame_times.push(duration.as_secs_f64() * 1000.0);
        }

        if let Some(duration) = data.frame_processing_duration.take() {
            self.frame_processing_times
                .push(duration.as_secs_f64() * 1000.0);
        }

        self.render_frame_times(ui);
        data.requests.frame_duration = true;
    }

    fn render_frame_times_text(&mut self, ui: &mut Ui) {
        let average_dur =
            self.frame_times.iter().copied().sum::<f64>() / self.frame_times.len() as f64;
        ui.label("Average GBA Frame Duration");
        ui.label(format!("{average_dur:0.2}ms"));
        ui.end_row();

        let average_fps = 1000.0 / average_dur;
        ui.label("Average GBA FPS");
        ui.label(format!("{average_fps:0.2}"));
        ui.end_row();

        let average_perf = (Self::GBA_MAX_FRAME_DUR / average_dur) * 100.0;
        ui.label("Average GBA Performance");
        ui.label(format!("{average_perf:0.2}%"));
        ui.end_row();
    }

    fn render_processing_times_plot(&mut self, ui: &mut Ui) {
        use egui::plot::{BarChart, Plot};
        const PROCESSING_COLOR: Color32 = Color32::from_rgb(0x1c, 0x7e, 0xd6);
        let mut bars = Vec::with_capacity(self.frame_processing_times.len());
        for (idx, &t) in self.frame_processing_times.iter().skip(1).enumerate() {
            bars.push(Bar::new(idx as f64, t).fill(PROCESSING_COLOR));
        }

        if !self.frame_processing_times.is_empty() {
            bars.push(Bar::new(bars.len() as f64, 0.0));
        }

        let chart = BarChart::new(bars).name("GBA Frame Processing Duration");
        Plot::new("GBA Processing Durations")
            .show_x(false)
            .show_axes([false, false])
            .allow_drag(false)
            .allow_zoom(false)
            .include_y(Self::GBA_MAX_FRAME_DUR)
            .show(ui, |plot_ui| {
                plot_ui.bar_chart(chart);
            });
    }

    fn render_frame_times_plot(&mut self, ui: &mut Ui) {
        use egui::plot::{BarChart, HLine, Plot};

        let bar_color = |t: f64| -> Color32 {
            if t > 4.0 {
                Self::BAD_FRAME_COLOR
            } else {
                Self::GOOD_FRAME_COLOR
            }
        };

        let bars = self
            .frame_times
            .iter()
            .enumerate()
            .map(|(idx, &t)| Bar::new(idx as f64, t).fill(bar_color(t)))
            .collect();
        let chart = BarChart::new(bars).name("GBA Frame Processing Duration");
        Plot::new("GBA Frame Durations")
            .show_x(false)
            .show_axes([false, false])
            .allow_drag(false)
            .allow_zoom(false)
            .include_y(Self::GBA_MAX_FRAME_DUR)
            .show(ui, |plot_ui| {
                plot_ui.hline(HLine::new(4.0).color(Self::BAD_FRAME_COLOR));
                plot_ui.bar_chart(chart);
            });
    }

    fn render_frame_times(&mut self, ui: &mut Ui) {
        Grid::new("GBA Frame Durations Grid")
            .num_columns(2)
            .striped(true)
            .show(ui, |ui| {
                self.render_frame_times_text(ui);

                ui.label("GBA Frame Durations");
                self.render_frame_times_plot(ui);
                ui.end_row();

                ui.label("GBA Processing Durations");
                self.render_processing_times_plot(ui);
                ui.end_row();
            });
    }
}

#[derive(Default)]
struct GbaData {
    frame_duration: Option<Duration>,
    frame_processing_duration: Option<Duration>,

    audio_commands: Vec<Command>,
    has_audio_commands: bool,

    updated: bool,
    requests: GbaDataRequests,
}

impl GbaData {
    fn copy_data(&mut self, source: &mut GbaData) {
        if !source.updated {
            self.updated = false;
            return;
        }
        self.updated = true;
        source.updated = false;

        self.frame_duration = source.frame_duration.take();
        self.frame_processing_duration = source.frame_processing_duration.take();

        if self.requests.audio_data {
            self.audio_commands.clear();
            self.audio_commands
                .extend(source.audio_commands.iter().rev().copied());
            self.has_audio_commands = source.has_audio_commands;
        } else {
            self.has_audio_commands = false;
        }

        source.requests = std::mem::take(&mut self.requests);
    }
}

#[derive(Default)]
struct GbaDataRequests {
    frame_duration: bool,
    audio_data: bool,
}

fn pull_data_from_gba(data: &mut GbaData, gba: &mut Gba, state: &mut GbaThreadState) {
    if data.requests.frame_duration {
        data.frame_duration = Some(state.frame_duration());
        data.frame_processing_duration = Some(state.frame_processing_duration());
    }

    if data.requests.audio_data {
        data.audio_commands.clear();
        data.audio_commands.extend(gba.audio().commands());
        data.has_audio_commands = true;
    } else {
        data.has_audio_commands = false;
    }

    data.updated = true;
}

const fn rgb(col: u32) -> Color32 {
    Color32::from_rgb((col >> 16) as u8, (col >> 8) as u8, col as u8)
}
<|endoftext|>


<commit_before><commit_msg>fix state feeds outside of the US failing to parse<commit_after><|endoftext|>