<commit_before>use std::io::Write;

use super::header::Header;
use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::ImageEncoder;

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 0 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        // Write out TGA header.
        let header = Header::from_pixel_info(color_type, width, height)?;
        header.write_to(&mut self.writer)?;

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

#[cfg(test)]
mod tests {
    use super::super::TgaDecoder;
    use super::TgaEncoder;
    use crate::color::ColorType;
    use crate::image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let encoder = TgaEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    // #[test]
    // fn test_image_too_large() {
    //     // TGA cannot encode images larger than 65,535×65,535
    //     // create a 65,536×1 8-bit black image buffer
    //     let size = usize::from(u16::MAX) + 1;
    //     let img = vec![0u8; size];
    //     // Try to encode an image that is too large
    //     let mut encoded = Vec::new();
    //     let encoder = TgaEncoder::new(&mut encoded);
    //     let result = encoder.encode(&img, size as u32, 1, ColorType::L8);
    //     match result {
    //         Err(ImageError::Parameter(err)) => {
    //             assert_eq!(err.kind(), ParameterErrorKind::DimensionMismatch)
    //         }
    //         other => assert!(
    //             false,
    //             "Encoding an image that is too large should return a DimensionError \
    //                             it returned {:?} instead",
    //             other
    //         ),
    //     }
    // }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_bgr() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgr8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0]);
    }

    #[test]
    fn round_trip_single_pixel_bgra() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgra8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0, 3]);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0, 1, 2, 3, 4, 5];
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }
}
<commit_msg>Re-enable tga encoding fail test<commit_after>use std::io::Write;

use super::header::Header;
use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::ImageEncoder;

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 0 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        // Write out TGA header.
        let header = Header::from_pixel_info(color_type, width, height)?;
        header.write_to(&mut self.writer)?;

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

#[cfg(test)]
mod tests {
    use super::TgaEncoder;
    use crate::tga::{TgaDecoder, header::EncoderError};

    use crate::ImageError;
    use crate::color::ColorType;
    use crate::image::ImageDecoder;

    use std::io::Cursor;
    use std::error::Error;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let encoder = TgaEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    #[test]
    fn test_image_too_large() {
        // TGA cannot encode images larger than 65,535×65,535
        // create a 65,536×1 8-bit black image buffer
        let size = usize::from(u16::MAX) + 1;
        let img = vec![0u8; size];
        // Try to encode an image that is too large
        let mut encoded = Vec::new();
        let encoder = TgaEncoder::new(&mut encoded);
        let result = encoder.encode(&img, size as u32, 1, ColorType::L8);
        match result {
            Err(ImageError::Encoding(err)) => {
                let _ = err.source().unwrap().downcast_ref::<EncoderError>().unwrap();
            }
            other => panic!(
                "Encoding an image that is too large should return a DimensionError \
                it returned {:?} instead",
                other
            ),
        }
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_bgr() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgr8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0]);
    }

    #[test]
    fn round_trip_single_pixel_bgra() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgra8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0, 3]);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0, 1, 2, 3, 4, 5];
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<InputSymbol, TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType, TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(tokens: AnnotatedStream<InputSymbol, TokenType>) -> Self {
        TreeStream { tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        self.tokens.read_input()
    }
}

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

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Whitespace
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }
}
<commit_msg>Start work on a way to read a ‘level’ of the tree as a stream<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<InputSymbol, TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType, TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(tokens: AnnotatedStream<InputSymbol, TokenType>) -> Self {
        TreeStream { tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        self.tokens.read_input()
    }

    ///
    /// Works out the depth of this tree
    ///
    pub fn depth(&self) -> usize {
        self.annotations.len()+1
    }

    ///
    /// Reads a the tokens on a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level_tokens<'a>(&'a self, depth: usize) -> Box<SymbolReader<Token<'a, TokenType, TokenType>>+'a> {
        unimplemented!();
    }

    ///
    /// Reads a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level<'a>(&'a self, depth: usize) -> Box<SymbolReader<TokenType>+'a> {
        if depth == self.annotations.len() {
            // Just the tokens; this level is flat
            self.tokens.read_output()
        } else {
            // Need to read 'through' the tree to deal with gaps to create the whole stream at this level
            unimplemented!()
        }
    }
}

///
/// Symbol reader that reads a 'level' of a tree
///
/// If the level has gaps in it, then those are filled in using the tokens from the level above
///
struct LevelReader<'a, InputSymbol: 'a, TokenType: 'static> {
    // The source treestream that is being read
    source: &'a TreeStream<InputSymbol, TokenType>,

    // The stack of levels being processed
    stack: Vec<(Box<SymbolReader<Token<'a, TokenType, TokenType>>+'a>, Option<Token<'a, TokenType, TokenType>>)>
}

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

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Whitespace
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenizer.depth() == 1);
        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }
}
<|endoftext|>


<commit_before>//! Provides an animated transformation that moves an object between a
//! set of specified keyframes.

use std::collections::BTreeSet;

use linalg::{keyframe, Keyframe, Transform};

/// An animated transform that blends between the keyframes in its transformation
/// list over time.
#[derive(Debug, Clone)]
pub struct AnimatedTransform {
    // TODO: Need to handle composing animated transforms. This basically
    // will be done by keeping a stack of these lists and working our way up/down
    // it when we want to compute the transform at some time.
    keyframes: BTreeSet<Keyframe>,
}

impl AnimatedTransform {
    /// Create a new empty animated transform
    pub fn new() -> AnimatedTransform {
        AnimatedTransform { keyframes: BTreeSet::new() }
    }
    /// Create an animated transformation blending between the passed keyframes
    pub fn with_keyframes(keyframes: Vec<Keyframe>) -> AnimatedTransform {
        AnimatedTransform { keyframes: keyframes.into_iter().collect() }
    }
    /// Insert a keyframe into the animation sequence
    pub fn insert(&mut self, keyframe: Keyframe) {
        self.keyframes.insert(keyframe);
    }
    /// Compute the transformation matrix for the animation at some time point.
    /// The transform is found by interpolating the two keyframes nearest to the
    /// time point being evaluated. **TODO** a binary search of some kind to find
    /// the two keyframes to blend would be much better.
    pub fn transform(&self, time: f32) -> Transform {
        if self.keyframes.is_empty() {
            Transform::identity()
        } else if time < self.keyframes.iter().next().unwrap().time {
            self.keyframes.iter().next().unwrap().transform()
        } else if time > self.keyframes.iter().last().unwrap().time {
            self.keyframes.iter().last().unwrap().transform()
        } else {
            let first = self.keyframes.iter().take_while(|k| k.time < time).last().unwrap();
            let second = self.keyframes.iter().skip_while(|k| k.time < time).next().unwrap();
            keyframe::interpolate(time, first, second)
        }
    }
}

<commit_msg>Proper handling of bounds of the time range<commit_after>//! Provides an animated transformation that moves an object between a
//! set of specified keyframes.

use std::collections::BTreeSet;

use linalg::{keyframe, Keyframe, Transform};

/// An animated transform that blends between the keyframes in its transformation
/// list over time.
#[derive(Debug, Clone)]
pub struct AnimatedTransform {
    // TODO: Need to handle composing animated transforms. This basically
    // will be done by keeping a stack of these lists and working our way up/down
    // it when we want to compute the transform at some time.
    keyframes: BTreeSet<Keyframe>,
}

impl AnimatedTransform {
    /// Create a new empty animated transform
    pub fn new() -> AnimatedTransform {
        AnimatedTransform { keyframes: BTreeSet::new() }
    }
    /// Create an animated transformation blending between the passed keyframes
    pub fn with_keyframes(keyframes: Vec<Keyframe>) -> AnimatedTransform {
        AnimatedTransform { keyframes: keyframes.into_iter().collect() }
    }
    /// Insert a keyframe into the animation sequence
    pub fn insert(&mut self, keyframe: Keyframe) {
        self.keyframes.insert(keyframe);
    }
    /// Compute the transformation matrix for the animation at some time point.
    /// The transform is found by interpolating the two keyframes nearest to the
    /// time point being evaluated. **TODO** a binary search of some kind to find
    /// the two keyframes to blend would be much better.
    pub fn transform(&self, time: f32) -> Transform {
        if self.keyframes.is_empty() {
            Transform::identity()
        } else {
            let first = self.keyframes.iter().take_while(|k| k.time < time).last();
            let second = self.keyframes.iter().skip_while(|k| k.time < time).next();
            if first.is_none() {
                self.keyframes.iter().next().unwrap().transform()
            } else if second.is_none() {
                self.keyframes.iter().last().unwrap().transform()
            } else {
                keyframe::interpolate(time, first.unwrap(), second.unwrap())
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate gtk;
#[macro_use] extern crate log;
extern crate thud_game;
extern crate thud_ui_common;
extern crate thud_ui_gtk;

use gtk::prelude::*;
use thud_ui_gtk::board_display;

use std::default::Default;

fn main() {
    if let Err(e) = gtk::init() {
        panic!("Failed to initialize GTK: {:?}", e)
    }

    let main_container = gtk::Grid::new();

    let main_board = board_display::view::Interactive::new(
        board_display::model::Interactive::new(thud_ui_common::ThudState::new(Default::default()),
                                               board_display::model::InteractiveRoles::Both),
        board_display::view::Properties::new());
    main_container.attach(main_board.widget(), 0, 0, 1, 1);

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Thud");
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        gtk::Inhibit(false)
    });
    window.add(&main_container);
    window.show_all();

    gtk::main();
}

//     let mut store = gtk_ui::search_table::Store::new(&columns);
//     let tree = gtk::TreeView::new_with_model(&store.model()).unwrap();
//     for (i, c) in columns.iter().enumerate() {
//         tree.append_column(&c.new_view_column(i as i32));
//     }
//     let graph_view = gtk::ScrolledWindow::new(None, None).unwrap();
//     graph_view.add(&tree);

//     let move_display = {
//         let mut properties = gtk_ui::board_display::view::Properties::new();
//         properties.margin_left = 0.0;
//         properties.margin_right = 0.0;
//         properties.margin_top = 0.0;
//         properties.margin_bottom = 0.0;
//         properties.border_width = 2.0;
//         properties.cell_dimension = 10.0;
//         properties.token_width = 5.0;
//         properties.token_height = 5.0;
//         gtk_ui::board_display::Passive::new_with_properties(properties).unwrap();
//     };

//     match display.canvas.try_lock() {
//         Result::Ok(guard) => main_container.attach(guard.deref(), 0, 0, 7, 7),
//         _ => panic!("Unable to intialize display"),
//     }
//     main_container.attach(&button_panel, 7, 0, 1, 1);
//     main_container.attach(&graph_view, 7, 1, 3, 1);
//     match move_display.canvas.try_lock() {
//         Result::Ok(guard) => main_container.attach(guard.deref(), 7, 4, 3, 1),
//         _ => panic!("Unable to initialize display"),
//     }

//     let window = gtk::Window::new(gtk::WindowType::Toplevel).unwrap();
//     window.set_window_position(gtk::WindowPosition::Center);
//     window.set_title("Thud");
//     window.connect_delete_event(|_, _| {
//         gtk::main_quit();
//         Inhibit(false)
//     });
//     window.add(&main_container);

//     window.show_all();
//     gtk::main();
// }
<commit_msg>Use new method for accessing drawing area widget.<commit_after>extern crate gtk;
#[macro_use] extern crate log;
extern crate thud_game;
extern crate thud_ui_common;
extern crate thud_ui_gtk;

use gtk::prelude::*;
use thud_ui_gtk::board_display;

use std::default::Default;

fn main() {
    if let Err(e) = gtk::init() {
        panic!("Failed to initialize GTK: {:?}", e)
    }

    let main_container = gtk::Grid::new();

    let main_board = board_display::view::Interactive::new(
        board_display::model::Interactive::new(thud_ui_common::ThudState::new(Default::default()),
                                               board_display::model::InteractiveRoles::Both),
        board_display::view::Properties::new());
    main_board.with_widget(|w| main_container.attach(w, 0, 0, 1, 1));

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Thud");
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        gtk::Inhibit(false)
    });
    window.add(&main_container);
    window.show_all();

    gtk::main();
}

//     let mut store = gtk_ui::search_table::Store::new(&columns);
//     let tree = gtk::TreeView::new_with_model(&store.model()).unwrap();
//     for (i, c) in columns.iter().enumerate() {
//         tree.append_column(&c.new_view_column(i as i32));
//     }
//     let graph_view = gtk::ScrolledWindow::new(None, None).unwrap();
//     graph_view.add(&tree);

//     let move_display = {
//         let mut properties = gtk_ui::board_display::view::Properties::new();
//         properties.margin_left = 0.0;
//         properties.margin_right = 0.0;
//         properties.margin_top = 0.0;
//         properties.margin_bottom = 0.0;
//         properties.border_width = 2.0;
//         properties.cell_dimension = 10.0;
//         properties.token_width = 5.0;
//         properties.token_height = 5.0;
//         gtk_ui::board_display::Passive::new_with_properties(properties).unwrap();
//     };

//     match display.canvas.try_lock() {
//         Result::Ok(guard) => main_container.attach(guard.deref(), 0, 0, 7, 7),
//         _ => panic!("Unable to intialize display"),
//     }
//     main_container.attach(&button_panel, 7, 0, 1, 1);
//     main_container.attach(&graph_view, 7, 1, 3, 1);
//     match move_display.canvas.try_lock() {
//         Result::Ok(guard) => main_container.attach(guard.deref(), 7, 4, 3, 1),
//         _ => panic!("Unable to initialize display"),
//     }

//     let window = gtk::Window::new(gtk::WindowType::Toplevel).unwrap();
//     window.set_window_position(gtk::WindowPosition::Center);
//     window.set_title("Thud");
//     window.connect_delete_event(|_, _| {
//         gtk::main_quit();
//         Inhibit(false)
//     });
//     window.add(&main_container);

//     window.show_all();
//     gtk::main();
// }
<|endoftext|>


<commit_before><commit_msg>a lot of bugs, but at least finished<commit_after><|endoftext|>


<commit_before>use nickel::{
    Params,
    BodyError,
};
use std;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Validators;

#[derive(Debug, Clone)]
pub enum FormValidationErrors {
    FieldNotExist,
    ParseError
}

pub trait FormValidator {
    fn validate(form_data: &Params)
            -> Result<Self, FormValidationErrors>
            where Self: std::marker::Sized {
        let _validators = Self::validators();
        create_validator(&form_data);
        Ok(Self::fill_form(&form_data)?)
    }
    fn validators() -> Validators;
    fn fill_form(form_data: &Params)
            -> Result<Self, FormValidationErrors>
            where Self: std::marker::Sized;
}

fn create_validator(form_data: &Params) -> Result<(), FormValidationErrors> {
    let mut validation_errors: HashMap<&str, Vec<FormValidationErrors>> = HashMap::new();
    let field_name = "done.a1";

    let get_data: Option<String> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::ParseError) ));
    println!("DATA: {:#?}", get_data);

    let field_name = "done.a";
    let _: Option<i32> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::ParseError) ));
    println!("DATA: {:#?}", get_data);

    let get_data: Option<String> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationErrors::ParseError) ));
    println!("DATA: {:#?}", get_data);
    println!("Err: {:#?}", validation_errors.len());
    println!("Errors: {:#?}", validation_errors);

    if validation_errors.is_empty() { Ok(()) } else { Err(validation_errors) }
}

fn add_error<'a, T>(validation_errors: &mut HashMap<&'a str, Vec<FormValidationErrors>>, field: &'a str, error: FormValidationErrors) -> Option<T> {
    if validation_errors.contains_key(&field) {
        let mut err = validation_errors.get_mut(&field).unwrap();
        err.push(error);
    } else {
        validation_errors.insert(&field, vec!(error));
    }
    None
}<commit_msg>Form validator - modified FromVAlidationsErrors type and fixed Result type<commit_after>use nickel::{
    Params,
    BodyError,
};
use std;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Validators;

pub type FormValidationErrors<'a> = HashMap<&'a str, Vec<FormValidationError>>;

#[derive(Debug, Clone)]
pub enum FormValidationError {
    FieldNotExist,
    ParseError
}

pub trait FormValidator {
    fn validate(form_data: &Params)
            -> Result<Self, FormValidationErrors>
            where Self: std::marker::Sized {
        let _validators = Self::validators();
        create_validator(&form_data);
        Ok(Self::fill_form(&form_data)?)
    }
    fn validators() -> Validators;
    fn fill_form(form_data: &Params)
            -> Result<Self, FormValidationErrors>
            where Self: std::marker::Sized;
}

fn create_validator(form_data: &Params) -> Result<(), FormValidationErrors> {
    let mut validation_errors: FormValidationErrors = HashMap::new();
    let field_name = "done.a1";

    let get_data: Option<String> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::ParseError) ));
    println!("DATA: {:#?}", get_data);

    let field_name = "done.a";
    let _: Option<i32> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::ParseError) ));
    println!("DATA: {:#?}", get_data);

    let get_data: Option<String> = form_data.get(field_name)
        .or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::FieldNotExist) )
        .and_then(|o| o.parse().ok().or_else(|| add_error(&mut validation_errors, field_name, FormValidationError::ParseError) ));
    println!("DATA: {:#?}", get_data);
    println!("Err: {:#?}", validation_errors.len());
    println!("Errors: {:#?}", validation_errors);

    if validation_errors.is_empty() { Ok(()) } else { Err(validation_errors) }
}

fn add_error<'a, T>(validation_errors: &mut FormValidationErrors<'a>, field: &'a str, error: FormValidationError) -> Option<T> {
    if validation_errors.contains_key(&field) {
        let mut err = validation_errors.get_mut(&field).unwrap();
        err.push(error);
    } else {
        validation_errors.insert(&field, vec!(error));
    }
    None
}
<|endoftext|>


<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 https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::XRSpaceBinding;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;

#[dom_struct]
pub struct XRSpace {
    eventtarget: EventTarget,
}

impl XRSpace {
    pub fn new_inherited() -> XRSpace {
        XRSpace {
            eventtarget: EventTarget::new_inherited(),
        }
    }

    pub fn new(global: &GlobalScope) -> DomRoot<XRSpace> {
        reflect_dom_object(
            Box::new(XRSpace::new_inherited()),
            global,
            XRSpaceBinding::Wrap,
        )
    }
}
<commit_msg>Remove Cell in XRSpace<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 https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::XRSpaceBinding;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;

#[dom_struct]
pub struct XRSpace {
    eventtarget: EventTarget,
}

impl XRSpace {
    pub fn new_inherited() -> XRSpace {
        XRSpace {
            eventtarget: EventTarget::new_inherited(),
        }
    }

    #[allow(unused)]
    pub fn new(global: &GlobalScope) -> DomRoot<XRSpace> {
        reflect_dom_object(
            Box::new(XRSpace::new_inherited()),
            global,
            XRSpaceBinding::Wrap,
        )
    }
}
<|endoftext|>


<commit_before>
extern crate ndarray;

use ndarray::prelude::*;

#[test]
fn broadcast_1()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let a = RcArray::linspace(0., 1., a_dim.size()).reshape(a_dim);
    let b = RcArray::linspace(0., 1., b_dim.size()).reshape(b_dim);
    assert!(b.broadcast(a.dim()).is_some());

    let c_dim = (2, 1);
    let c = RcArray::linspace(0., 1., c_dim.size()).reshape(c_dim);
    assert!(c.broadcast(1).is_none());
    assert!(c.broadcast(()).is_none());
    assert!(c.broadcast((2, 1)).is_some());
    assert!(c.broadcast((2, 2)).is_some());
    assert!(c.broadcast((32, 2, 1)).is_some());
    assert!(c.broadcast((32, 1, 2)).is_none());

    /* () can be broadcast to anything */
    let z = RcArray::<f32,_>::zeros(());
    assert!(z.broadcast(()).is_some());
    assert!(z.broadcast(1).is_some());
    assert!(z.broadcast(3).is_some());
    assert!(z.broadcast((7,2,9)).is_some());
}

#[test]
fn test_add()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let mut a = RcArray::linspace(0.0, 1., a_dim.size()).reshape(a_dim);
    let b = RcArray::linspace(0.0, 1., b_dim.size()).reshape(b_dim);
    a += &b;
    let t = RcArray::from_elem((), 1.0f32);
    a += &t;
}

#[test] #[should_panic]
fn test_add_incompat()
{
    let a_dim = (2, 4, 2, 2);
    let mut a = RcArray::linspace(0.0, 1., a_dim.size()).reshape(a_dim);
    let incompat = RcArray::from_elem(3, 1.0f32);
    a += &incompat;
}

#[test]
fn test_broadcast() {
    let (_, n, k) = (16, 16, 16);
    let x1 = 1.;
    // b0 broadcast 1 -> n, k
    let x = Array::from_vec(vec![x1]);
    let b0 = x.broadcast((n, k)).unwrap();
    // b1 broadcast n -> n, k
    let b1 = Array::from_elem(n, x1);
    let b1 = b1.broadcast((n, k)).unwrap();
    // b2 is n, k
    let b2 = Array::from_elem((n, k), x1);

    println!("b0=\n{:?}", b0);
    println!("b1=\n{:?}", b1);
    println!("b2=\n{:?}", b2);
    assert_eq!(b0, b1);
    assert_eq!(b0, b2);
}
<commit_msg>Add another test for 1 -> n broadcast (1d)<commit_after>
extern crate ndarray;

use ndarray::prelude::*;

#[test]
fn broadcast_1()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let a = RcArray::linspace(0., 1., a_dim.size()).reshape(a_dim);
    let b = RcArray::linspace(0., 1., b_dim.size()).reshape(b_dim);
    assert!(b.broadcast(a.dim()).is_some());

    let c_dim = (2, 1);
    let c = RcArray::linspace(0., 1., c_dim.size()).reshape(c_dim);
    assert!(c.broadcast(1).is_none());
    assert!(c.broadcast(()).is_none());
    assert!(c.broadcast((2, 1)).is_some());
    assert!(c.broadcast((2, 2)).is_some());
    assert!(c.broadcast((32, 2, 1)).is_some());
    assert!(c.broadcast((32, 1, 2)).is_none());

    /* () can be broadcast to anything */
    let z = RcArray::<f32,_>::zeros(());
    assert!(z.broadcast(()).is_some());
    assert!(z.broadcast(1).is_some());
    assert!(z.broadcast(3).is_some());
    assert!(z.broadcast((7,2,9)).is_some());
}

#[test]
fn test_add()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let mut a = RcArray::linspace(0.0, 1., a_dim.size()).reshape(a_dim);
    let b = RcArray::linspace(0.0, 1., b_dim.size()).reshape(b_dim);
    a += &b;
    let t = RcArray::from_elem((), 1.0f32);
    a += &t;
}

#[test] #[should_panic]
fn test_add_incompat()
{
    let a_dim = (2, 4, 2, 2);
    let mut a = RcArray::linspace(0.0, 1., a_dim.size()).reshape(a_dim);
    let incompat = RcArray::from_elem(3, 1.0f32);
    a += &incompat;
}

#[test]
fn test_broadcast() {
    let (_, n, k) = (16, 16, 16);
    let x1 = 1.;
    // b0 broadcast 1 -> n, k
    let x = Array::from_vec(vec![x1]);
    let b0 = x.broadcast((n, k)).unwrap();
    // b1 broadcast n -> n, k
    let b1 = Array::from_elem(n, x1);
    let b1 = b1.broadcast((n, k)).unwrap();
    // b2 is n, k
    let b2 = Array::from_elem((n, k), x1);

    println!("b0=\n{:?}", b0);
    println!("b1=\n{:?}", b1);
    println!("b2=\n{:?}", b2);
    assert_eq!(b0, b1);
    assert_eq!(b0, b2);
}

#[test]
fn test_broadcast_1d() {
    let n = 16;
    let x1 = 1.;
    // b0 broadcast 1 -> n
    let x = Array::from_vec(vec![x1]);
    let b0 = x.broadcast(n).unwrap();
    let b2 = Array::from_elem(n, x1);

    println!("b0=\n{:?}", b0);
    println!("b2=\n{:?}", b2);
    assert_eq!(b0, b2);
}
<|endoftext|>


<commit_before>#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm",
                not(any(target_env = "gnu", target_env = "musl")),
                target_os = "linux",
                test), no_std)]

include!(concat!(env!("OUT_DIR"), "/floattidf.rs"));
<commit_msg>Ignore failing test on mips<commit_after>#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm",
                not(any(target_env = "gnu", target_env = "musl")),
                target_os = "linux",
                test), no_std)]
#![cfg(not(target_arch = "mips"))] // FIXME(#168)

include!(concat!(env!("OUT_DIR"), "/floattidf.rs"));
<|endoftext|>


<commit_before>
use ::std::mem;

pub struct Sprite {
	pub pix: [u8; 4],
}

/// All the valid tetrominoes.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum Piece { O, I, S, Z, L, J, T }

impl ::rand::Rand for Piece {
	fn rand<R: ::rand::Rng>(rng: &mut R) -> Piece {
		let entropy = rng.next_u32();
		unsafe { mem::transmute((entropy % 7) as u8) }
	}
}
<commit_msg>Wrote Piece documentation.<commit_after>
use ::std::mem;

/// Piece sprite.
///
/// The sprite pixels are 4x4 with only the low nibble used.
pub struct Sprite {
	pub pix: [u8; 4],
}

/// All the valid tetrominoes.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum Piece {
	/// The `O` tetromino.
	///
	/// ```text
	/// □□
	/// □□
	/// ```
	O,
	/// The `I` tetromino.
	///
	/// ```text
	/// □□□□
	/// ```
	I,
	/// The `S` tetromino.
	///
	/// ```text
	///  □□
	/// □□
	/// ```
	S,
	/// The `Z` tetromino.
	///
	/// ```text
	/// □□
	///  □□
	/// ```
	Z,
	/// The `L` tetromino.
	///
	/// ```text
	/// □
	/// □
	/// □□
	/// ```
	L,
	/// The `J` tetromino.
	///
	/// ```text
	///  □
	///  □
	/// □□
	/// ```
	J,
	/// The `T` tetromino.
	///
	/// ```text
	/// □□□
	///  □
	/// ```
	T,
}

impl ::rand::Rand for Piece {
	fn rand<R: ::rand::Rng>(rng: &mut R) -> Piece {
		let entropy = rng.next_u32();
		unsafe { mem::transmute((entropy % 7) as u8) }
	}
}
<|endoftext|>


<commit_before><commit_msg>Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de><commit_after><|endoftext|>


<commit_before>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2012-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

use std::cmp::min;
use std::env;
use std::fs::File;
use std::io::{self, BufWriter};
use std::io::prelude::*;

const LINE_LENGTH: usize = 60;
const IM: u32 = 139968;

struct MyRandom {
    last: u32
}
impl MyRandom {
    fn new() -> MyRandom { MyRandom { last: 42 } }
    fn normalize(p: f32) -> u32 {(p * IM as f32).floor() as u32}
    fn gen(&mut self) -> u32 {
        self.last = (self.last * 3877 + 29573) % IM;
        self.last
    }
}

struct AAGen<'a> {
    rng: &'a mut MyRandom,
    data: Vec<(u32, u8)>
}
impl<'a> AAGen<'a> {
    fn new<'b>(rng: &'b mut MyRandom, aa: &[(char, f32)]) -> AAGen<'b> {
        let mut cum = 0.;
        let data = aa.iter()
            .map(|&(ch, p)| { cum += p; (MyRandom::normalize(cum), ch as u8) })
            .collect();
        AAGen { rng: rng, data: data }
    }
}
impl<'a> Iterator for AAGen<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        let r = self.rng.gen();
        self.data.iter()
            .skip_while(|pc| pc.0 < r)
            .map(|&(_, c)| c)
            .next()
    }
}

fn make_fasta<W: Write, I: Iterator<Item=u8>>(
    wr: &mut W, header: &str, mut it: I, mut n: usize)
    -> io::Result<()>
{
    try!(wr.write(header.as_bytes()));
    let mut line = [0; LINE_LENGTH + 1];
    while n > 0 {
        let nb = min(LINE_LENGTH, n);
        for i in 0..nb {
            line[i] = it.next().unwrap();
        }
        n -= nb;
        line[nb] = '\n' as u8;
        try!(wr.write(&line[..nb+1]));
    }
    Ok(())
}

fn run<W: Write>(writer: &mut W) -> io::Result<()> {
    let mut args = env::args();
    let n = if env::var_os("RUST_BENCH").is_some() {
        25000000
    } else if args.len() <= 1 {
        1000
    } else {
        args.nth(1).unwrap().parse().unwrap()
    };

    let rng = &mut MyRandom::new();
    let alu =
        "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\
        GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\
        CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\
        ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\
        GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\
        AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\
        AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
    let iub = &[('a', 0.27), ('c', 0.12), ('g', 0.12),
                ('t', 0.27), ('B', 0.02), ('D', 0.02),
                ('H', 0.02), ('K', 0.02), ('M', 0.02),
                ('N', 0.02), ('R', 0.02), ('S', 0.02),
                ('V', 0.02), ('W', 0.02), ('Y', 0.02)];
    let homosapiens = &[('a', 0.3029549426680),
                        ('c', 0.1979883004921),
                        ('g', 0.1975473066391),
                        ('t', 0.3015094502008)];

    try!(make_fasta(writer, ">ONE Homo sapiens alu\n",
                    alu.as_bytes().iter().cycle().cloned(), n * 2));
    try!(make_fasta(writer, ">TWO IUB ambiguity codes\n",
                    AAGen::new(rng, iub), n * 3));
    try!(make_fasta(writer, ">THREE Homo sapiens frequency\n",
                    AAGen::new(rng, homosapiens), n * 5));

    writer.flush()
}

fn main() {
    let res = if env::var_os("RUST_BENCH").is_some() {
        let mut file = BufWriter::new(File::create("./shootout-fasta.data").unwrap());
        run(&mut file)
    } else {
        run(&mut io::stdout())
    };
    res.unwrap()
}
<commit_msg>change fasta benchmark to Veedrac's implementation<commit_after>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2012-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

use std::cmp::min;
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
use std::thread;

const LINE_LEN: usize = 60;

const BLOCK_LINES: usize = 512;
const BLOCK_THOROUGHPUT: usize = LINE_LEN * BLOCK_LINES;
const BLOCK_LEN: usize = BLOCK_THOROUGHPUT + BLOCK_LINES;

const STDIN_BUF: usize = (LINE_LEN + 1) * 1024;

const ALU: &'static [u8] =
    b"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\
      GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\
      CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\
      ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\
      GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\
      AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\
      AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";

const IUB: &'static [(u8, f32)] =
    &[(b'a', 0.27), (b'c', 0.12), (b'g', 0.12),
      (b't', 0.27), (b'B', 0.02), (b'D', 0.02),
      (b'H', 0.02), (b'K', 0.02), (b'M', 0.02),
      (b'N', 0.02), (b'R', 0.02), (b'S', 0.02),
      (b'V', 0.02), (b'W', 0.02), (b'Y', 0.02)];

const HOMOSAPIENS: &'static [(u8, f32)] =
    &[(b'a', 0.3029549426680),
      (b'c', 0.1979883004921),
      (b'g', 0.1975473066391),
      (b't', 0.3015094502008)];

// We need a specific Rng,
// so implement this manually
const MODULUS: u32 = 139968;
const MULTIPLIER: u32 = 3877;
const ADDITIVE: u32 = 29573;

// Why doesn't rust already have this?
// Algorithm directly taken from Wikipedia
fn powmod(mut base: u64, mut exponent: u32, modulus: u64) -> u64 {
    let mut ret = 1;
    base %= modulus;

    while exponent > 0 {
        if exponent & 1 == 1 {
           ret *= base;
           ret %= modulus;
        }
        exponent >>= 1;
        base *= base;
        base %= modulus;
    }

    ret
}

// Just a typical LCRNG
pub struct Rng {
    last: u32
}

impl Rng {
    pub fn new() -> Rng {
        Rng { last: 42 }
    }

    pub fn max_value() -> u32 {
        MODULUS - 1
    }

    pub fn normalize(p: f32) -> u32 {
        (p * MODULUS as f32).floor() as u32
    }

    pub fn gen(&mut self) -> u32 {
        self.last = (self.last * MULTIPLIER + ADDITIVE) % MODULUS;
        self.last
    }

    // This allows us to fast-forward the RNG,
    // allowing us to run it in parallel.
    pub fn future(&self, n: u32) -> Rng {
        let a = MULTIPLIER as u64;
        let b = ADDITIVE as u64;
        let m = MODULUS as u64;

        //                          (a^n - 1) mod (a-1) m
        // x_k = ((a^n x_0 mod m) + --------------------- b) mod m
        //                                   a - 1
        //
        // Since (a - 1) divides (a^n - 1) mod (a-1) m,
        // the subtraction does not overflow and thus can be non-modular.
        //
        let new_seed =
            (powmod(a, n, m) * self.last as u64) % m +
            (powmod(a, n, (a-1) * m) - 1) / (a-1) * b;

        Rng { last: (new_seed % m) as u32 }
    }
}

// This will end up keeping track of threads, like
// in the other multithreaded Rust version, in
// order to keep writes in order.
//
// This is stolen from another multithreaded Rust
// implementation, although that implementation
// was not able to parallelize the RNG itself.
struct BlockSubmitter<W: io::Write> {
    writer: W,
    pub waiting_on: usize,
}

impl<W: io::Write> BlockSubmitter<W> {
    fn submit(&mut self, data: &[u8], block_num: usize) -> Option<io::Result<()>> {
        if block_num == self.waiting_on {
            self.waiting_on += 1;
            Some(self.submit_async(data))
        }
        else {
            None
        }
    }

    fn submit_async(&mut self, data: &[u8]) -> io::Result<()> {
        self.writer.write_all(data)
    }
}

// For repeating strings as output
fn fasta_static<W: io::Write>(
    writer: &mut W,
    header: &[u8],
    data: &[u8],
    mut n: usize
) -> io::Result<()>
{
    // The aim here is to print a short(ish) string cyclically
    // with line breaks as appropriate.
    //
    // The secret technique is to repeat the string such that
    // any wanted line is a single offset in the string.
    //
    // This technique is stolen from the Haskell version.

    try!(writer.write_all(header));

    // Maximum offset is data.len(),
    // Maximum read len is LINE_LEN
    let stream = data.iter().cloned().cycle();
    let mut extended: Vec<u8> = stream.take(data.len() + LINE_LEN + 1).collect();

    let mut offset = 0;
    while n > 0 {
        let write_len = min(LINE_LEN, n);
        let end = offset + write_len;
        n -= write_len;

        let tmp = extended[end];
        extended[end] = b'\n';
        try!(writer.write_all(&extended[offset..end + 1]));
        extended[end] = tmp;

        offset = end;
        offset %= data.len();
    }

    Ok(())
}

// For RNG streams as output
fn fasta<W: io::Write + Send + 'static>(
    submitter: &Arc<Mutex<BlockSubmitter<W>>>,
    header: &[u8],
    table: &[(u8, f32)],
    rng: &mut Rng,
    n: usize
) -> io::Result<()>
{
    // There's another secret technique in use here:
    // we generate a lookup table to cache search of the
    // aa buffer.
    //
    // The secret technique used is stolen from Haskell's
    // implementation, and is the main secret to the Haskell
    // implementation's  speed.
    fn gen_lookup_table(aa: &[(u8, f32)]) -> Vec<u8> {
        let mut table = Vec::with_capacity(Rng::max_value() as usize + 1);

        let mut cumulative_prob = 0.0;
        let mut cumulative_norm = 0;

        for &(byte, prob) in aa {
            let last_norm = cumulative_norm;
            cumulative_prob += prob;
            cumulative_norm = min(Rng::max_value(), Rng::normalize(cumulative_prob)) + 1;

            table.extend((0..cumulative_norm - last_norm).map(|_| byte));
        }

        table
    }

    {
        try!(submitter.lock().unwrap().submit_async(header));
    }

    let lookup_table = Arc::new(gen_lookup_table(table));

    let thread_count = 4; // avoid external dependency
    let mut threads = Vec::new();
    for block_num in (0..thread_count) {
        let offset = BLOCK_THOROUGHPUT * block_num;

        let local_submitter = submitter.clone();
        let local_lookup_table = lookup_table.clone();
        let local_rng = rng.future(offset as u32);

        threads.push(thread::spawn(move || {
            gen_block(
                local_submitter,
                local_lookup_table,
                local_rng,
                n.saturating_sub(offset),
                block_num,
                thread_count
            )
        }));
    }

    for thread in threads {
        try!(thread.join().unwrap());
    }

    *rng = rng.future(n as u32);

    Ok(())
}

// A very optimized writer.
// I have a feeling a simpler version wouldn't slow
// things down too much, though, since the RNG
// is the really heavy hitter.
fn gen_block<W: io::Write>(
    submitter: Arc<Mutex<BlockSubmitter<W>>>,
    lookup_table: Arc<Vec<u8>>,
    mut rng: Rng,
    mut length: usize,
    mut block_num: usize,
    block_stride: usize,
) -> io::Result<()>
{
    // Include newlines in block
    length += length / LINE_LEN;
    let block: &mut [u8] = &mut [b'\n'; BLOCK_LEN];

    while length > 0 {
        {
            let gen_into = &mut block[..min(length, BLOCK_LEN)];

            // Write random numbers, skipping newlines
            for (i, byte) in gen_into.iter_mut().enumerate() {
                if (i + 1) % (LINE_LEN + 1) != 0 {
                    *byte = lookup_table[rng.gen() as usize];
                }
            }
        }

        let write_out = {
            if length >= BLOCK_LEN               { &mut *block }
            else if length % (LINE_LEN + 1) == 0 { &mut block[..length] }
            else                                 { &mut block[..length + 1] }
        };

        *write_out.last_mut().unwrap() = b'\n';
        loop {
            match submitter.lock().unwrap().submit(write_out, block_num) {
                Some(result) => { try!(result); break; }
                None => std::thread::yield_now()
            }
        }
        block_num += block_stride;
        rng = rng.future((BLOCK_THOROUGHPUT * (block_stride - 1)) as u32);
        length = length.saturating_sub(BLOCK_LEN * (block_stride - 1));

        length = length.saturating_sub(BLOCK_LEN);
    }

    Ok(())
}

fn run<W: io::Write + Send + 'static>(writer: W) -> io::Result<()> {
    let n = std::env::args_os().nth(1)
        .and_then(|s| s.into_string().ok())
        .and_then(|n| n.parse().ok())
        .unwrap_or(1000);

    let rng = &mut Rng::new();

    // Use automatic buffering for the static version...
    let mut writer = io::BufWriter::with_capacity(STDIN_BUF, writer);
    try!(fasta_static(&mut writer, b">ONE Homo sapiens alu\n", ALU, n * 2));

    // ...but the dynamic version does its own buffering already
    let writer = try!(writer.into_inner());
    let submitter = Arc::new(Mutex::new(BlockSubmitter { writer: writer, waiting_on: 0 }));

    { submitter.lock().unwrap().waiting_on = 0; }
    try!(fasta(&submitter, b">TWO IUB ambiguity codes\n", &IUB, rng, n * 3));
    { submitter.lock().unwrap().waiting_on = 0; }
    try!(fasta(&submitter, b">THREE Homo sapiens frequency\n", &HOMOSAPIENS, rng, n * 5));

    Ok(())
}

fn main() {
    run(io::stdout()).unwrap()
}
<|endoftext|>


<commit_before>use config;

use std::collections::BTreeMap;
use rustc_serialize::json::Json;
use regex::Regex;
use git2;

use chrono::naive::datetime::NaiveDateTime;
use chrono::offset::fixed::FixedOffset;
use chrono::datetime::DateTime;

pub fn linkify(s: &str) -> String {
    let re = Regex::new(r"\b(?P<bugno>[1-9][0-9]{4,9})\b").unwrap();
    re.replace_all(s, "$bugno")
}

pub fn commit_header(commit: &git2::Commit) -> Result<(String, String), &'static str> {
    fn entity_replace(s: &str) -> String {
        s.replace("&", "&").replace("<", "<")
    }

    let msg = try!(commit.message().ok_or("Invalid message"));
    let mut iter = msg.split('\n');
    let header = iter.next().unwrap();
    let remainder = iter.collect::<Vec<_>>().join("\n");
    let header = linkify(&entity_replace(header));
    Ok((header, entity_replace(&remainder)))
}

pub fn get_commit_info(cfg: &config::Config, tree_name: &str, rev: &str) -> Result<String, &'static str> {
    let tree_config = try!(cfg.trees.get(tree_name).ok_or("Invalid tree"));
    let git = try!(config::get_git(tree_config));
    let commit_obj = try!(git.repo.revparse_single(rev).map_err(|_| "Bad revision"));
    let commit = try!(commit_obj.as_commit().ok_or("Bad revision"));
    let (msg, _) = try!(commit_header(&commit));

    let naive_t = NaiveDateTime::from_timestamp(commit.time().seconds(), 0);
    let tz = FixedOffset::east(commit.time().offset_minutes() * 60);
    let t : DateTime<FixedOffset> = DateTime::from_utc(naive_t, tz);
    let t = t.to_rfc2822();

    let sig = commit.author();

    let msg = format!("{}\n
{} <{}>, {}", msg, sig.name().unwrap(), sig.email().unwrap(), t);

    let mut obj = BTreeMap::new();

    obj.insert("header".to_owned(), Json::String(msg));

    let parents = commit.parent_ids().collect::<Vec<_>>();
    if parents.len() == 1 {
        obj.insert("parent".to_owned(), Json::String(parents[0].to_string()));
    }

    obj.insert("date".to_owned(), Json::String(t));

    let json = Json::Object(obj);

    Ok(json.to_string())
}
<commit_msg>blame: Linkify servo PR in commit message headers.<commit_after>use config;

use std::collections::BTreeMap;
use rustc_serialize::json::Json;
use regex::Regex;
use git2;

use chrono::naive::datetime::NaiveDateTime;
use chrono::offset::fixed::FixedOffset;
use chrono::datetime::DateTime;

fn linkify_commit_header(s: &str) -> String {
    lazy_static! {
        static ref BUG_NUMBER_REGEX: Regex = {
            Regex::new(r"\b(?P<bugno>[1-9][0-9]{4,9})\b").unwrap()
        };
        static ref SERVO_PR_REGEX: Regex = {
            Regex::new(r"#(?P<prno>[1-9][0-9]*)\b").unwrap()
        };
    }
    if s.starts_with("servo: ") {
        SERVO_PR_REGEX.replace_all(s, "#$prno")
    } else {
        BUG_NUMBER_REGEX.replace_all(s, "$bugno")
    }
}

#[test]
fn test_linkify_servo_pr() {
    let linkified =
        linkify_commit_header("servo: Merge #1234 - stylo: Report a specific error for invalid CSS color values (from jdm:valueerr); r=heycam");
    assert!(linkified.contains("github.com"), "{:?}", linkified);
}

pub fn commit_header(commit: &git2::Commit) -> Result<(String, String), &'static str> {
    fn entity_replace(s: &str) -> String {
        s.replace("&", "&").replace("<", "<")
    }

    let msg = try!(commit.message().ok_or("Invalid message"));
    let mut iter = msg.split('\n');
    let header = iter.next().unwrap();
    let remainder = iter.collect::<Vec<_>>().join("\n");
    let header = linkify_commit_header(&entity_replace(header));
    Ok((header, entity_replace(&remainder)))
}

pub fn get_commit_info(cfg: &config::Config, tree_name: &str, rev: &str) -> Result<String, &'static str> {
    let tree_config = try!(cfg.trees.get(tree_name).ok_or("Invalid tree"));
    let git = try!(config::get_git(tree_config));
    let commit_obj = try!(git.repo.revparse_single(rev).map_err(|_| "Bad revision"));
    let commit = try!(commit_obj.as_commit().ok_or("Bad revision"));
    let (msg, _) = try!(commit_header(&commit));

    let naive_t = NaiveDateTime::from_timestamp(commit.time().seconds(), 0);
    let tz = FixedOffset::east(commit.time().offset_minutes() * 60);
    let t : DateTime<FixedOffset> = DateTime::from_utc(naive_t, tz);
    let t = t.to_rfc2822();

    let sig = commit.author();

    let msg = format!("{}\n
{} <{}>, {}", msg, sig.name().unwrap(), sig.email().unwrap(), t);

    let mut obj = BTreeMap::new();

    obj.insert("header".to_owned(), Json::String(msg));

    let parents = commit.parent_ids().collect::<Vec<_>>();
    if parents.len() == 1 {
        obj.insert("parent".to_owned(), Json::String(parents[0].to_string()));
    }

    obj.insert("date".to_owned(), Json::String(t));

    let json = Json::Object(obj);

    Ok(json.to_string())
}
<|endoftext|>


<commit_before>use crate::value::AMQPValue;

use std::{
    borrow,
    collections::{btree_map, BTreeMap},
    fmt, str,
};

use serde::{Deserialize, Serialize};

/// Enumeration referencing all the available AMQP types
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum AMQPType {
    /// A bool
    Boolean,
    /// An i8
    ShortShortInt,
    /// A u8
    ShortShortUInt,
    /// An i16
    ShortInt,
    /// A u16
    ShortUInt,
    /// An i32
    LongInt,
    /// A u32
    LongUInt,
    /// An i64
    LongLongInt,
    /// A u64
    LongLongUInt,
    /// An f32
    Float,
    /// An f64
    Double,
    /// A decimal value represented by a scale and a value
    DecimalValue,
    /// Deprecated, a String
    ShortString,
    /// A String
    LongString,
    /// An array of AMQPValue
    FieldArray,
    /// A timestamp (u64)
    Timestamp,
    /// A Map<String, AMQPValue>
    FieldTable,
    /// An array of bytes, RabbitMQ specific
    ByteArray, /* ByteArray is specific to RabbitMQ */
    /// No value
    Void,
}

impl AMQPType {
    /// Get the AMQPType corresponding to the given id.
    /// We don't strictly follow the spec here but rather the RabbitMQ implementation
    /// 's' means ShortInt (like 'U') instead of ShortString
    /// 'l' and 'L' both mean LongLongInt (no LongLongUInt)
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            /* Specs says 'U', RabbitMQ says 's' (which means ShortString in specs) */
            's' | 'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            /* RabbitMQ treats both 'l' and 'L' as LongLongInt and ignores LongLongUInt */
            'L' | 'l' => Some(AMQPType::LongLongInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::Timestamp),
            'F' => Some(AMQPType::FieldTable),
            'x' => Some(AMQPType::ByteArray),
            'V' => Some(AMQPType::Void),
            _ => None,
        }
    }

    /// Get the id from an AMQPType
    /// We don't strictly follow the spec here but rather the RabbitMQ implementation
    /// ShortString doesn't have an id, we return '_' instead
    /// ShortInt is supposed to be 'U' but we use 's'
    /// LongLongUInt is supposed to be 'L' but we return 'l' as LongLongInt
    pub fn get_id(self) -> char {
        match self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            /* Specs says 'U', RabbitMQ says 's' (which means ShortString in specs) */
            AMQPType::ShortInt => 's',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            /* RabbitMQ treats both 'l' and 'L' as LongLongInt and ignores LongLongUInt */
            AMQPType::LongLongInt | AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            /* ShortString only exists for internal usage, we shouldn't ever have to use this */
            AMQPType::ShortString => '_',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::Timestamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::ByteArray => 'x',
            AMQPType::Void => 'V',
        }
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{:?}", self))
    }
}

/// A bool
pub type Boolean = bool;
/// An i8
pub type ShortShortInt = i8;
/// A u8
pub type ShortShortUInt = u8;
/// An i16
pub type ShortInt = i16;
/// A u16
pub type ShortUInt = u16;
/// An i32
pub type LongInt = i32;
/// A u32
pub type LongUInt = u32;
/// An i64
pub type LongLongInt = i64;
/// A u64
pub type LongLongUInt = u64;
/// A f32
pub type Float = f32;
/// A f64
pub type Double = f64;
/// A timestamp (u64)
pub type Timestamp = LongLongUInt;
/// No value
pub type Void = ();

/// A String (deprecated)
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct ShortString(String);
/// A String
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct LongString(Vec<u8>);
/// An array of AMQPValue
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct FieldArray(Vec<AMQPValue>);
/// A Map<String, AMQPValue>
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct FieldTable(BTreeMap<ShortString, AMQPValue>);
/// An array of bytes (RabbitMQ specific)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct ByteArray(Vec<u8>);

/// A Decimal value composed of a scale and a value
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct DecimalValue {
    /// The scale of the value
    pub scale: ShortShortUInt,
    /// The actual value
    pub value: LongUInt,
}

impl<'a> ShortString {
    /// Get a reference to a ShortString as &str
    pub fn as_str(&'a self) -> &'a str {
        self.0.as_str()
    }
}

impl From<String> for ShortString {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for ShortString {
    fn from(s: &str) -> Self {
        s.to_owned().into()
    }
}

impl borrow::Borrow<str> for ShortString {
    fn borrow(&self) -> &str {
        self.0.borrow()
    }
}

impl fmt::Display for ShortString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> LongString {
    /// Get a reference to a LongString as &[u8]
    pub fn as_bytes(&'a self) -> &'a [u8] {
        &self.0[..]
    }
}

impl From<String> for LongString {
    fn from(s: String) -> Self {
        Self(s.into_bytes())
    }
}

impl From<&str> for LongString {
    fn from(s: &str) -> Self {
        s.to_owned().into()
    }
}

impl fmt::Display for LongString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Ok(s) = String::from_utf8(self.0.clone()) {
            s.fmt(f)
        } else {
            f.write_fmt(format_args!("{:?}", self.0))
        }
    }
}

impl FieldArray {
    /// Get the inner values as a slice
    pub fn as_slice(&self) -> &[AMQPValue] {
        self.0.as_slice()
    }

    /// Add an item to the array
    pub fn push(&mut self, v: AMQPValue) {
        self.0.push(v);
    }
}

impl From<Vec<AMQPValue>> for FieldArray {
    fn from(v: Vec<AMQPValue>) -> Self {
        Self(v)
    }
}

impl FieldTable {
    /// Insert a new entry in the table
    pub fn insert(&mut self, k: ShortString, v: AMQPValue) {
        self.0.insert(k, v);
    }

    /// Check whether the table contains the given key
    pub fn contains_key(&self, k: &str) -> bool {
        self.0.contains_key(k)
    }

    /// Access the inner BTreeMap to perform lookups
    pub fn inner(&self) -> &BTreeMap<ShortString, AMQPValue> {
        &self.0
    }
}

impl<'a> IntoIterator for &'a FieldTable {
    type Item = (&'a ShortString, &'a AMQPValue);
    type IntoIter = btree_map::Iter<'a, ShortString, AMQPValue>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl From<BTreeMap<ShortString, AMQPValue>> for FieldTable {
    fn from(m: BTreeMap<ShortString, AMQPValue>) -> Self {
        Self(m)
    }
}

impl ByteArray {
    /// Get the inner bytes array as slice
    pub fn as_slice(&self) -> &[u8] {
        self.0.as_slice()
    }

    /// Get the length of the inner bytes array
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Check whether the ByteArray is empty
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}

impl From<Vec<u8>> for ByteArray {
    fn from(v: Vec<u8>) -> Self {
        Self(v)
    }
}

impl From<&[u8]> for ByteArray {
    fn from(v: &[u8]) -> Self {
        Self(v.to_vec())
    }
}

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

    #[test]
    fn test_type_from_id() {
        assert_eq!(AMQPType::from_id('T'), Some(AMQPType::Timestamp));
        assert_eq!(AMQPType::from_id('S'), Some(AMQPType::LongString));
        assert_eq!(AMQPType::from_id('s'), Some(AMQPType::ShortInt));
        assert_eq!(AMQPType::from_id('U'), Some(AMQPType::ShortInt));
        assert_eq!(AMQPType::from_id('l'), Some(AMQPType::LongLongInt));
        assert_eq!(AMQPType::from_id('z'), None);
    }

    #[test]
    fn test_type_get_id() {
        assert_eq!(AMQPType::LongLongInt.get_id(), 'l');
        assert_eq!(AMQPType::LongLongUInt.get_id(), 'l');
        assert_eq!(AMQPType::ShortString.get_id(), '_');
    }

    #[test]
    fn test_type_to_string() {
        assert_eq!(AMQPType::Boolean.to_string(), "Boolean");
        assert_eq!(AMQPType::Void.to_string(), "Void");
    }
}
<commit_msg>better display impl for LongString<commit_after>use crate::value::AMQPValue;

use std::{
    borrow,
    collections::{btree_map, BTreeMap},
    fmt, str,
};

use serde::{Deserialize, Serialize};

/// Enumeration referencing all the available AMQP types
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum AMQPType {
    /// A bool
    Boolean,
    /// An i8
    ShortShortInt,
    /// A u8
    ShortShortUInt,
    /// An i16
    ShortInt,
    /// A u16
    ShortUInt,
    /// An i32
    LongInt,
    /// A u32
    LongUInt,
    /// An i64
    LongLongInt,
    /// A u64
    LongLongUInt,
    /// An f32
    Float,
    /// An f64
    Double,
    /// A decimal value represented by a scale and a value
    DecimalValue,
    /// Deprecated, a String
    ShortString,
    /// A String
    LongString,
    /// An array of AMQPValue
    FieldArray,
    /// A timestamp (u64)
    Timestamp,
    /// A Map<String, AMQPValue>
    FieldTable,
    /// An array of bytes, RabbitMQ specific
    ByteArray, /* ByteArray is specific to RabbitMQ */
    /// No value
    Void,
}

impl AMQPType {
    /// Get the AMQPType corresponding to the given id.
    /// We don't strictly follow the spec here but rather the RabbitMQ implementation
    /// 's' means ShortInt (like 'U') instead of ShortString
    /// 'l' and 'L' both mean LongLongInt (no LongLongUInt)
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            /* Specs says 'U', RabbitMQ says 's' (which means ShortString in specs) */
            's' | 'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            /* RabbitMQ treats both 'l' and 'L' as LongLongInt and ignores LongLongUInt */
            'L' | 'l' => Some(AMQPType::LongLongInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::Timestamp),
            'F' => Some(AMQPType::FieldTable),
            'x' => Some(AMQPType::ByteArray),
            'V' => Some(AMQPType::Void),
            _ => None,
        }
    }

    /// Get the id from an AMQPType
    /// We don't strictly follow the spec here but rather the RabbitMQ implementation
    /// ShortString doesn't have an id, we return '_' instead
    /// ShortInt is supposed to be 'U' but we use 's'
    /// LongLongUInt is supposed to be 'L' but we return 'l' as LongLongInt
    pub fn get_id(self) -> char {
        match self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            /* Specs says 'U', RabbitMQ says 's' (which means ShortString in specs) */
            AMQPType::ShortInt => 's',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            /* RabbitMQ treats both 'l' and 'L' as LongLongInt and ignores LongLongUInt */
            AMQPType::LongLongInt | AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            /* ShortString only exists for internal usage, we shouldn't ever have to use this */
            AMQPType::ShortString => '_',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::Timestamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::ByteArray => 'x',
            AMQPType::Void => 'V',
        }
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{:?}", self))
    }
}

/// A bool
pub type Boolean = bool;
/// An i8
pub type ShortShortInt = i8;
/// A u8
pub type ShortShortUInt = u8;
/// An i16
pub type ShortInt = i16;
/// A u16
pub type ShortUInt = u16;
/// An i32
pub type LongInt = i32;
/// A u32
pub type LongUInt = u32;
/// An i64
pub type LongLongInt = i64;
/// A u64
pub type LongLongUInt = u64;
/// A f32
pub type Float = f32;
/// A f64
pub type Double = f64;
/// A timestamp (u64)
pub type Timestamp = LongLongUInt;
/// No value
pub type Void = ();

/// A String (deprecated)
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct ShortString(String);
/// A String
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct LongString(Vec<u8>);
/// An array of AMQPValue
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct FieldArray(Vec<AMQPValue>);
/// A Map<String, AMQPValue>
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct FieldTable(BTreeMap<ShortString, AMQPValue>);
/// An array of bytes (RabbitMQ specific)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct ByteArray(Vec<u8>);

/// A Decimal value composed of a scale and a value
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct DecimalValue {
    /// The scale of the value
    pub scale: ShortShortUInt,
    /// The actual value
    pub value: LongUInt,
}

impl<'a> ShortString {
    /// Get a reference to a ShortString as &str
    pub fn as_str(&'a self) -> &'a str {
        self.0.as_str()
    }
}

impl From<String> for ShortString {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for ShortString {
    fn from(s: &str) -> Self {
        s.to_owned().into()
    }
}

impl borrow::Borrow<str> for ShortString {
    fn borrow(&self) -> &str {
        self.0.borrow()
    }
}

impl fmt::Display for ShortString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> LongString {
    /// Get a reference to a LongString as &[u8]
    pub fn as_bytes(&'a self) -> &'a [u8] {
        &self.0[..]
    }
}

impl From<String> for LongString {
    fn from(s: String) -> Self {
        Self(s.into_bytes())
    }
}

impl From<&str> for LongString {
    fn from(s: &str) -> Self {
        s.to_owned().into()
    }
}

impl fmt::Display for LongString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        String::from_utf8_lossy(&self.0).fmt(f)
    }
}

impl FieldArray {
    /// Get the inner values as a slice
    pub fn as_slice(&self) -> &[AMQPValue] {
        self.0.as_slice()
    }

    /// Add an item to the array
    pub fn push(&mut self, v: AMQPValue) {
        self.0.push(v);
    }
}

impl From<Vec<AMQPValue>> for FieldArray {
    fn from(v: Vec<AMQPValue>) -> Self {
        Self(v)
    }
}

impl FieldTable {
    /// Insert a new entry in the table
    pub fn insert(&mut self, k: ShortString, v: AMQPValue) {
        self.0.insert(k, v);
    }

    /// Check whether the table contains the given key
    pub fn contains_key(&self, k: &str) -> bool {
        self.0.contains_key(k)
    }

    /// Access the inner BTreeMap to perform lookups
    pub fn inner(&self) -> &BTreeMap<ShortString, AMQPValue> {
        &self.0
    }
}

impl<'a> IntoIterator for &'a FieldTable {
    type Item = (&'a ShortString, &'a AMQPValue);
    type IntoIter = btree_map::Iter<'a, ShortString, AMQPValue>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl From<BTreeMap<ShortString, AMQPValue>> for FieldTable {
    fn from(m: BTreeMap<ShortString, AMQPValue>) -> Self {
        Self(m)
    }
}

impl ByteArray {
    /// Get the inner bytes array as slice
    pub fn as_slice(&self) -> &[u8] {
        self.0.as_slice()
    }

    /// Get the length of the inner bytes array
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Check whether the ByteArray is empty
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}

impl From<Vec<u8>> for ByteArray {
    fn from(v: Vec<u8>) -> Self {
        Self(v)
    }
}

impl From<&[u8]> for ByteArray {
    fn from(v: &[u8]) -> Self {
        Self(v.to_vec())
    }
}

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

    #[test]
    fn test_type_from_id() {
        assert_eq!(AMQPType::from_id('T'), Some(AMQPType::Timestamp));
        assert_eq!(AMQPType::from_id('S'), Some(AMQPType::LongString));
        assert_eq!(AMQPType::from_id('s'), Some(AMQPType::ShortInt));
        assert_eq!(AMQPType::from_id('U'), Some(AMQPType::ShortInt));
        assert_eq!(AMQPType::from_id('l'), Some(AMQPType::LongLongInt));
        assert_eq!(AMQPType::from_id('z'), None);
    }

    #[test]
    fn test_type_get_id() {
        assert_eq!(AMQPType::LongLongInt.get_id(), 'l');
        assert_eq!(AMQPType::LongLongUInt.get_id(), 'l');
        assert_eq!(AMQPType::ShortString.get_id(), '_');
    }

    #[test]
    fn test_type_to_string() {
        assert_eq!(AMQPType::Boolean.to_string(), "Boolean");
        assert_eq!(AMQPType::Void.to_string(), "Void");
    }
}
<|endoftext|>


<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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    fn winit_event_to_servo_event(&self, event: glutin::Event) {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    self.window.winit_event_to_servo_event(event);
                }
            },
        }
    }

    fn run_loop(self) {
        let mut stop = false;
        loop {
            let mut events_loop = self.events_loop.borrow_mut();
            if self.window.is_animating() && !self.suspended.get() {
                // We block on compositing (self.handle_events() ends up calling swap_buffers)
                events_loop.poll_events(|e| {
                    self.winit_event_to_servo_event(e);
                });
                stop = self.handle_events();
            } else {
                // We block on winit's event loop (window events)
                events_loop.run_forever(|e| {
                    self.winit_event_to_servo_event(e);
                    if self.has_events() && !self.suspended.get() {
                        stop = self.handle_events();
                    }
                    if stop || self.window.is_animating() && !self.suspended.get() {
                        glutin::ControlFlow::Break
                    } else {
                        glutin::ControlFlow::Continue
                    }
                });
            }
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<commit_msg>Don't process events while borrowing the event loop<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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    fn winit_event_to_servo_event(&self, event: glutin::Event) {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    self.window.winit_event_to_servo_event(event);
                }
            },
        }
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    self.winit_event_to_servo_event(e);
                    glutin::ControlFlow::Break
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2020-present, Gregory Szorc
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.

use {
    crate::ZstdError,
    pyo3::{buffer::PyBuffer, prelude::*, wrap_pyfunction},
};

#[pyclass]
struct FrameParameters {
    header: zstd_sys::ZSTD_frameHeader,
}

#[pymethods]
impl FrameParameters {
    #[getter]
    fn content_size(&self) -> PyResult<libc::c_ulonglong> {
        Ok(self.header.frameContentSize)
    }

    #[getter]
    fn window_size(&self) -> PyResult<libc::c_ulonglong> {
        Ok(self.header.windowSize)
    }

    #[getter]
    fn dict_id(&self) -> PyResult<libc::c_uint> {
        Ok(self.header.dictID)
    }

    #[getter]
    fn has_checksum(&self) -> PyResult<bool> {
        Ok(match self.header.checksumFlag {
            0 => false,
            _ => true,
        })
    }
}

#[pyfunction]
fn get_frame_parameters(py: Python, buffer: PyBuffer<u8>) -> PyResult<Py<FrameParameters>> {
    let raw_data = unsafe {
        std::slice::from_raw_parts::<u8>(buffer.buf_ptr() as *const _, buffer.len_bytes())
    };

    let mut header = zstd_sys::ZSTD_frameHeader {
        frameContentSize: 0,
        windowSize: 0,
        blockSizeMax: 0,
        frameType: zstd_sys::ZSTD_frameType_e::ZSTD_frame,
        headerSize: 0,
        dictID: 0,
        checksumFlag: 0,
    };
    let zresult = unsafe {
        zstd_sys::ZSTD_getFrameHeader(&mut header, raw_data.as_ptr() as *const _, raw_data.len())
    };

    if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
        Err(ZstdError::new_err(format!(
            "cannot get frame parameters: {}",
            zstd_safe::get_error_name(zresult)
        )))
    } else if zresult != 0 {
        Err(ZstdError::new_err(format!(
            "not enough data for frame parameters; need {} bytes",
            zresult
        )))
    } else {
        Py::new(py, FrameParameters { header })
    }
}

pub(crate) fn init_module(module: &PyModule) -> PyResult<()> {
    module.add_class::<FrameParameters>()?;
    module.add_function(wrap_pyfunction!(get_frame_parameters, module)?)?;

    Ok(())
}
<commit_msg>rust: implement frame_content_size() and frame_header_size()<commit_after>// Copyright (c) 2020-present, Gregory Szorc
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.

use {
    crate::ZstdError,
    pyo3::{buffer::PyBuffer, prelude::*, wrap_pyfunction},
};

#[pyclass]
struct FrameParameters {
    header: zstd_sys::ZSTD_frameHeader,
}

#[pymethods]
impl FrameParameters {
    #[getter]
    fn content_size(&self) -> PyResult<libc::c_ulonglong> {
        Ok(self.header.frameContentSize)
    }

    #[getter]
    fn window_size(&self) -> PyResult<libc::c_ulonglong> {
        Ok(self.header.windowSize)
    }

    #[getter]
    fn dict_id(&self) -> PyResult<libc::c_uint> {
        Ok(self.header.dictID)
    }

    #[getter]
    fn has_checksum(&self) -> PyResult<bool> {
        Ok(match self.header.checksumFlag {
            0 => false,
            _ => true,
        })
    }
}

#[pyfunction]
fn frame_content_size(data: PyBuffer<u8>) -> PyResult<i64> {
    let size = unsafe { zstd_sys::ZSTD_getFrameContentSize(data.buf_ptr(), data.len_bytes()) };

    if size == zstd_sys::ZSTD_CONTENTSIZE_ERROR as _ {
        Err(ZstdError::new_err("error when determining content size"))
    } else if size == zstd_sys::ZSTD_CONTENTSIZE_UNKNOWN as _ {
        Ok(-1)
    } else {
        Ok(size as _)
    }
}

#[pyfunction]
fn frame_header_size(data: PyBuffer<u8>) -> PyResult<usize> {
    let zresult = unsafe { zstd_sys::ZSTD_frameHeaderSize(data.buf_ptr(), data.len_bytes()) };
    if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
        return Err(ZstdError::new_err(format!(
            "could not determine frame header size: {}",
            zstd_safe::get_error_name(zresult)
        )));
    }

    Ok(zresult)
}

#[pyfunction]
fn get_frame_parameters(py: Python, buffer: PyBuffer<u8>) -> PyResult<Py<FrameParameters>> {
    let raw_data = unsafe {
        std::slice::from_raw_parts::<u8>(buffer.buf_ptr() as *const _, buffer.len_bytes())
    };

    let mut header = zstd_sys::ZSTD_frameHeader {
        frameContentSize: 0,
        windowSize: 0,
        blockSizeMax: 0,
        frameType: zstd_sys::ZSTD_frameType_e::ZSTD_frame,
        headerSize: 0,
        dictID: 0,
        checksumFlag: 0,
    };
    let zresult = unsafe {
        zstd_sys::ZSTD_getFrameHeader(&mut header, raw_data.as_ptr() as *const _, raw_data.len())
    };

    if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
        Err(ZstdError::new_err(format!(
            "cannot get frame parameters: {}",
            zstd_safe::get_error_name(zresult)
        )))
    } else if zresult != 0 {
        Err(ZstdError::new_err(format!(
            "not enough data for frame parameters; need {} bytes",
            zresult
        )))
    } else {
        Py::new(py, FrameParameters { header })
    }
}

pub(crate) fn init_module(module: &PyModule) -> PyResult<()> {
    module.add_class::<FrameParameters>()?;
    module.add_function(wrap_pyfunction!(frame_content_size, module)?)?;
    module.add_function(wrap_pyfunction!(frame_header_size, module)?)?;
    module.add_function(wrap_pyfunction!(get_frame_parameters, module)?)?;

    Ok(())
}
<|endoftext|>