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

use cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use style::parser::ParserContext;
use style::stylesheets::Origin;
use url::Url;

#[test]
fn font_feature_settings_should_parse_properly() {
    use style::properties::longhands::font_feature_settings;
    use style::properties::longhands::font_feature_settings::computed_value;
    use style::properties::longhands::font_feature_settings::computed_value::FeatureTagValue;

    let normal = parse_longhand!(font_feature_settings, "normal");
    let normal_computed = computed_value::T::Normal;
    assert_eq!(normal, normal_computed);

    let on = parse_longhand!(font_feature_settings, "\"abcd\" on");
    let on_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 1 }
    ]);
    assert_eq!(on, on_computed);

    let off = parse_longhand!(font_feature_settings, "\"abcd\" off");
    let off_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 0 }
    ]);
    assert_eq!(off, off_computed);

    let no_value = parse_longhand!(font_feature_settings, "\"abcd\"");
    let no_value_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 1 }
    ]);
    assert_eq!(no_value, no_value_computed);

    let pos_integer = parse_longhand!(font_feature_settings, "\"abcd\" 100");
    let pos_integer_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 100 }
    ]);
    assert_eq!(pos_integer, pos_integer_computed);

    let multiple = parse_longhand!(font_feature_settings, "\"abcd\" off, \"efgh\"");
    let multiple_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 0 },
        FeatureTagValue { tag: String::from("efgh"), value: 1 }
    ]);
    assert_eq!(multiple, multiple_computed);
}

#[test]
fn font_feature_settings_should_throw_on_bad_input() {
    use style::properties::longhands::font_feature_settings;

    let url = Url::parse("http://localhost").unwrap();
    let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));

    let mut empty = Parser::new("");
    assert!(font_feature_settings::parse(&context, &mut empty).is_err());

    let mut negative = Parser::new("\"abcd\" -1");
    assert!(font_feature_settings::parse(&context, &mut negative).is_err());

    let mut short_tag = Parser::new("\"abc\"");
    assert!(font_feature_settings::parse(&context, &mut short_tag).is_err());

    let mut illegal_tag = Parser::new("\"abcó\"");
    assert!(font_feature_settings::parse(&context, &mut illegal_tag).is_err());
}
<commit_msg>ToCss tests<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use style::parser::ParserContext;
use style::properties::longhands::font_feature_settings;
use style::properties::longhands::font_feature_settings::computed_value;
use style::properties::longhands::font_feature_settings::computed_value::FeatureTagValue;
use style::stylesheets::Origin;
use url::Url;

#[test]
fn font_feature_settings_should_parse_properly() {
    let normal = parse_longhand!(font_feature_settings, "normal");
    let normal_computed = computed_value::T::Normal;
    assert_eq!(normal, normal_computed);

    let on = parse_longhand!(font_feature_settings, "\"abcd\" on");
    let on_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 1 }
    ]);
    assert_eq!(on, on_computed);

    let off = parse_longhand!(font_feature_settings, "\"abcd\" off");
    let off_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 0 }
    ]);
    assert_eq!(off, off_computed);

    let no_value = parse_longhand!(font_feature_settings, "\"abcd\"");
    let no_value_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 1 }
    ]);
    assert_eq!(no_value, no_value_computed);

    let pos_integer = parse_longhand!(font_feature_settings, "\"abcd\" 100");
    let pos_integer_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 100 }
    ]);
    assert_eq!(pos_integer, pos_integer_computed);

    let multiple = parse_longhand!(font_feature_settings, "\"abcd\" off, \"efgh\"");
    let multiple_computed = computed_value::T::Tag(vec![
        FeatureTagValue { tag: String::from("abcd"), value: 0 },
        FeatureTagValue { tag: String::from("efgh"), value: 1 }
    ]);
    assert_eq!(multiple, multiple_computed);
}

#[test]
fn font_feature_settings_should_throw_on_bad_input() {
    let url = Url::parse("http://localhost").unwrap();
    let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));

    let mut empty = Parser::new("");
    assert!(font_feature_settings::parse(&context, &mut empty).is_err());

    let mut negative = Parser::new("\"abcd\" -1");
    assert!(font_feature_settings::parse(&context, &mut negative).is_err());

    let mut short_tag = Parser::new("\"abc\"");
    assert!(font_feature_settings::parse(&context, &mut short_tag).is_err());

    let mut illegal_tag = Parser::new("\"abcó\"");
    assert!(font_feature_settings::parse(&context, &mut illegal_tag).is_err());
}

#[test]
fn font_feature_settings_to_css() {
    assert_roundtrip_with_context!(font_feature_settings::parse, "normal");
    assert_roundtrip_with_context!(font_feature_settings::parse, "\"abcd\"", "\"abcd\" 1");
    assert_roundtrip_with_context!(font_feature_settings::parse, "\"abcd\" on", "\"abcd\" 1");
    assert_roundtrip_with_context!(font_feature_settings::parse, "\"abcd\" off", "\"abcd\" 0");
    assert_roundtrip_with_context!(font_feature_settings::parse, "\"abcd\" 4");
    assert_roundtrip_with_context!(font_feature_settings::parse, "\"abcd\", \"efgh\"",
                                                                 "\"abcd\" 1, \"efgh\" 1");
}
<|endoftext|>


<commit_before>use event::{Event, Rule, State};
use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    fn start_rule(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            return None
        }

        let c = self.bytes[self.offset];
        if c == b'}' {
            self.offset += 1;
            return Some(self.end())
        }
        if c == b'$' {
            return Some(self.next_variable())
        }

        let d = self.bytes[self.offset + 1];
        if c == b'/' && d == b'*' {
            return Some(self.next_comment())
        }

        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = match self.stack.pop() {
            Some(r) => r,
            None => {
                println!("Unexpected empty stack!");
                return Event::End(Rule::SassRule)
            },
        };
        self.state = State::StartRule;
        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let i = self.offset;
        self.offset += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
    }

    fn next_comment(&mut self) -> Event<'a> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2]))
            } else {
                i += 1;
            }
        }
        Event::End(Rule::SassRule)
    }

    fn next_variable(&mut self) -> Event<'a> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Variable(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )
            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            return self.next_comment()
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InSelectors;
                self.stack.push(Rule::SassRule);
                return Event::Start(Rule::SassRule)
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_selector(&mut self) -> Event<'a> {
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}
<commit_msg>Make skip leading whitespace skip inline comments too<commit_after>use event::{Event, Rule, State};
use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

fn isnt_newline(c: u8) -> bool {
    !is_newline(c)
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    fn start_rule(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            return None
        }

        let c = self.bytes[self.offset];
        if c == b'}' {
            self.offset += 1;
            return Some(self.end())
        }
        if c == b'$' {
            return Some(self.next_variable())
        }

        let d = self.bytes[self.offset + 1];
        if c == b'/' && d == b'*' {
            return Some(self.next_comment())
        }

        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = match self.stack.pop() {
            Some(r) => r,
            None => {
                println!("Unexpected empty stack!");
                return Event::End(Rule::SassRule)
            },
        };
        self.state = State::StartRule;
        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let mut i = self.offset;
        let limit = self.sass.len();

        while i < limit {
            let c = self.bytes[i];
            if is_ascii_whitespace(c) {
                i += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
            } else if c == b'/' && i + 1 < limit && self.bytes[i + 1] == b'/' {
                i += self.scan_while(&self.sass[i..self.sass.len()], isnt_newline);
            } else {
                self.offset = i;
                return
            }
        }
        self.offset = limit;
    }

    fn next_comment(&mut self) -> Event<'a> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2]))
            } else {
                i += 1;
            }
        }
        Event::End(Rule::SassRule)
    }

    fn next_variable(&mut self) -> Event<'a> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Variable(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )
            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            return self.next_comment()
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InSelectors;
                self.stack.push(Rule::SassRule);
                return Event::Start(Rule::SassRule)
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    fn next_selector(&mut self) -> Event<'a> {
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>use num::Num;

#[inline(always)]
pub fn rotation_x<T: Num>(out: [T; 4]) -> T {
    (T::from_isize(2isize) * out[0] * out[3] + T::from_isize(2isize) * out[1] * out[2])
        .atan2(T::one() - T::from_isize(2isize) * (out[2] * out[2] + out[3] * out[3]))
}

#[inline(always)]
pub fn rotation_y<T: Num>(out: [T; 4]) -> T {
    let theta = T::from_isize(2isize) * (out[0] * out[2] + out[3] * out[1]);
    (if theta < -T::one() {-T::one()} else if theta > T::one() {T::one()} else {theta}).asin()
}

#[inline(always)]
pub fn rotation_z<T: Num>(out: [T; 4]) -> T {
    (T::from_isize(2isize) * out[0] * out[1] + T::from_isize(2isize) * out[2] * out[3])
        .atan2(T::one() - T::from_isize(2isize) * (out[1] * out[1] + out[2] * out[2]))
}

#[inline(always)]
pub fn rotate_x<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let bx = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw + aw * bx;
    out[1] = ay * bw + az * bx;
    out[2] = az * bw - ay * bx;
    out[3] = aw * bw - ax * bx;
    out
}

#[inline(always)]
pub fn rotate_y<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let by = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw - az * by;
    out[1] = ay * bw + aw * by;
    out[2] = az * bw + ax * by;
    out[3] = aw * bw - ay * by;
    out
}

#[inline(always)]
pub fn rotate_z<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let bz = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw + ay * bz;
    out[1] = ay * bw - ax * bz;
    out[2] = az * bw + aw * bz;
    out[3] = aw * bw - az * bz;
    out
}

#[inline(always)]
pub fn rotate<T: Num>(out: &mut [T; 4], a: [T; 4], x: T, y: T, z: T) -> &mut [T; 4] {
    rotate_z(out, a, z);
    rotate_x(out, a, x);
    rotate_y(out, a, y);
    out
}

#[inline(always)]
pub fn look_rotation<T: Num>(out: &mut [T; 4], forward: [T; 3], up: [T; 3]) -> &mut [T; 4] {
    let fx = forward[0];
    let fy = forward[1];
    let fz = forward[2];
    let ux = up[0];
    let uy = up[1];
    let uz = up[2];

    let ax = uy * fz - uz * fy;
    let ay = uz * fx - ux * fz;
    let az = ux * fy - uy * fx;

    let d = (T::one() + ux * fx + uy * fy + uz * fz) * T::from_isize(2isize);
    let dsq = d * d;
    let s = if dsq != T::zero() {T::one() / dsq} else {dsq};

    out[0] = ax * s;
    out[1] = ay * s;
    out[2] = az * s;
    out[3] = dsq / T::from_isize(2isize);
    out
}

#[inline(always)]
pub fn from_axis_angle<T: Num>(out: &mut [T; 4], axis: [T; 3], angle: T) -> &mut [T; 4] {
    let half_angle = angle / T::from_isize(2isize);
    let s = half_angle.sin();

    out[0] = axis[0] * s;
    out[1] = axis[1] * s;
    out[2] = axis[2] * s;
    out[3] = half_angle.cos();
    out
}

#[inline(always)]
pub fn from_mat<T: Num>(
    out: &mut [T; 4],
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> &mut [T; 4] {
    let trace = m11 + m22 + m33;

    if trace > T::zero() {
        let s = T::from_f32(0.5f32) / (trace + T::one()).sqrt();

        out[3] = T::from_f32(0.25f32) / s;
        out[0] = (m32 - m23) * s;
        out[1] = (m13 - m31) * s;
        out[2] = (m21 - m12) * s;
    } else if m11 > m22 && m11 > m33 {
        let s = T::from_isize(2isize) * (T::one() + m11 - m22 - m33).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m32 - m23) * inv_s;
        out[0] = s / T::from_isize(4isize);
        out[1] = (m12 + m21) * inv_s;
        out[2] = (m13 + m31) * inv_s;
    } else if m22 > m33 {
        let s = T::from_isize(2isize) * (T::one() + m22 - m11 - m33).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m13 - m31) * inv_s;
        out[0] = (m12 + m21) * inv_s;
        out[1] = s / T::from_isize(4isize);
        out[2] = (m23 + m32) * inv_s;
    } else {
        let s = T::from_isize(2isize) * (T::one() + m33 - m11 - m22).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m21 - m12) * inv_s;
        out[0] = (m13 + m31) * inv_s;
        out[1] = (m23 + m32) * inv_s;
        out[2] = s / T::from_isize(4isize);
    }
    out
}

#[inline(always)]
pub fn from_mat2<T: Num>(out: &mut [T; 4], m: [T; 4]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[2], T::zero(),
        m[1], m[3], T::zero(),
        T::zero(), T::zero(), T::one()
    )
}

#[inline(always)]
pub fn from_mat32<T: Num>(out: &mut [T; 4], m: [T; 6]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[2], T::zero(),
        m[1], m[3], T::zero(),
        T::zero(), T::zero(), T::one()
    )
}

#[inline(always)]
pub fn from_mat3<T: Num>(out: &mut [T; 4], m: [T; 9]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[3], m[6],
        m[1], m[4], m[7],
        m[2], m[5], m[8]
    )
}

#[inline(always)]
pub fn from_mat4<T: Num>(out: &mut [T; 4], m: [T; 16]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[4], m[8],
        m[1], m[5], m[9],
        m[2], m[6], m[10]
    )
}
<commit_msg>updates<commit_after>use num::Num;
use create::{clone, create};

#[inline(always)]
pub fn rotation_x<T: Num>(out: [T; 4]) -> T {
    (T::from_isize(2isize) * out[0] * out[3] + T::from_isize(2isize) * out[1] * out[2])
        .atan2(T::one() - T::from_isize(2isize) * (out[2] * out[2] + out[3] * out[3]))
}

#[inline(always)]
pub fn rotation_y<T: Num>(out: [T; 4]) -> T {
    let theta = T::from_isize(2isize) * (out[0] * out[2] + out[3] * out[1]);
    (if theta < -T::one() {-T::one()} else if theta > T::one() {T::one()} else {theta}).asin()
}

#[inline(always)]
pub fn rotation_z<T: Num>(out: [T; 4]) -> T {
    (T::from_isize(2isize) * out[0] * out[1] + T::from_isize(2isize) * out[2] * out[3])
        .atan2(T::one() - T::from_isize(2isize) * (out[1] * out[1] + out[2] * out[2]))
}

#[inline(always)]
pub fn rotate_x<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let bx = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw + aw * bx;
    out[1] = ay * bw + az * bx;
    out[2] = az * bw - ay * bx;
    out[3] = aw * bw - ax * bx;
    out
}

#[inline(always)]
pub fn rotate_y<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let by = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw - az * by;
    out[1] = ay * bw + aw * by;
    out[2] = az * bw + ax * by;
    out[3] = aw * bw - ay * by;
    out
}

#[inline(always)]
pub fn rotate_z<T: Num>(out: &mut [T; 4], a: [T; 4], angle: T) -> &mut [T; 4] {
    let ax = a[0];
    let ay = a[1];
    let az = a[2];
    let aw = a[3];
    let half_angle = angle / T::from_isize(2isize);
    let bz = half_angle.sin();
    let bw = half_angle.cos();

    out[0] = ax * bw + ay * bz;
    out[1] = ay * bw - ax * bz;
    out[2] = az * bw + aw * bz;
    out[3] = aw * bw - az * bz;
    out
}

#[inline(always)]
pub fn rotate<T: Num>(out: &mut [T; 4], a: [T; 4], x: T, y: T, z: T) -> &mut [T; 4] {
    let mut tmp_a = clone(a);
    let mut tmp_b = create(T::zero(), T::zero(), T::zero(), T::one());
    rotate_z(&mut tmp_a, a, z);
    rotate_x(&mut tmp_b, tmp_a, x);
    rotate_y(out, tmp_b, y);
    out
}

#[inline(always)]
pub fn look_rotation<T: Num>(out: &mut [T; 4], forward: [T; 3], up: [T; 3]) -> &mut [T; 4] {
    let fx = forward[0];
    let fy = forward[1];
    let fz = forward[2];
    let ux = up[0];
    let uy = up[1];
    let uz = up[2];

    let ax = uy * fz - uz * fy;
    let ay = uz * fx - ux * fz;
    let az = ux * fy - uy * fx;

    let d = (T::one() + ux * fx + uy * fy + uz * fz) * T::from_isize(2isize);
    let dsq = d * d;
    let s = if dsq != T::zero() {T::one() / dsq} else {dsq};

    out[0] = ax * s;
    out[1] = ay * s;
    out[2] = az * s;
    out[3] = dsq / T::from_isize(2isize);
    out
}

#[inline(always)]
pub fn from_axis_angle<T: Num>(out: &mut [T; 4], axis: [T; 3], angle: T) -> &mut [T; 4] {
    let half_angle = angle / T::from_isize(2isize);
    let s = half_angle.sin();

    out[0] = axis[0] * s;
    out[1] = axis[1] * s;
    out[2] = axis[2] * s;
    out[3] = half_angle.cos();
    out
}

#[inline(always)]
pub fn from_mat<T: Num>(
    out: &mut [T; 4],
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> &mut [T; 4] {
    let trace = m11 + m22 + m33;

    if trace > T::zero() {
        let s = T::from_f32(0.5f32) / (trace + T::one()).sqrt();

        out[3] = T::from_f32(0.25f32) / s;
        out[0] = (m32 - m23) * s;
        out[1] = (m13 - m31) * s;
        out[2] = (m21 - m12) * s;
    } else if m11 > m22 && m11 > m33 {
        let s = T::from_isize(2isize) * (T::one() + m11 - m22 - m33).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m32 - m23) * inv_s;
        out[0] = s / T::from_isize(4isize);
        out[1] = (m12 + m21) * inv_s;
        out[2] = (m13 + m31) * inv_s;
    } else if m22 > m33 {
        let s = T::from_isize(2isize) * (T::one() + m22 - m11 - m33).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m13 - m31) * inv_s;
        out[0] = (m12 + m21) * inv_s;
        out[1] = s / T::from_isize(4isize);
        out[2] = (m23 + m32) * inv_s;
    } else {
        let s = T::from_isize(2isize) * (T::one() + m33 - m11 - m22).sqrt();
        let inv_s = T::one() / s;

        out[3] = (m21 - m12) * inv_s;
        out[0] = (m13 + m31) * inv_s;
        out[1] = (m23 + m32) * inv_s;
        out[2] = s / T::from_isize(4isize);
    }
    out
}

#[inline(always)]
pub fn from_mat2<T: Num>(out: &mut [T; 4], m: [T; 4]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[2], T::zero(),
        m[1], m[3], T::zero(),
        T::zero(), T::zero(), T::one()
    )
}

#[inline(always)]
pub fn from_mat32<T: Num>(out: &mut [T; 4], m: [T; 6]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[2], T::zero(),
        m[1], m[3], T::zero(),
        T::zero(), T::zero(), T::one()
    )
}

#[inline(always)]
pub fn from_mat3<T: Num>(out: &mut [T; 4], m: [T; 9]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[3], m[6],
        m[1], m[4], m[7],
        m[2], m[5], m[8]
    )
}

#[inline(always)]
pub fn from_mat4<T: Num>(out: &mut [T; 4], m: [T; 16]) -> &mut [T; 4] {
    from_mat(
        out,
        m[0], m[4], m[8],
        m[1], m[5], m[9],
        m[2], m[6], m[10]
    )
}
<|endoftext|>


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

//! An implementation of `VatNetwork` for the common case of a client-server connection.

use capnp::message::ReaderOptions;
use capnp::capability::Promise;
use futures::{AsyncRead, AsyncWrite, FutureExt, TryFutureExt};
use futures::channel::oneshot;

use std::cell::RefCell;
use std::rc::{Rc, Weak};

pub type VatId = crate::rpc_twoparty_capnp::Side;

struct IncomingMessage {
    message: ::capnp::message::Reader<capnp::serialize::OwnedSegments>,
}

impl IncomingMessage {
    pub fn new(message: ::capnp::message::Reader<capnp::serialize::OwnedSegments>) -> IncomingMessage {
        IncomingMessage { message: message }
    }
}

impl crate::IncomingMessage for IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root()
    }
}

struct OutgoingMessage {
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
    sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
}

impl crate::OutgoingMessage for OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>> {
        self.message.get_root()
    }

    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root_as_reader()
    }

    fn send(self: Box<Self>)
            ->
        (Promise<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>, ::capnp::Error>,
         Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>)
    {
        let tmp = *self;
        let OutgoingMessage {message, mut sender} = tmp;
        let m = Rc::new(message);
        (Promise::from_future(sender.send(m.clone()).map_err(|e| e.into())), m)
    }

    fn take(self: Box<Self>)
            -> ::capnp::message::Builder<::capnp::message::HeapAllocator>
    {
        self.message
    }
}

struct ConnectionInner<T> where T: AsyncRead + 'static {
    input_stream: Rc<RefCell<Option<T>>>,
    sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
    side: crate::rpc_twoparty_capnp::Side,
    receive_options: ReaderOptions,
    on_disconnect_fulfiller: Option<oneshot::Sender<()>>,
}

struct Connection<T> where T: AsyncRead + 'static {
    inner: Rc<RefCell<ConnectionInner<T>>>,
}

impl <T> Drop for ConnectionInner<T> where T: AsyncRead {
    fn drop(&mut self) {
        let maybe_fulfiller = ::std::mem::replace(&mut self.on_disconnect_fulfiller, None);
        match maybe_fulfiller {
            Some(fulfiller) => {
                let _ = fulfiller.send(());
            }
            None => unreachable!(),
        }
    }
}

impl <T> Connection<T> where T: AsyncRead {
    fn new(input_stream: T,
           sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
           side: crate::rpc_twoparty_capnp::Side,
           receive_options: ReaderOptions,
           on_disconnect_fulfiller: oneshot::Sender<()>,
           ) -> Connection<T>
    {

        Connection {
            inner: Rc::new(RefCell::new(
                ConnectionInner {
                    input_stream: Rc::new(RefCell::new(Some(input_stream))),
                    sender: sender,
                    side: side,
                    receive_options: receive_options,
                    on_disconnect_fulfiller: Some(on_disconnect_fulfiller),
                })),
        }
    }
}

impl <T> crate::Connection<crate::rpc_twoparty_capnp::Side> for Connection<T>
    where T: AsyncRead + Unpin
{
    fn get_peer_vat_id(&self) -> crate::rpc_twoparty_capnp::Side {
        self.inner.borrow().side
    }

    fn new_outgoing_message(&mut self, _first_segment_word_size: u32) -> Box<dyn crate::OutgoingMessage> {
        Box::new(OutgoingMessage {
            message: ::capnp::message::Builder::new_default(),
            sender: self.inner.borrow().sender.clone(),
        })
    }

    fn receive_incoming_message(&mut self) -> Promise<Option<Box<dyn crate::IncomingMessage + 'static>>, ::capnp::Error> {
        let mut inner = self.inner.borrow_mut();
        let maybe_input_stream = ::std::mem::replace(&mut *inner.input_stream.borrow_mut(), None);
        let return_it_here = inner.input_stream.clone();
        match maybe_input_stream {
            Some(mut s) => {
                let receive_options = inner.receive_options;
                Promise::from_future(async move {
                    let maybe_message = ::capnp_futures::serialize::read_message(&mut s, receive_options).await?;
                    *return_it_here.borrow_mut() = Some(s);
                    Ok(maybe_message.map(|message|
                                         Box::new(IncomingMessage::new(message)) as Box<dyn crate::IncomingMessage>))
                })
            }
            None => {
                Promise::err(::capnp::Error::failed("this should not be possible".to_string()))
             //   unreachable!(),
            }
        }
    }

    fn shutdown(&mut self, result: ::capnp::Result<()>) -> Promise<(), ::capnp::Error> {
        Promise::from_future(self.inner.borrow_mut().sender.terminate(result).map_err(|e| e.into()))
    }
}

/// A vat network with two parties, the client and the server.
pub struct VatNetwork<T> where T: AsyncRead + 'static + Unpin {
    connection: Option<Connection<T>>,

    // HACK
    weak_connection_inner: Weak<RefCell<ConnectionInner<T>>>,

    execution_driver: futures::future::Shared<Promise<(), ::capnp::Error>>,
    side: crate::rpc_twoparty_capnp::Side,
}

impl <T> VatNetwork<T> where T: AsyncRead + Unpin {
    /// Creates a new two-party vat network that will receive data on `input_stream` and send data on
    /// `output_stream`.
    ///
    /// `side` indicates whether this is the client or the server side of the connection. This has no
    /// effect on the data sent over the connection; it merely exists so that `RpcNetwork::bootstrap` knows
    /// whether to return the local or the remote bootstrap capability. `VatId` parameters like this one
    /// will make more sense once we have vat networks with more than two parties.
    ///
    /// The options in `receive_options` will be used when reading the messages that come in on `input_stream`.
    pub fn new<U>(input_stream: T,
               output_stream: U,
               side: crate::rpc_twoparty_capnp::Side,
               receive_options: ReaderOptions) -> VatNetwork<T>
        where U: AsyncWrite + 'static + Unpin,
    {

        let (fulfiller, disconnect_promise) = oneshot::channel();
        let disconnect_promise = disconnect_promise
            .map_err(|_| ::capnp::Error::disconnected("disconnected".into()));

        let (execution_driver, sender) = {
            let (tx, write_queue) = ::capnp_futures::write_queue(output_stream);

            // Don't use `.join()` here because we need to make sure to wait for `disconnect_promise` to
            // resolve even if `write_queue` resolves to an error.
            (Promise::from_future(
                write_queue
                    .then(move |r| disconnect_promise.then(move |_| futures::future::ready(r)).map_ok(|_| ()))).shared(),
             tx)
        };

        let connection = Connection::new(input_stream, sender, side, receive_options, fulfiller);
        let weak_inner = Rc::downgrade(&connection.inner);
        VatNetwork {
            connection: Some(connection),
            weak_connection_inner: weak_inner,
            execution_driver: execution_driver,
            side: side,
        }
    }
}

impl <T> crate::VatNetwork<VatId> for VatNetwork<T>
    where T: AsyncRead + Unpin
{
    fn connect(&mut self, host_id: VatId) -> Option<Box<dyn crate::Connection<VatId>>> {
        if host_id == self.side {
            None
        } else {
            let connection = ::std::mem::replace(&mut self.connection, None);
            match connection {
                Some(c) => {
                    Some(Box::new(c))
                } None => {
                    match self.weak_connection_inner.upgrade() {
                        Some(connection_inner) => {
                            Some(Box::new(Connection { inner: connection_inner }))
                        }
                        None => {
                            panic!("tried to reconnect a disconnected twoparty vat network.")
                        }
                    }
                }
            }
        }
    }

    fn accept(&mut self) -> Promise<Box<dyn crate::Connection<VatId>>, ::capnp::Error> {
        let connection = ::std::mem::replace(&mut self.connection, None);
        match connection {
            Some(c) => Promise::ok(Box::new(c) as Box<dyn crate::Connection<VatId>>),
            None => Promise::from_future(::futures::future::pending()),
        }
    }

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

//! An implementation of `VatNetwork` for the common case of a client-server connection.

use capnp::message::ReaderOptions;
use capnp::capability::Promise;
use futures::{AsyncRead, AsyncWrite, FutureExt, TryFutureExt};
use futures::channel::oneshot;

use std::cell::RefCell;
use std::rc::{Rc, Weak};

pub type VatId = crate::rpc_twoparty_capnp::Side;

struct IncomingMessage {
    message: ::capnp::message::Reader<capnp::serialize::OwnedSegments>,
}

impl IncomingMessage {
    pub fn new(message: ::capnp::message::Reader<capnp::serialize::OwnedSegments>) -> IncomingMessage {
        IncomingMessage { message: message }
    }
}

impl crate::IncomingMessage for IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root()
    }
}

struct OutgoingMessage {
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
    sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
}

impl crate::OutgoingMessage for OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>> {
        self.message.get_root()
    }

    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root_as_reader()
    }

    fn send(self: Box<Self>)
            ->
        (Promise<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>, ::capnp::Error>,
         Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>)
    {
        let tmp = *self;
        let OutgoingMessage {message, mut sender} = tmp;
        let m = Rc::new(message);
        (Promise::from_future(sender.send(m.clone()).map_err(|e| e.into())), m)
    }

    fn take(self: Box<Self>)
            -> ::capnp::message::Builder<::capnp::message::HeapAllocator>
    {
        self.message
    }
}

struct ConnectionInner<T> where T: AsyncRead + 'static {
    input_stream: Rc<RefCell<Option<T>>>,
    sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
    side: crate::rpc_twoparty_capnp::Side,
    receive_options: ReaderOptions,
    on_disconnect_fulfiller: Option<oneshot::Sender<()>>,
}

struct Connection<T> where T: AsyncRead + 'static {
    inner: Rc<RefCell<ConnectionInner<T>>>,
}

impl <T> Drop for ConnectionInner<T> where T: AsyncRead {
    fn drop(&mut self) {
        let maybe_fulfiller = ::std::mem::replace(&mut self.on_disconnect_fulfiller, None);
        match maybe_fulfiller {
            Some(fulfiller) => {
                let _ = fulfiller.send(());
            }
            None => unreachable!(),
        }
    }
}

impl <T> Connection<T> where T: AsyncRead {
    fn new(input_stream: T,
           sender: ::capnp_futures::Sender<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>>,
           side: crate::rpc_twoparty_capnp::Side,
           receive_options: ReaderOptions,
           on_disconnect_fulfiller: oneshot::Sender<()>,
           ) -> Connection<T>
    {

        Connection {
            inner: Rc::new(RefCell::new(
                ConnectionInner {
                    input_stream: Rc::new(RefCell::new(Some(input_stream))),
                    sender: sender,
                    side: side,
                    receive_options: receive_options,
                    on_disconnect_fulfiller: Some(on_disconnect_fulfiller),
                })),
        }
    }
}

impl <T> crate::Connection<crate::rpc_twoparty_capnp::Side> for Connection<T>
    where T: AsyncRead + Unpin
{
    fn get_peer_vat_id(&self) -> crate::rpc_twoparty_capnp::Side {
        self.inner.borrow().side
    }

    fn new_outgoing_message(&mut self, _first_segment_word_size: u32) -> Box<dyn crate::OutgoingMessage> {
        Box::new(OutgoingMessage {
            message: ::capnp::message::Builder::new_default(),
            sender: self.inner.borrow().sender.clone(),
        })
    }

    fn receive_incoming_message(&mut self) -> Promise<Option<Box<dyn crate::IncomingMessage + 'static>>, ::capnp::Error> {
        #[allow(unused_mut)] // rustc 1.44 still requires this `mut`
        let mut inner = self.inner.borrow_mut();

        let maybe_input_stream = ::std::mem::replace(&mut *inner.input_stream.borrow_mut(), None);
        let return_it_here = inner.input_stream.clone();
        match maybe_input_stream {
            Some(mut s) => {
                let receive_options = inner.receive_options;
                Promise::from_future(async move {
                    let maybe_message = ::capnp_futures::serialize::read_message(&mut s, receive_options).await?;
                    *return_it_here.borrow_mut() = Some(s);
                    Ok(maybe_message.map(|message|
                                         Box::new(IncomingMessage::new(message)) as Box<dyn crate::IncomingMessage>))
                })
            }
            None => {
                Promise::err(::capnp::Error::failed("this should not be possible".to_string()))
             //   unreachable!(),
            }
        }
    }

    fn shutdown(&mut self, result: ::capnp::Result<()>) -> Promise<(), ::capnp::Error> {
        Promise::from_future(self.inner.borrow_mut().sender.terminate(result).map_err(|e| e.into()))
    }
}

/// A vat network with two parties, the client and the server.
pub struct VatNetwork<T> where T: AsyncRead + 'static + Unpin {
    connection: Option<Connection<T>>,

    // HACK
    weak_connection_inner: Weak<RefCell<ConnectionInner<T>>>,

    execution_driver: futures::future::Shared<Promise<(), ::capnp::Error>>,
    side: crate::rpc_twoparty_capnp::Side,
}

impl <T> VatNetwork<T> where T: AsyncRead + Unpin {
    /// Creates a new two-party vat network that will receive data on `input_stream` and send data on
    /// `output_stream`.
    ///
    /// `side` indicates whether this is the client or the server side of the connection. This has no
    /// effect on the data sent over the connection; it merely exists so that `RpcNetwork::bootstrap` knows
    /// whether to return the local or the remote bootstrap capability. `VatId` parameters like this one
    /// will make more sense once we have vat networks with more than two parties.
    ///
    /// The options in `receive_options` will be used when reading the messages that come in on `input_stream`.
    pub fn new<U>(input_stream: T,
               output_stream: U,
               side: crate::rpc_twoparty_capnp::Side,
               receive_options: ReaderOptions) -> VatNetwork<T>
        where U: AsyncWrite + 'static + Unpin,
    {

        let (fulfiller, disconnect_promise) = oneshot::channel();
        let disconnect_promise = disconnect_promise
            .map_err(|_| ::capnp::Error::disconnected("disconnected".into()));

        let (execution_driver, sender) = {
            let (tx, write_queue) = ::capnp_futures::write_queue(output_stream);

            // Don't use `.join()` here because we need to make sure to wait for `disconnect_promise` to
            // resolve even if `write_queue` resolves to an error.
            (Promise::from_future(
                write_queue
                    .then(move |r| disconnect_promise.then(move |_| futures::future::ready(r)).map_ok(|_| ()))).shared(),
             tx)
        };

        let connection = Connection::new(input_stream, sender, side, receive_options, fulfiller);
        let weak_inner = Rc::downgrade(&connection.inner);
        VatNetwork {
            connection: Some(connection),
            weak_connection_inner: weak_inner,
            execution_driver: execution_driver,
            side: side,
        }
    }
}

impl <T> crate::VatNetwork<VatId> for VatNetwork<T>
    where T: AsyncRead + Unpin
{
    fn connect(&mut self, host_id: VatId) -> Option<Box<dyn crate::Connection<VatId>>> {
        if host_id == self.side {
            None
        } else {
            let connection = ::std::mem::replace(&mut self.connection, None);
            match connection {
                Some(c) => {
                    Some(Box::new(c))
                } None => {
                    match self.weak_connection_inner.upgrade() {
                        Some(connection_inner) => {
                            Some(Box::new(Connection { inner: connection_inner }))
                        }
                        None => {
                            panic!("tried to reconnect a disconnected twoparty vat network.")
                        }
                    }
                }
            }
        }
    }

    fn accept(&mut self) -> Promise<Box<dyn crate::Connection<VatId>>, ::capnp::Error> {
        let connection = ::std::mem::replace(&mut self.connection, None);
        match connection {
            Some(c) => Promise::ok(Box::new(c) as Box<dyn crate::Connection<VatId>>),
            None => Promise::from_future(::futures::future::pending()),
        }
    }

    fn drive_until_shutdown(&mut self) -> Promise<(), ::capnp::Error> {
        Promise::from_future(self.execution_driver.clone())
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::Instant;

use crate::cmdline::Opt;
use crate::core::*;
use crate::utils::is_dev_machine;

const TMUX: &str = "tmux";

pub struct Tmux {
    nmk_home: PathBuf,
    tmux_dir: PathBuf,
    config: PathBuf,
    pub bin: PathBuf,
    pub version: String,
}

fn find_config(tmux_dir: &PathBuf, version: &str) -> PathBuf {
    let config = tmux_dir.join(format!("{}.conf", version));
    assert!(config.exists(), "unsupported tmux version: {}", version);
    config
}

fn find_version() -> String {
    let output = Command::new(TMUX)
        .arg("-V")
        .output()
        .expect("tmux not found");
    if !output.status.success() {
        let code = output.status.code().expect("tmux is terminated by signal");
        panic!("tmux exit with status: {}", code);
    }
    let unparsed_version =
        std::str::from_utf8(&output.stdout).expect("tmux version output contain non utf-8");
    unparsed_version
        .trim()
        .split(" ")
        .nth(1)
        .unwrap_or_else(|| panic!("bad output: {}", unparsed_version))
        .to_string()
}

fn is_server_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|status| status.success())
        .unwrap_or(false);
    log::debug!("server {} running", if running { "is" } else { "is not" });
    running
}

impl Tmux {
    pub fn new(nmk_home: &Path) -> Tmux {
        let tmux_dir = nmk_home.join("tmux");
        assert!(
            tmux_dir.is_dir(),
            "{} is not directory",
            tmux_dir.to_string_lossy()
        );
        let bin = which::which(TMUX).expect("Cannot find tmux binary");
        let version = find_version();
        let config = find_config(&tmux_dir, &version);
        Tmux {
            nmk_home: nmk_home.to_owned(),
            tmux_dir,
            bin,
            version,
            config,
        }
    }

    pub fn setup_environment(&self, arg: &Opt, is_color_term: bool) {
        set_env(
            "NMK_TMUX_DEFAULT_SHELL",
            which::which("zsh").expect("zsh not found"),
        );
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.tmux_dir.join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
        let default_term = if is_color_term {
            "screen-256color"
        } else {
            "screen"
        };
        set_env("NMK_TMUX_DEFAULT_TERMINAL", default_term);
        set_env("NMK_TMUX_256_COLOR", one_hot!(is_color_term));
    }

    fn print_usage_time(&self, arg: &Opt, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            log::debug!("usage time: {}ms", before_exec);
        }
    }

    pub fn login_shell(&self, arg: &Opt, start: &Instant, is_color_term: bool) -> ! {
        let mut cmd = Command::new(&self.bin);
        cmd.args(&["-L", &arg.socket]);
        if is_color_term {
            cmd.arg("-2");
        }
        if arg.unicode {
            cmd.arg("-u");
        }
        cmd.arg("-f");
        cmd.arg(&self.config);
        cmd.args(&["-c", "exec zsh --login"]);
        log::debug!("login command: {:?}", cmd);
        self.print_usage_time(&arg, &start);
        let err = cmd.exec();
        panic!("exec fail with {:?}", err);
    }

    pub fn exec(&self, arg: &Opt, start: &Instant, is_color_term: bool) -> ! {
        let mut cmd = Command::new(&self.bin);
        cmd.args(&["-L", &arg.socket]);
        if is_color_term {
            cmd.arg("-2");
        }
        if arg.unicode {
            cmd.arg("-u");
        }
        if is_server_running(&arg.socket) {
            if !arg.tmux_args.is_empty() {
                cmd.args(arg.tmux_args.iter());
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    panic!("add --inception to allow nested tmux sessions");
                }
                cmd.arg("attach");
            }
        } else {
            cmd.arg("-f");
            cmd.arg(&self.config);
            cmd.args(arg.tmux_args.iter());
        }
        log::debug!("exec command: {:?}", cmd);
        self.print_usage_time(&arg, &start);
        if self.is_vendored_tmux() && is_dev_machine() {
            log::warn!("Using vendored tmux on development machine")
        }
        let err = cmd.exec();
        panic!("exec fail with {:?}", err);
    }

    pub fn is_vendored_tmux(&self) -> bool {
        self.bin.starts_with(&self.nmk_home)
    }
}
<commit_msg>Don't show full path to tmux in ps output<commit_after>use std::env;
use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::Instant;

use crate::cmdline::Opt;
use crate::core::*;
use crate::utils::is_dev_machine;

const TMUX: &str = "tmux";

pub struct Tmux {
    nmk_home: PathBuf,
    tmux_dir: PathBuf,
    config: PathBuf,
    pub bin: PathBuf,
    pub version: String,
}

fn find_config(tmux_dir: &PathBuf, version: &str) -> PathBuf {
    let config = tmux_dir.join(format!("{}.conf", version));
    assert!(config.exists(), "unsupported tmux version: {}", version);
    config
}

fn find_version() -> String {
    let output = Command::new(TMUX)
        .arg("-V")
        .output()
        .expect("tmux not found");
    if !output.status.success() {
        let code = output.status.code().expect("tmux is terminated by signal");
        panic!("tmux exit with status: {}", code);
    }
    let unparsed_version =
        std::str::from_utf8(&output.stdout).expect("tmux version output contain non utf-8");
    unparsed_version
        .trim()
        .split(" ")
        .nth(1)
        .unwrap_or_else(|| panic!("bad output: {}", unparsed_version))
        .to_string()
}

fn is_server_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|status| status.success())
        .unwrap_or(false);
    log::debug!("server {} running", if running { "is" } else { "is not" });
    running
}

impl Tmux {
    pub fn new(nmk_home: &Path) -> Tmux {
        let tmux_dir = nmk_home.join("tmux");
        assert!(
            tmux_dir.is_dir(),
            "{} is not directory",
            tmux_dir.to_string_lossy()
        );
        let bin = which::which(TMUX).expect("Cannot find tmux binary");
        let version = find_version();
        let config = find_config(&tmux_dir, &version);
        Tmux {
            nmk_home: nmk_home.to_owned(),
            tmux_dir,
            bin,
            version,
            config,
        }
    }

    pub fn setup_environment(&self, arg: &Opt, is_color_term: bool) {
        set_env(
            "NMK_TMUX_DEFAULT_SHELL",
            which::which("zsh").expect("zsh not found"),
        );
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.tmux_dir.join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
        let default_term = if is_color_term {
            "screen-256color"
        } else {
            "screen"
        };
        set_env("NMK_TMUX_DEFAULT_TERMINAL", default_term);
        set_env("NMK_TMUX_256_COLOR", one_hot!(is_color_term));
    }

    fn print_usage_time(&self, arg: &Opt, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            log::debug!("usage time: {}ms", before_exec);
        }
    }

    pub fn login_shell(&self, arg: &Opt, start: &Instant, is_color_term: bool) -> ! {
        let mut cmd = Command::new(&self.bin);
        cmd.args(&["-L", &arg.socket]);
        if is_color_term {
            cmd.arg("-2");
        }
        if arg.unicode {
            cmd.arg("-u");
        }
        cmd.arg("-f");
        cmd.arg(&self.config);
        cmd.args(&["-c", "exec zsh --login"]);
        log::debug!("login command: {:?}", cmd);
        self.print_usage_time(&arg, &start);
        let err = cmd.exec();
        panic!("exec fail with {:?}", err);
    }

    pub fn exec(&self, arg: &Opt, start: &Instant, is_color_term: bool) -> ! {
        let mut cmd = Command::new(TMUX);
        cmd.args(&["-L", &arg.socket]);
        if is_color_term {
            cmd.arg("-2");
        }
        if arg.unicode {
            cmd.arg("-u");
        }
        if is_server_running(&arg.socket) {
            if !arg.tmux_args.is_empty() {
                cmd.args(arg.tmux_args.iter());
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    panic!("add --inception to allow nested tmux sessions");
                }
                cmd.arg("attach");
            }
        } else {
            cmd.arg("-f");
            cmd.arg(&self.config);
            cmd.args(arg.tmux_args.iter());
        }
        log::debug!("exec command: {:?}", cmd);
        self.print_usage_time(&arg, &start);
        if self.is_vendored_tmux() && is_dev_machine() {
            log::warn!("Using vendored tmux on development machine")
        }
        let err = cmd.exec();
        panic!("exec fail with {:?}", err);
    }

    pub fn is_vendored_tmux(&self) -> bool {
        self.bin.starts_with(&self.nmk_home)
    }
}
<|endoftext|>


<commit_before>#![crate_name = "foo"]

// @has foo/fn.foo.html
// !@has - '//a[@href="http://a.a"]'
// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
// @has - '//a[@href="#another-one-urg"]' 'Another one urg'

/// fooo
///
/// # Implementing [stuff](http://a.a) somewhere
///
/// hello
///
/// # Another [one][two] urg
///
/// [two]: http://a.a
pub fn foo() {}
<commit_msg>Extend url in heading test a bit<commit_after>#![crate_name = "foo"]

// @has foo/fn.foo.html
// !@has - '//a[@href="http://a.a"]'
// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
// @has - '//a[@href="#another-one-urg"]' 'Another one urg'

/// fooo
///
/// # Implementing [stuff](http://a.a "title") somewhere
///
/// hello
///
/// # Another [one][two] urg
///
/// [two]: http://a.a
pub fn foo() {}
<|endoftext|>


<commit_before>// run-pass
#![feature(core_intrinsics)]

use std::intrinsics::*;

pub fn main() {
    unsafe {
        let mut x: Box<u8> = Box::new(0);
        let mut y: Box<u8> = Box::new(0);

        // test volatile load
        assert_eq!(volatile_load(&*x), 0);
        *x = 1;
        assert_eq!(volatile_load(&*x), 1);

        // test volatile store
        volatile_store(&mut *x, 2);
        assert_eq!(*x, 2);

        // test volatile copy memory
        volatile_copy_memory(&mut *y, &*x, 1);
        assert_eq!(*y, 2);

        // test volatile copy non-overlapping memory
        *x = 3;
        volatile_copy_nonoverlapping_memory(&mut *y, &*x, 1);
        assert_eq!(*y, 3);

        // test volatile set memory
        volatile_set_memory(&mut *x, 4, 1);
        assert_eq!(*x, 4);

        // test unaligned volatile load
        let arr: [u8; 3] = [1, 2, 3];
        let ptr = arr[1..].as_ptr() as *const u16;
        assert_eq!(unaligned_volatile_load(ptr), u16::from_ne_bytes([arr[1], arr[2]]));

        // test unaligned volatile store
        let ptr = arr[1..].as_ptr() as *mut u16;
        unaligned_volatile_store(ptr, 0);
        assert_eq!(arr, [1, 0, 0]);
    }
}
<commit_msg>Remove trailing whitespace<commit_after>// run-pass

#![feature(core_intrinsics)]

use std::intrinsics::*;

pub fn main() {
    unsafe {
        let mut x: Box<u8> = Box::new(0);
        let mut y: Box<u8> = Box::new(0);

        // test volatile load
        assert_eq!(volatile_load(&*x), 0);
        *x = 1;
        assert_eq!(volatile_load(&*x), 1);

        // test volatile store
        volatile_store(&mut *x, 2);
        assert_eq!(*x, 2);

        // test volatile copy memory
        volatile_copy_memory(&mut *y, &*x, 1);
        assert_eq!(*y, 2);

        // test volatile copy non-overlapping memory
        *x = 3;
        volatile_copy_nonoverlapping_memory(&mut *y, &*x, 1);
        assert_eq!(*y, 3);

        // test volatile set memory
        volatile_set_memory(&mut *x, 4, 1);
        assert_eq!(*x, 4);

        // test unaligned volatile load
        let arr: [u8; 3] = [1, 2, 3];
        let ptr = arr[1..].as_ptr() as *const u16;
        assert_eq!(unaligned_volatile_load(ptr), u16::from_ne_bytes([arr[1], arr[2]]));

        // test unaligned volatile store
        let ptr = arr[1..].as_ptr() as *mut u16;
        unaligned_volatile_store(ptr, 0);
        assert_eq!(arr, [1, 0, 0]);
    }
}
<|endoftext|>


<commit_before>use std::process;
use std::fs::File;
use std::io::{Read, BufReader};

use serde_json;
use std::collections::HashMap;
use std::collections::HashSet;

use web::data::{APIMaps, IdGeneSubsetMap, APIGeneSummary, APIAlleleDetails,
                GeneDetails, TermDetails, GenotypeDetails, ReferenceDetails};
use web::config::Config;
use api::query::{SingleOrMultiAllele, QueryExpressionFilter};

use flate2::read::GzDecoder;

use types::GeneUniquename;

pub struct ServerData {
    config_file_name: String,
    maps: APIMaps,
    search_maps_file_name: String,
    gene_subsets: IdGeneSubsetMap,
    gene_subsets_file_name: String,
}

fn load(config: &Config, search_maps_file_name: &str, gene_subsets_file_name: &str)
        -> (APIMaps, IdGeneSubsetMap)
{
    let file = match File::open(search_maps_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", search_maps_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut decoder = GzDecoder::new(reader).unwrap();
    let mut decoded_json = String::new();
    decoder.read_to_string(&mut decoded_json).unwrap();

    let query_api_maps: APIMaps =
        match serde_json::from_str(&decoded_json) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", search_maps_file_name, err);
                process::exit(1);
            },
        };

    let file = match File::open(gene_subsets_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", gene_subsets_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut gene_subsets: IdGeneSubsetMap =
        match serde_json::from_reader(reader) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", gene_subsets_file_name, err);
                process::exit(1);
            },
        };

    let mut new_entries: IdGeneSubsetMap = HashMap::new();

    let prefixes_to_remove: Vec<String> =
        config.server.subsets.prefixes_to_remove
        .iter().map(|prefix| prefix.clone() + ":").collect();

    // strip prefixes and add to map
    for (subset_name, subset_details) in gene_subsets.iter() {
        for prefix in &prefixes_to_remove {
            if subset_name.starts_with(prefix) {
                let new_subset_name = &subset_name[prefix.len()..];
                new_entries.insert(String::from(new_subset_name), subset_details.clone());
            }
        }
    }

    gene_subsets.extend(new_entries);

    (query_api_maps, gene_subsets)
}

impl ServerData {
    pub fn new(config_file_name: &str, search_maps_file_name: &str,
               gene_subsets_file_name: &str)
               -> ServerData
    {
        let config = Config::read(config_file_name);

        let (maps, gene_subsets) =
            load(&config, search_maps_file_name, gene_subsets_file_name);
        ServerData {
            config_file_name: config_file_name.into(),
            search_maps_file_name: search_maps_file_name.into(),
            maps: maps,
            gene_subsets_file_name: gene_subsets_file_name.into(),
            gene_subsets: gene_subsets,
        }
    }

    pub fn gene_uniquename_of_id(&self, id: &str) -> Option<GeneUniquename> {
        if self.maps.gene_summaries.contains_key(id) {
            Some(id.to_owned())
        } else {
            if let Some(gene_uniquename) =
                self.maps.gene_name_gene_map.get(id) {
                    Some(gene_uniquename.clone())
                } else {
                    None
                }
        }
    }

    pub fn get_gene_summary(&self, gene_uniquename: &str) -> Option<&APIGeneSummary> {
        self.maps.gene_summaries.get(gene_uniquename)
    }

    pub fn genes_of_termid(&self, term_id: &str) -> Vec<GeneUniquename> {
        match self.maps.termid_genes.get(term_id) {
            Some(gene_uniquenames) => {
                gene_uniquenames.iter().cloned().collect::<Vec<_>>()
            },
            None => vec![],
        }
    }

    pub fn genes_of_subset(&self, search_name: &str) -> Vec<GeneUniquename> {
        if search_name.starts_with('!') || search_name.ends_with('*') {
            let mut trimmed_search_name = search_name.to_owned();
            let invert_search = search_name.starts_with('!');
            let wildcard = search_name.ends_with('*');
            if invert_search {
                trimmed_search_name.remove(0);
            }
            if wildcard {
                trimmed_search_name.pop();
            }
            let mut genes = HashSet::new();
            for (subset_name, subset_details) in &self.gene_subsets {
                let name_matches =
                    wildcard && subset_name.starts_with(&trimmed_search_name) ||
                    trimmed_search_name.eq(subset_name);

                if !invert_search && name_matches || invert_search && !name_matches {
                    genes.extend(subset_details.elements.iter().cloned());
                }
            }
            genes.iter().cloned().collect::<Vec<_>>()
        } else {
            match self.gene_subsets.get(search_name) {
                Some(subset_details) => {
                    subset_details.elements.iter().cloned().collect::<Vec<_>>()
                },
                None => vec![],
            }
        }
    }

    pub fn genes_of_genotypes(&self, term_id: &str,
                              single_or_multi_allele: &SingleOrMultiAllele,
                              expression_filter: &Option<QueryExpressionFilter>)
                              -> Vec<GeneUniquename>
    {
        if let Some(annotations) = self.maps.termid_genotype_annotation.get(term_id) {
            let mut genes: HashSet<GeneUniquename> = HashSet::new();
            for annotation in annotations {

                let mut add_single = false;
                let mut add_multi = false;

                match *single_or_multi_allele {
                    SingleOrMultiAllele::Single => add_single = true,
                    SingleOrMultiAllele::Multi => add_multi = true,
                    SingleOrMultiAllele::Both => {
                        add_single = true;
                        add_multi = true;
                    },
                }

                let expression_matches =
                    |allele_details: &APIAlleleDetails| {
                        let expression = &allele_details.expression;
                        let allele_type = &allele_details.allele_type;
                        if let Some(ref expression_filter) = *expression_filter {
                            if *expression_filter == QueryExpressionFilter::Any {
                                return true;
                            }
                            if *expression_filter == QueryExpressionFilter::Null {
                                if allele_type == "deletion" {
                                    return true;
                                }
                                if let Some(ref expression) = *expression {
                                    expression == "Null"
                                } else {
                                    false
                                }
                            } else {
                                if *expression_filter == QueryExpressionFilter::WtOverexpressed {
                                    if let Some(ref expression) = *expression {
                                        expression == "Overexpression" &&
                                            allele_type == "wild_type"
                                    } else {
                                        false
                                    }
                                } else {
                                    false
                                }
                            }
                        } else {
                            true
                        }
                    };

                if annotation.is_multi && add_multi ||
                    !annotation.is_multi && add_single &&
                    expression_matches(&annotation.alleles[0]) {
                        for allele_details in &annotation.alleles {
                            genes.insert(allele_details.gene.clone());
                        }
                }
            }
            genes.into_iter().collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn filter_genes(&self, p: &Fn(&APIGeneSummary) -> bool)
                        -> Vec<GeneUniquename>
    {
        self.maps.gene_summaries.values()
            .filter(|ref summ| p(summ))
            .map(|ref summ| summ.uniquename.clone())
            .collect()
    }

    pub fn get_gene_details(&self, gene_uniquename: &str) -> Option<&GeneDetails> {
        self.maps.genes.get(gene_uniquename)
    }

    pub fn get_genotype_details(&self, genotype_uniquename: &str) -> Option<&GenotypeDetails> {
        self.maps.genotypes.get(genotype_uniquename)
    }

    pub fn get_term_details(&self, termid: &str) -> Option<&TermDetails> {
        self.maps.terms.get(termid)
    }

    pub fn get_reference_details(&self, reference_uniquename: &str) -> Option<&ReferenceDetails> {
        self.maps.references.get(reference_uniquename)
    }

    pub fn reload(&mut self) {
        let config = Config::read(&self.config_file_name);
        let (maps, gene_subsets) =
            load(&config, &self.search_maps_file_name,
                 &self.gene_subsets_file_name);
        self.maps = maps;
        self.gene_subsets = gene_subsets;
    }
}
<commit_msg>Make gene list searches case insensitive<commit_after>use std::process;
use std::fs::File;
use std::io::{Read, BufReader};

use serde_json;
use std::collections::HashMap;
use std::collections::HashSet;

use web::data::{APIMaps, IdGeneSubsetMap, APIGeneSummary, APIAlleleDetails,
                GeneDetails, TermDetails, GenotypeDetails, ReferenceDetails};
use web::config::Config;
use api::query::{SingleOrMultiAllele, QueryExpressionFilter};

use flate2::read::GzDecoder;

use types::GeneUniquename;

pub struct ServerData {
    config_file_name: String,
    maps: APIMaps,
    search_maps_file_name: String,
    gene_subsets: IdGeneSubsetMap,
    gene_subsets_file_name: String,
}

fn load(config: &Config, search_maps_file_name: &str, gene_subsets_file_name: &str)
        -> (APIMaps, IdGeneSubsetMap)
{
    let file = match File::open(search_maps_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", search_maps_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut decoder = GzDecoder::new(reader).unwrap();
    let mut decoded_json = String::new();
    decoder.read_to_string(&mut decoded_json).unwrap();

    let query_api_maps: APIMaps =
        match serde_json::from_str(&decoded_json) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", search_maps_file_name, err);
                process::exit(1);
            },
        };

    let file = match File::open(gene_subsets_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", gene_subsets_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut gene_subsets: IdGeneSubsetMap =
        match serde_json::from_reader(reader) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", gene_subsets_file_name, err);
                process::exit(1);
            },
        };

    let mut new_entries: IdGeneSubsetMap = HashMap::new();

    let prefixes_to_remove: Vec<String> =
        config.server.subsets.prefixes_to_remove
        .iter().map(|prefix| prefix.clone() + ":").collect();

    // strip prefixes and add to map
    for (subset_name, subset_details) in gene_subsets.iter() {
        for prefix in &prefixes_to_remove {
            if subset_name.starts_with(prefix) {
                let new_subset_name = &subset_name[prefix.len()..];
                new_entries.insert(String::from(new_subset_name), subset_details.clone());
            }
        }
    }

    gene_subsets.extend(new_entries);

    (query_api_maps, gene_subsets)
}

impl ServerData {
    pub fn new(config_file_name: &str, search_maps_file_name: &str,
               gene_subsets_file_name: &str)
               -> ServerData
    {
        let config = Config::read(config_file_name);

        let (maps, gene_subsets) =
            load(&config, search_maps_file_name, gene_subsets_file_name);
        ServerData {
            config_file_name: config_file_name.into(),
            search_maps_file_name: search_maps_file_name.into(),
            maps: maps,
            gene_subsets_file_name: gene_subsets_file_name.into(),
            gene_subsets: gene_subsets,
        }
    }

    pub fn gene_uniquename_of_id(&self, id: &str) -> Option<GeneUniquename> {
        if self.maps.gene_summaries.contains_key(id) {
            Some(id.to_owned())
        } else {
            if let Some(gene_uniquename) =
                self.maps.gene_name_gene_map.get(id) {
                    Some(gene_uniquename.clone())
                } else {
                    let lower_case_id = id.to_lowercase();
                    for gene_uniquename in self.maps.gene_summaries.keys() {
                        if gene_uniquename.to_lowercase() == lower_case_id {
                            return Some(gene_uniquename.clone());
                        }
                    }
                    None
                }
        }
    }

    pub fn get_gene_summary(&self, gene_uniquename: &str) -> Option<&APIGeneSummary> {
        self.maps.gene_summaries.get(gene_uniquename)
    }

    pub fn genes_of_termid(&self, term_id: &str) -> Vec<GeneUniquename> {
        match self.maps.termid_genes.get(term_id) {
            Some(gene_uniquenames) => {
                gene_uniquenames.iter().cloned().collect::<Vec<_>>()
            },
            None => vec![],
        }
    }

    pub fn genes_of_subset(&self, search_name: &str) -> Vec<GeneUniquename> {
        if search_name.starts_with('!') || search_name.ends_with('*') {
            let mut trimmed_search_name = search_name.to_owned();
            let invert_search = search_name.starts_with('!');
            let wildcard = search_name.ends_with('*');
            if invert_search {
                trimmed_search_name.remove(0);
            }
            if wildcard {
                trimmed_search_name.pop();
            }
            let mut genes = HashSet::new();
            for (subset_name, subset_details) in &self.gene_subsets {
                let name_matches =
                    wildcard && subset_name.starts_with(&trimmed_search_name) ||
                    trimmed_search_name.eq(subset_name);

                if !invert_search && name_matches || invert_search && !name_matches {
                    genes.extend(subset_details.elements.iter().cloned());
                }
            }
            genes.iter().cloned().collect::<Vec<_>>()
        } else {
            match self.gene_subsets.get(search_name) {
                Some(subset_details) => {
                    subset_details.elements.iter().cloned().collect::<Vec<_>>()
                },
                None => vec![],
            }
        }
    }

    pub fn genes_of_genotypes(&self, term_id: &str,
                              single_or_multi_allele: &SingleOrMultiAllele,
                              expression_filter: &Option<QueryExpressionFilter>)
                              -> Vec<GeneUniquename>
    {
        if let Some(annotations) = self.maps.termid_genotype_annotation.get(term_id) {
            let mut genes: HashSet<GeneUniquename> = HashSet::new();
            for annotation in annotations {

                let mut add_single = false;
                let mut add_multi = false;

                match *single_or_multi_allele {
                    SingleOrMultiAllele::Single => add_single = true,
                    SingleOrMultiAllele::Multi => add_multi = true,
                    SingleOrMultiAllele::Both => {
                        add_single = true;
                        add_multi = true;
                    },
                }

                let expression_matches =
                    |allele_details: &APIAlleleDetails| {
                        let expression = &allele_details.expression;
                        let allele_type = &allele_details.allele_type;
                        if let Some(ref expression_filter) = *expression_filter {
                            if *expression_filter == QueryExpressionFilter::Any {
                                return true;
                            }
                            if *expression_filter == QueryExpressionFilter::Null {
                                if allele_type == "deletion" {
                                    return true;
                                }
                                if let Some(ref expression) = *expression {
                                    expression == "Null"
                                } else {
                                    false
                                }
                            } else {
                                if *expression_filter == QueryExpressionFilter::WtOverexpressed {
                                    if let Some(ref expression) = *expression {
                                        expression == "Overexpression" &&
                                            allele_type == "wild_type"
                                    } else {
                                        false
                                    }
                                } else {
                                    false
                                }
                            }
                        } else {
                            true
                        }
                    };

                if annotation.is_multi && add_multi ||
                    !annotation.is_multi && add_single &&
                    expression_matches(&annotation.alleles[0]) {
                        for allele_details in &annotation.alleles {
                            genes.insert(allele_details.gene.clone());
                        }
                }
            }
            genes.into_iter().collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn filter_genes(&self, p: &Fn(&APIGeneSummary) -> bool)
                        -> Vec<GeneUniquename>
    {
        self.maps.gene_summaries.values()
            .filter(|ref summ| p(summ))
            .map(|ref summ| summ.uniquename.clone())
            .collect()
    }

    pub fn get_gene_details(&self, gene_uniquename: &str) -> Option<&GeneDetails> {
        self.maps.genes.get(gene_uniquename)
    }

    pub fn get_genotype_details(&self, genotype_uniquename: &str) -> Option<&GenotypeDetails> {
        self.maps.genotypes.get(genotype_uniquename)
    }

    pub fn get_term_details(&self, termid: &str) -> Option<&TermDetails> {
        self.maps.terms.get(termid)
    }

    pub fn get_reference_details(&self, reference_uniquename: &str) -> Option<&ReferenceDetails> {
        self.maps.references.get(reference_uniquename)
    }

    pub fn reload(&mut self) {
        let config = Config::read(&self.config_file_name);
        let (maps, gene_subsets) =
            load(&config, &self.search_maps_file_name,
                 &self.gene_subsets_file_name);
        self.maps = maps;
        self.gene_subsets = gene_subsets;
    }
}
<|endoftext|>