<commit_before>#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request<'a>(pub &'a [u8], pub &'a [u8]);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
    All,
    Fast,
    Full,
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Response<'a> {
    Capabilities(Vec<Capability<'a>>),
    Continue {
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Done {
        tag: RequestId,
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Data {
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Expunge(u32),
    Vanished {
        earlier: bool,
        uids: Vec<std::ops::RangeInclusive<u32>>,
    },
    Fetch(u32, Vec<AttributeValue<'a>>),
    MailboxData(MailboxDatum<'a>),
}

impl<'a> Response<'a> {
    pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult {
        crate::parser::parse_response(buf)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ResponseCode<'a> {
    Alert,
    BadCharset(Option<Vec<&'a str>>),
    Capabilities(Vec<Capability<'a>>),
    HighestModSeq(u64), // RFC 4551, section 3.1.1
    Parse,
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
    AppendUid(u32, Vec<UidSetMember>),
    CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
    UidNotSticky,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum UidSetMember {
    UidRange(std::ops::RangeInclusive<u32>),
    Uid(u32),
}
impl From<std::ops::RangeInclusive<u32>> for UidSetMember {
    fn from(x: std::ops::RangeInclusive<u32>) -> Self {
        UidSetMember::UidRange(x)
    }
}
impl From<u32> for UidSetMember {
    fn from(x: u32) -> Self {
        UidSetMember::Uid(x)
    }
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum StatusAttribute {
    HighestModSeq(u64), // RFC 4551
    Messages(u32),
    Recent(u32),
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
    pub entry: String,
    pub value: Option<String>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MailboxDatum<'a> {
    Exists(u32),
    Flags(Vec<&'a str>),
    List {
        flags: Vec<&'a str>,
        delimiter: Option<&'a str>,
        name: &'a str,
    },
    Search(Vec<u32>),
    Status {
        mailbox: &'a str,
        status: Vec<StatusAttribute>,
    },
    Recent(u32),
    MetadataSolicited {
        mailbox: &'a str,
        values: Vec<Metadata>,
    },
    MetadataUnsolicited {
        mailbox: &'a str,
        values: Vec<&'a str>,
    },
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
    Imap4rev1,
    Auth(&'a str),
    Atom(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Attribute {
    Body,
    Envelope,
    Flags,
    InternalDate,
    ModSeq, // RFC 4551, section 3.3.2
    Rfc822,
    Rfc822Size,
    Rfc822Text,
    Uid,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
    Header,
    Mime,
    Text,
}

#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
    Full(MessageSection),
    Part(Vec<u32>, Option<MessageSection>),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum AttributeValue<'a> {
    BodySection {
        section: Option<SectionPath>,
        index: Option<u32>,
        data: Option<&'a [u8]>,
    },
    BodyStructure(BodyStructure<'a>),
    Envelope(Box<Envelope<'a>>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    ModSeq(u64), // RFC 4551, section 3.3.2
    Rfc822(Option<&'a [u8]>),
    Rfc822Header(Option<&'a [u8]>),
    Rfc822Size(u32),
    Rfc822Text(Option<&'a [u8]>),
    Uid(u32),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
    Basic {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        extension: Option<BodyExtension<'a>>,
    },
    Text {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Message {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        envelope: Envelope<'a>,
        body: Box<BodyStructure<'a>>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Multipart {
        common: BodyContentCommon<'a>,
        bodies: Vec<BodyStructure<'a>>,
        extension: Option<BodyExtension<'a>>,
    },
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
    pub ty: ContentType<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
    pub id: Option<&'a str>,
    pub md5: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
    pub ty: &'a str,
    pub subtype: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
    pub ty: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
    SevenBit,
    EightBit,
    Binary,
    Base64,
    QuotedPrintable,
    Other(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
    Num(u32),
    Str(Option<&'a str>),
    List(Vec<BodyExtension<'a>>),
}

pub type BodyParams<'a> = Option<Vec<(&'a str, &'a str)>>;

#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
    pub date: Option<&'a [u8]>,
    pub subject: Option<&'a [u8]>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a [u8]>,
    pub message_id: Option<&'a [u8]>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
    pub name: Option<&'a [u8]>,
    pub adl: Option<&'a [u8]>,
    pub mailbox: Option<&'a [u8]>,
    pub host: Option<&'a [u8]>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}

// Body Structure

pub struct BodyFields<'a> {
    pub param: BodyParams<'a>,
    pub id: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

pub struct BodyExt1Part<'a> {
    pub md5: Option<&'a str>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}

pub struct BodyExtMPart<'a> {
    pub param: BodyParams<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}
<commit_msg>Import RangeInclusive<commit_after>use std::ops::RangeInclusive;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request<'a>(pub &'a [u8], pub &'a [u8]);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
    All,
    Fast,
    Full,
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Response<'a> {
    Capabilities(Vec<Capability<'a>>),
    Continue {
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Done {
        tag: RequestId,
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Data {
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Expunge(u32),
    Vanished {
        earlier: bool,
        uids: Vec<std::ops::RangeInclusive<u32>>,
    },
    Fetch(u32, Vec<AttributeValue<'a>>),
    MailboxData(MailboxDatum<'a>),
}

impl<'a> Response<'a> {
    pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult {
        crate::parser::parse_response(buf)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ResponseCode<'a> {
    Alert,
    BadCharset(Option<Vec<&'a str>>),
    Capabilities(Vec<Capability<'a>>),
    HighestModSeq(u64), // RFC 4551, section 3.1.1
    Parse,
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
    AppendUid(u32, Vec<UidSetMember>),
    CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
    UidNotSticky,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum UidSetMember {
    UidRange(RangeInclusive<u32>),
    Uid(u32),
}
impl From<RangeInclusive<u32>> for UidSetMember {
    fn from(x: RangeInclusive<u32>) -> Self {
        UidSetMember::UidRange(x)
    }
}
impl From<u32> for UidSetMember {
    fn from(x: u32) -> Self {
        UidSetMember::Uid(x)
    }
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum StatusAttribute {
    HighestModSeq(u64), // RFC 4551
    Messages(u32),
    Recent(u32),
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
    pub entry: String,
    pub value: Option<String>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MailboxDatum<'a> {
    Exists(u32),
    Flags(Vec<&'a str>),
    List {
        flags: Vec<&'a str>,
        delimiter: Option<&'a str>,
        name: &'a str,
    },
    Search(Vec<u32>),
    Status {
        mailbox: &'a str,
        status: Vec<StatusAttribute>,
    },
    Recent(u32),
    MetadataSolicited {
        mailbox: &'a str,
        values: Vec<Metadata>,
    },
    MetadataUnsolicited {
        mailbox: &'a str,
        values: Vec<&'a str>,
    },
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
    Imap4rev1,
    Auth(&'a str),
    Atom(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Attribute {
    Body,
    Envelope,
    Flags,
    InternalDate,
    ModSeq, // RFC 4551, section 3.3.2
    Rfc822,
    Rfc822Size,
    Rfc822Text,
    Uid,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
    Header,
    Mime,
    Text,
}

#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
    Full(MessageSection),
    Part(Vec<u32>, Option<MessageSection>),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum AttributeValue<'a> {
    BodySection {
        section: Option<SectionPath>,
        index: Option<u32>,
        data: Option<&'a [u8]>,
    },
    BodyStructure(BodyStructure<'a>),
    Envelope(Box<Envelope<'a>>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    ModSeq(u64), // RFC 4551, section 3.3.2
    Rfc822(Option<&'a [u8]>),
    Rfc822Header(Option<&'a [u8]>),
    Rfc822Size(u32),
    Rfc822Text(Option<&'a [u8]>),
    Uid(u32),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
    Basic {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        extension: Option<BodyExtension<'a>>,
    },
    Text {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Message {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        envelope: Envelope<'a>,
        body: Box<BodyStructure<'a>>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Multipart {
        common: BodyContentCommon<'a>,
        bodies: Vec<BodyStructure<'a>>,
        extension: Option<BodyExtension<'a>>,
    },
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
    pub ty: ContentType<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
    pub id: Option<&'a str>,
    pub md5: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
    pub ty: &'a str,
    pub subtype: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
    pub ty: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
    SevenBit,
    EightBit,
    Binary,
    Base64,
    QuotedPrintable,
    Other(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
    Num(u32),
    Str(Option<&'a str>),
    List(Vec<BodyExtension<'a>>),
}

pub type BodyParams<'a> = Option<Vec<(&'a str, &'a str)>>;

#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
    pub date: Option<&'a [u8]>,
    pub subject: Option<&'a [u8]>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a [u8]>,
    pub message_id: Option<&'a [u8]>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
    pub name: Option<&'a [u8]>,
    pub adl: Option<&'a [u8]>,
    pub mailbox: Option<&'a [u8]>,
    pub host: Option<&'a [u8]>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}

// Body Structure

pub struct BodyFields<'a> {
    pub param: BodyParams<'a>,
    pub id: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

pub struct BodyExt1Part<'a> {
    pub md5: Option<&'a str>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}

pub struct BodyExtMPart<'a> {
    pub param: BodyParams<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::vec_ng::Vec;
use cgmath::vector::{Vec3, Vec2};
use core::map::MapPosIter;
use core::types::{MInt, Size2, MapPos};
use visualizer::gl_helpers::{
    set_clear_color,
    clear_screen,
    get_vec2_from_pixel,
};
use visualizer::camera::Camera;
use visualizer::geom::Geom;
use visualizer::mesh::Mesh;
use visualizer::types::{VertexCoord, Color3, MFloat, MatId};
use visualizer::shader::Shader;

fn build_hex_map_mesh(
    geom: &Geom,
    map_size: Size2<MInt>
) -> (Vec<VertexCoord>, Vec<Color3>) {
    let mut c_data = Vec::new();
    let mut v_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos3d = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as MInt, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            let col_x = tile_pos.x as MFloat / 255.0;
            let col_y = tile_pos.y as MFloat / 255.0;
            let color = Color3{r: col_x, g: col_y, b: 1.0};
            v_data.push(pos3d + vertex);
            c_data.push(color);
            v_data.push(pos3d + next_vertex);
            c_data.push(color);
            v_data.push(pos3d + Vec3::zero());
            c_data.push(color);
        }
    }
    (v_data, c_data)
}

fn get_mesh(geom: &Geom, map_size: Size2<MInt>, shader: &Shader) -> Mesh {
    let (vertex_data, color_data) = build_hex_map_mesh(geom, map_size);
    let mut mesh = Mesh::new(vertex_data.as_slice());
    mesh.set_color(color_data.as_slice());
    mesh.prepare(shader);
    mesh
}

pub struct TilePicker {
    shader: Shader,
    map_mesh: Mesh,
    mvp_mat_id: MatId,
    win_size: Size2<MInt>,
}

impl TilePicker {
    pub fn new(
        win_size: Size2<MInt>,
        geom: &Geom,
        map_size: Size2<MInt>
    ) -> ~TilePicker {
        let shader = Shader::new("pick.vs.glsl", "pick.fs.glsl");
        let mvp_mat_id = MatId(shader.get_uniform("mvp_mat"));
        let map_mesh = get_mesh(geom, map_size, &shader);
        let tile_picker = ~TilePicker {
            map_mesh: map_mesh,
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            win_size: win_size,
        };
        tile_picker
    }

    pub fn set_win_size(&mut self, win_size: Size2<MInt>) {
        self.win_size = win_size;
    }

    pub fn pick_tile(
        &mut self,
        camera: &Camera,
        mouse_pos: Vec2<MInt>
    ) -> Option<MapPos> {
        self.shader.activate();
        self.shader.uniform_mat4f(self.mvp_mat_id, &camera.mat());
        set_clear_color(0.0, 0.0, 0.0);
        clear_screen();
        self.map_mesh.draw(&self.shader);
        get_vec2_from_pixel(self.win_size, mouse_pos)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>tile_picker.rs: merged build_hex_map_mesh() into get_mesh()<commit_after>// See LICENSE file for copyright and license details.

use std::vec_ng::Vec;
use cgmath::vector::{Vec3, Vec2};
use core::map::MapPosIter;
use core::types::{MInt, Size2, MapPos};
use visualizer::gl_helpers::{
    set_clear_color,
    clear_screen,
    get_vec2_from_pixel,
};
use visualizer::camera::Camera;
use visualizer::geom::Geom;
use visualizer::mesh::Mesh;
use visualizer::types::{VertexCoord, Color3, MFloat, MatId};
use visualizer::shader::Shader;

fn get_mesh(geom: &Geom, map_size: Size2<MInt>, shader: &Shader) -> Mesh {
    let mut c_data = Vec::new();
    let mut v_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos3d = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as MInt, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            let col_x = tile_pos.x as MFloat / 255.0;
            let col_y = tile_pos.y as MFloat / 255.0;
            let color = Color3{r: col_x, g: col_y, b: 1.0};
            v_data.push(pos3d + vertex);
            c_data.push(color);
            v_data.push(pos3d + next_vertex);
            c_data.push(color);
            v_data.push(pos3d + Vec3::zero());
            c_data.push(color);
        }
    }
    let mut mesh = Mesh::new(v_data.as_slice());
    mesh.set_color(c_data.as_slice());
    mesh.prepare(shader);
    mesh
}

pub struct TilePicker {
    shader: Shader,
    map_mesh: Mesh,
    mvp_mat_id: MatId,
    win_size: Size2<MInt>,
}

impl TilePicker {
    pub fn new(
        win_size: Size2<MInt>,
        geom: &Geom,
        map_size: Size2<MInt>
    ) -> ~TilePicker {
        let shader = Shader::new("pick.vs.glsl", "pick.fs.glsl");
        let mvp_mat_id = MatId(shader.get_uniform("mvp_mat"));
        let map_mesh = get_mesh(geom, map_size, &shader);
        let tile_picker = ~TilePicker {
            map_mesh: map_mesh,
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            win_size: win_size,
        };
        tile_picker
    }

    pub fn set_win_size(&mut self, win_size: Size2<MInt>) {
        self.win_size = win_size;
    }

    pub fn pick_tile(
        &mut self,
        camera: &Camera,
        mouse_pos: Vec2<MInt>
    ) -> Option<MapPos> {
        self.shader.activate();
        self.shader.uniform_mat4f(self.mvp_mat_id, &camera.mat());
        set_clear_color(0.0, 0.0, 0.0);
        clear_screen();
        self.map_mesh.draw(&self.shader);
        get_vec2_from_pixel(self.win_size, mouse_pos)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>//! # Integration tests.
//!
//! These tests are run on our executable to make sure that all the
//! command-line options work correctly.

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};

static TEST_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// This code is inspired by the `WorkDir` pattern that BurntSushi uses to
/// test CLI tools like `ripgrep` and `xsv`.
struct WorkDir {
    bin: PathBuf,
    dir: PathBuf,
}

impl WorkDir {
    fn new(test_name: &str) -> WorkDir {
        let mut bin_dir = env::current_exe()
            .expect("Could not find executable")
            .parent()
            .expect("Could not find parent directory for executable")
            .to_path_buf();
        if bin_dir.ends_with("deps") {
            bin_dir.pop();
        }
        let id = TEST_ID.fetch_add(1, Ordering::SeqCst);
        let dir = bin_dir.join("vobsub2png-tests")
            .join(test_name)
            .join(format!("{}", id));
        if dir.exists() {
            fs::remove_dir_all(&dir)
                .expect("Could not remove test output directory");
        }
        fs::create_dir_all(&dir)
            .expect("Could not create test output directory");
        WorkDir {
            bin: bin_dir.join("vobsub2png"),
            dir: dir,
        }
    }

    fn cmd(&self) -> process::Command {
        let mut cmd = process::Command::new(&self.bin);
        cmd.current_dir(&self.dir);
        cmd
    }

    fn fixture<P: AsRef<Path>>(&self, path: P) -> PathBuf {
        let cwd = env::current_dir().expect("Could not get current dir");
        fs::canonicalize(cwd.join(path))
            .expect("Could not canonicalize path")
    }

    fn expect_path<P: AsRef<Path>>(&self, path: P) {
        let path = self.dir.join(path);
        assert!(path.exists(), format!("{} exists", path.display()));
    }
}

#[test]
fn generates_png_and_json_files() {
    let workdir = WorkDir::new("generates_png_and_json_files");
    let status = workdir.cmd()
        .arg("-o")
        .arg("out")
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("out/index.json");
    workdir.expect_path("out/0000.png");
    workdir.expect_path("out/0001.png");
}

#[test]
fn defaults_out_dir_based_on_input_name() {
    let workdir = WorkDir::new("generates_png_and_json_files");
    let status = workdir.cmd()
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("example_subtitles/index.json");
    workdir.expect_path("example_subtitles/0000.png");
    workdir.expect_path("example_subtitles/0001.png");
}
<commit_msg>Fix test directory name<commit_after>//! # Integration tests.
//!
//! These tests are run on our executable to make sure that all the
//! command-line options work correctly.

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};

static TEST_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// This code is inspired by the `WorkDir` pattern that BurntSushi uses to
/// test CLI tools like `ripgrep` and `xsv`.
struct WorkDir {
    bin: PathBuf,
    dir: PathBuf,
}

impl WorkDir {
    fn new(test_name: &str) -> WorkDir {
        let mut bin_dir = env::current_exe()
            .expect("Could not find executable")
            .parent()
            .expect("Could not find parent directory for executable")
            .to_path_buf();
        if bin_dir.ends_with("deps") {
            bin_dir.pop();
        }
        let id = TEST_ID.fetch_add(1, Ordering::SeqCst);
        let dir = bin_dir.join("vobsub2png-tests")
            .join(test_name)
            .join(format!("{}", id));
        if dir.exists() {
            fs::remove_dir_all(&dir)
                .expect("Could not remove test output directory");
        }
        fs::create_dir_all(&dir)
            .expect("Could not create test output directory");
        WorkDir {
            bin: bin_dir.join("vobsub2png"),
            dir: dir,
        }
    }

    fn cmd(&self) -> process::Command {
        let mut cmd = process::Command::new(&self.bin);
        cmd.current_dir(&self.dir);
        cmd
    }

    fn fixture<P: AsRef<Path>>(&self, path: P) -> PathBuf {
        let cwd = env::current_dir().expect("Could not get current dir");
        fs::canonicalize(cwd.join(path))
            .expect("Could not canonicalize path")
    }

    fn expect_path<P: AsRef<Path>>(&self, path: P) {
        let path = self.dir.join(path);
        assert!(path.exists(), format!("{} exists", path.display()));
    }
}

#[test]
fn generates_png_and_json_files() {
    let workdir = WorkDir::new("generates_png_and_json_files");
    let status = workdir.cmd()
        .arg("-o")
        .arg("out")
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("out/index.json");
    workdir.expect_path("out/0000.png");
    workdir.expect_path("out/0001.png");
}

#[test]
fn defaults_out_dir_based_on_input_name() {
    let workdir = WorkDir::new("defaults_out_dir_based_on_input_name");
    let status = workdir.cmd()
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("example_subtitles/index.json");
    workdir.expect_path("example_subtitles/0000.png");
    workdir.expect_path("example_subtitles/0001.png");
}
<|endoftext|>


<commit_before>use super::*;
use kafka::client::KafkaClient;

#[test]
fn test_kafka_client_load_metadata() {
    let hosts = vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()];
    let mut client = KafkaClient::new(hosts.clone());
    client.load_metadata_all().unwrap();

    let topics = client.topics();

    // sanity check the hosts
    assert_eq!(hosts.as_ref() as &[String], client.hosts());

    // names
    let topic_names: Vec<&str> = topics.names()
        // don't count the consumer offsets internal topic
        .filter(|name| *name != KAFKA_CONSUMER_OFFSETS_TOPIC_NAME)
        .collect();
    let correct_topic_names = vec![TEST_TOPIC_NAME];
    assert_eq!(correct_topic_names, topic_names);

    // partitions
    let topic_partitions = topics.partitions(TEST_TOPIC_NAME).unwrap().available_ids();
    let correct_topic_partitions = TEST_TOPIC_PARTITIONS.to_vec();
    assert_eq!(correct_topic_partitions, topic_partitions);
}
<commit_msg>sanity check KafkaClient::client_id<commit_after>use super::*;
use kafka::client::KafkaClient;

#[test]
fn test_kafka_client_load_metadata() {
    let hosts = vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()];
    let client_id = "test-id".to_string();
    let mut client = KafkaClient::new(hosts.clone());
    client.set_client_id(client_id.clone());
    client.load_metadata_all().unwrap();

    let topics = client.topics();

    // sanity checks
    assert_eq!(hosts.as_ref() as &[String], client.hosts());
    assert_eq!(&client_id, client.client_id());

    // names
    let topic_names: Vec<&str> = topics.names()
        // don't count the consumer offsets internal topic
        .filter(|name| *name != KAFKA_CONSUMER_OFFSETS_TOPIC_NAME)
        .collect();
    let correct_topic_names = vec![TEST_TOPIC_NAME];
    assert_eq!(correct_topic_names, topic_names);

    // partitions
    let topic_partitions = topics.partitions(TEST_TOPIC_NAME).unwrap().available_ids();
    let correct_topic_partitions = TEST_TOPIC_PARTITIONS.to_vec();
    assert_eq!(correct_topic_partitions, topic_partitions);
}
<|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 http://mozilla.org/MPL/2.0/. */

//! The style bloom filter is used as an optimization when matching deep
//! descendant selectors.

#![deny(missing_docs)]

use atomic_refcell::{AtomicRefMut, AtomicRefCell};
use dom::{SendElement, TElement};
use owning_ref::OwningHandle;
use selectors::bloom::BloomFilter;
use servo_arc::Arc;
use smallvec::SmallVec;

/// Bloom filters are large allocations, so we store them in thread-local storage
/// such that they can be reused across style traversals. StyleBloom is responsible
/// for ensuring that the bloom filter is zeroed when it is dropped.
thread_local!(static BLOOM_KEY: Arc<AtomicRefCell<BloomFilter>> =
              Arc::new(AtomicRefCell::new(BloomFilter::new())));

/// A struct that allows us to fast-reject deep descendant selectors avoiding
/// selector-matching.
///
/// This is implemented using a counting bloom filter, and it's a standard
/// optimization. See Gecko's `AncestorFilter`, and Blink's and WebKit's
/// `SelectorFilter`.
///
/// The constraints for Servo's style system are a bit different compared to
/// traditional style systems given Servo does a parallel breadth-first
/// traversal instead of a sequential depth-first traversal.
///
/// This implies that we need to track a bit more state than other browsers to
/// ensure we're doing the correct thing during the traversal, and being able to
/// apply this optimization effectively.
///
/// Concretely, we have a bloom filter instance per worker thread, and we track
/// the current DOM depth in order to find a common ancestor when it doesn't
/// match the previous element we've styled.
///
/// This is usually a pretty fast operation (we use to be one level deeper than
/// the previous one), but in the case of work-stealing, we may needed to push
/// and pop multiple elements.
///
/// See the `insert_parents_recovering`, where most of the magic happens.
///
/// Regarding thread-safety, this struct is safe because:
///
///  * We clear this after a restyle.
///  * The DOM shape and attributes (and every other thing we access here) are
///    immutable during a restyle.
///
pub struct StyleBloom<E: TElement> {
    /// A handle to the bloom filter from the thread upon which this StyleBloom
    /// was created. We use AtomicRefCell so that this is all |Send|, which allows
    /// StyleBloom to live in ThreadLocalStyleContext, which is dropped from the
    /// parent thread.
    filter: OwningHandle<Arc<AtomicRefCell<BloomFilter>>, AtomicRefMut<'static, BloomFilter>>,

    /// The stack of elements that this bloom filter contains, along with the
    /// number of hashes pushed for each element.
    elements: SmallVec<[PushedElement<E>; 16]>,

    /// Stack of hashes that have been pushed onto this filter.
    pushed_hashes: SmallVec<[u32; 64]>,
}

/// The very rough benchmarks in the selectors crate show clear()
/// costing about 25 times more than remove_hash(). We use this to implement
/// clear() more efficiently when only a small number of hashes have been
/// pushed.
///
/// One subtly to note is that remove_hash() will not touch the value
/// if the filter overflowed. However, overflow can only occur if we
/// get 255 collisions on the same hash value, and 25 < 255.
const MEMSET_CLEAR_THRESHOLD: usize = 25;

struct PushedElement<E: TElement> {
    /// The element that was pushed.
    element: SendElement<E>,

    /// The number of hashes pushed for the element.
    num_hashes: usize,
}

impl<E: TElement> PushedElement<E> {
    fn new(el: E, num_hashes: usize) -> Self {
        PushedElement {
            element: unsafe { SendElement::new(el) },
            num_hashes: num_hashes,
        }
    }
}

fn each_relevant_element_hash<E, F>(element: E, mut f: F)
    where E: TElement,
          F: FnMut(u32),
{
    f(element.get_local_name().get_hash());
    f(element.get_namespace().get_hash());

    if let Some(id) = element.get_id() {
        f(id.get_hash());
    }

    element.each_class(|class| {
        f(class.get_hash())
    });
}

impl<E: TElement> Drop for StyleBloom<E> {
    fn drop(&mut self) {
        // Leave the reusable bloom filter in a zeroed state.
        self.clear();
    }
}

impl<E: TElement> StyleBloom<E> {
    /// Create an empty `StyleBloom`. Because StyleBloom acquires the thread-
    /// local filter buffer, creating multiple live StyleBloom instances at
    /// the same time on the same thread will panic.
    pub fn new() -> Self {
        let bloom_arc = BLOOM_KEY.with(|b| b.clone());
        let filter = OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
        debug_assert!(filter.is_zeroed(), "Forgot to zero the bloom filter last time");
        StyleBloom {
            filter: filter,
            elements: Default::default(),
            pushed_hashes: Default::default(),
        }
    }

    /// Return the bloom filter used properly by the `selectors` crate.
    pub fn filter(&self) -> &BloomFilter {
        &*self.filter
    }

    /// Push an element to the bloom filter, knowing that it's a child of the
    /// last element parent.
    pub fn push(&mut self, element: E) {
        if cfg!(debug_assertions) {
            if self.elements.is_empty() {
                assert!(element.traversal_parent().is_none());
            }
        }
        self.push_internal(element);
    }

    /// Same as `push`, but without asserting, in order to use it from
    /// `rebuild`.
    fn push_internal(&mut self, element: E) {
        let mut count = 0;
        each_relevant_element_hash(element, |hash| {
            count += 1;
            self.filter.insert_hash(hash);
            self.pushed_hashes.push(hash);
        });
        self.elements.push(PushedElement::new(element, count));
    }

    /// Pop the last element in the bloom filter and return it.
    #[inline]
    fn pop(&mut self) -> Option<E> {
        let (popped_element, num_hashes)  = match self.elements.pop() {
            None => return None,
            Some(x) => (*x.element, x.num_hashes),
        };

        // Verify that the pushed hashes match the ones we'd get from the element.
        let mut expected_hashes = vec![];
        if cfg!(debug_assertions) {
            each_relevant_element_hash(popped_element, |hash| expected_hashes.push(hash));
        }

        for _ in 0..num_hashes {
            let hash = self.pushed_hashes.pop().unwrap();
            debug_assert_eq!(expected_hashes.pop().unwrap(), hash);
            self.filter.remove_hash(hash);
        }

        Some(popped_element)
    }

    /// Returns true if the bloom filter is empty.
    pub fn is_empty(&self) -> bool {
        self.elements.is_empty()
    }

    /// Returns the DOM depth of elements that can be correctly
    /// matched against the bloom filter (that is, the number of
    /// elements in our list).
    pub fn matching_depth(&self) -> usize {
        self.elements.len()
    }

    /// Clears the bloom filter.
    pub fn clear(&mut self) {
        self.elements.clear();

        if self.pushed_hashes.len() > MEMSET_CLEAR_THRESHOLD {
            self.filter.clear();
            self.pushed_hashes.clear();
        } else {
            for hash in self.pushed_hashes.drain() {
                self.filter.remove_hash(hash);
            }
            debug_assert!(self.filter.is_zeroed());
        }
    }

    /// Rebuilds the bloom filter up to the parent of the given element.
    pub fn rebuild(&mut self, mut element: E) {
        self.clear();

        let mut parents_to_insert = SmallVec::<[E; 16]>::new();
        while let Some(parent) = element.traversal_parent() {
            parents_to_insert.push(parent);
            element = parent;
        }

        for parent in parents_to_insert.drain().rev() {
            self.push(parent);
        }
    }

    /// In debug builds, asserts that all the parents of `element` are in the
    /// bloom filter.
    ///
    /// Goes away in release builds.
    pub fn assert_complete(&self, mut element: E) {
        if cfg!(debug_assertions) {
            let mut checked = 0;
            while let Some(parent) = element.traversal_parent() {
                assert_eq!(parent, *(self.elements[self.elements.len() - 1 - checked].element));
                element = parent;
                checked += 1;
            }
            assert_eq!(checked, self.elements.len());
        }
    }

    /// Get the element that represents the chain of things inserted
    /// into the filter right now.  That chain is the given element
    /// (if any) and its ancestors.
    #[inline]
    pub fn current_parent(&self) -> Option<E> {
        self.elements.last().map(|ref el| *el.element)
    }

    /// Insert the parents of an element in the bloom filter, trying to recover
    /// the filter if the last element inserted doesn't match.
    ///
    /// Gets the element depth in the dom, to make it efficient, or if not
    /// provided always rebuilds the filter from scratch.
    ///
    /// Returns the new bloom filter depth, that the traversal code is
    /// responsible to keep around if it wants to get an effective filter.
    pub fn insert_parents_recovering(&mut self,
                                     element: E,
                                     element_depth: usize)
    {
        // Easy case, we're in a different restyle, or we're empty.
        if self.elements.is_empty() {
            self.rebuild(element);
            return;
        }

        let traversal_parent = match element.traversal_parent() {
            Some(parent) => parent,
            None => {
                // Yay, another easy case.
                self.clear();
                return;
            }
        };

        if self.current_parent() == Some(traversal_parent) {
            // Ta da, cache hit, we're all done.
            return;
        }

        if element_depth == 0 {
            self.clear();
            return;
        }

        // We should've early exited above.
        debug_assert!(element_depth != 0,
                      "We should have already cleared the bloom filter");
        debug_assert!(!self.elements.is_empty(),
                      "How! We should've just rebuilt!");

        // Now the fun begins: We have the depth of the dom and the depth of the
        // last element inserted in the filter, let's try to find a common
        // parent.
        //
        // The current depth, that is, the depth of the last element inserted in
        // the bloom filter, is the number of elements _minus one_, that is: if
        // there's one element, it must be the root -> depth zero.
        let mut current_depth = self.elements.len() - 1;

        // If the filter represents an element too deep in the dom, we need to
        // pop ancestors.
        while current_depth > element_depth - 1 {
            self.pop().expect("Emilio is bad at math");
            current_depth -= 1;
        }

        // Now let's try to find a common parent in the bloom filter chain,
        // starting with traversal_parent.
        let mut common_parent = traversal_parent;
        let mut common_parent_depth = element_depth - 1;

        // Let's collect the parents we are going to need to insert once we've
        // found the common one.
        let mut parents_to_insert = SmallVec::<[E; 16]>::new();

        // If the bloom filter still doesn't have enough elements, the common
        // parent is up in the dom.
        while common_parent_depth > current_depth {
            // TODO(emilio): Seems like we could insert parents here, then
            // reverse the slice.
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.traversal_parent().expect("We were lied to");
            common_parent_depth -= 1;
        }

        // Now the two depths are the same.
        debug_assert_eq!(common_parent_depth, current_depth);

        // Happy case: The parents match, we only need to push the ancestors
        // we've collected and we'll never enter in this loop.
        //
        // Not-so-happy case: Parent's don't match, so we need to keep going up
        // until we find a common ancestor.
        //
        // Gecko currently models native anonymous content that conceptually
        // hangs off the document (such as scrollbars) as a separate subtree
        // from the document root.
        //
        // Thus it's possible with Gecko that we do not find any common
        // ancestor.
        while *(self.elements.last().unwrap().element) != common_parent {
            parents_to_insert.push(common_parent);
            self.pop().unwrap();
            common_parent = match common_parent.traversal_parent() {
                Some(parent) => parent,
                None => {
                    debug_assert!(self.elements.is_empty());
                    if cfg!(feature = "gecko") {
                        break;
                    } else {
                        panic!("should have found a common ancestor");
                    }
                }
            }
        }

        // Now the parents match, so insert the stack of elements we have been
        // collecting so far.
        for parent in parents_to_insert.drain().rev() {
            self.push(parent);
        }

        debug_assert_eq!(self.elements.len(), element_depth);

        // We're done! Easy.
    }
}
<commit_msg>style: Minimal cleanup in bloom.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The style bloom filter is used as an optimization when matching deep
//! descendant selectors.

#![deny(missing_docs)]

use atomic_refcell::{AtomicRefMut, AtomicRefCell};
use dom::{SendElement, TElement};
use owning_ref::OwningHandle;
use selectors::bloom::BloomFilter;
use servo_arc::Arc;
use smallvec::SmallVec;

/// Bloom filters are large allocations, so we store them in thread-local storage
/// such that they can be reused across style traversals. StyleBloom is responsible
/// for ensuring that the bloom filter is zeroed when it is dropped.
thread_local!(static BLOOM_KEY: Arc<AtomicRefCell<BloomFilter>> =
              Arc::new(AtomicRefCell::new(BloomFilter::new())));

/// A struct that allows us to fast-reject deep descendant selectors avoiding
/// selector-matching.
///
/// This is implemented using a counting bloom filter, and it's a standard
/// optimization. See Gecko's `AncestorFilter`, and Blink's and WebKit's
/// `SelectorFilter`.
///
/// The constraints for Servo's style system are a bit different compared to
/// traditional style systems given Servo does a parallel breadth-first
/// traversal instead of a sequential depth-first traversal.
///
/// This implies that we need to track a bit more state than other browsers to
/// ensure we're doing the correct thing during the traversal, and being able to
/// apply this optimization effectively.
///
/// Concretely, we have a bloom filter instance per worker thread, and we track
/// the current DOM depth in order to find a common ancestor when it doesn't
/// match the previous element we've styled.
///
/// This is usually a pretty fast operation (we use to be one level deeper than
/// the previous one), but in the case of work-stealing, we may needed to push
/// and pop multiple elements.
///
/// See the `insert_parents_recovering`, where most of the magic happens.
///
/// Regarding thread-safety, this struct is safe because:
///
///  * We clear this after a restyle.
///  * The DOM shape and attributes (and every other thing we access here) are
///    immutable during a restyle.
///
pub struct StyleBloom<E: TElement> {
    /// A handle to the bloom filter from the thread upon which this StyleBloom
    /// was created. We use AtomicRefCell so that this is all |Send|, which allows
    /// StyleBloom to live in ThreadLocalStyleContext, which is dropped from the
    /// parent thread.
    filter: OwningHandle<Arc<AtomicRefCell<BloomFilter>>, AtomicRefMut<'static, BloomFilter>>,

    /// The stack of elements that this bloom filter contains, along with the
    /// number of hashes pushed for each element.
    elements: SmallVec<[PushedElement<E>; 16]>,

    /// Stack of hashes that have been pushed onto this filter.
    pushed_hashes: SmallVec<[u32; 64]>,
}

/// The very rough benchmarks in the selectors crate show clear()
/// costing about 25 times more than remove_hash(). We use this to implement
/// clear() more efficiently when only a small number of hashes have been
/// pushed.
///
/// One subtly to note is that remove_hash() will not touch the value
/// if the filter overflowed. However, overflow can only occur if we
/// get 255 collisions on the same hash value, and 25 < 255.
const MEMSET_CLEAR_THRESHOLD: usize = 25;

struct PushedElement<E: TElement> {
    /// The element that was pushed.
    element: SendElement<E>,

    /// The number of hashes pushed for the element.
    num_hashes: usize,
}

impl<E: TElement> PushedElement<E> {
    fn new(el: E, num_hashes: usize) -> Self {
        PushedElement {
            element: unsafe { SendElement::new(el) },
            num_hashes,
        }
    }
}

fn each_relevant_element_hash<E, F>(element: E, mut f: F)
where
    E: TElement,
    F: FnMut(u32),
{
    f(element.get_local_name().get_hash());
    f(element.get_namespace().get_hash());

    if let Some(id) = element.get_id() {
        f(id.get_hash());
    }

    element.each_class(|class| {
        f(class.get_hash())
    });
}

impl<E: TElement> Drop for StyleBloom<E> {
    fn drop(&mut self) {
        // Leave the reusable bloom filter in a zeroed state.
        self.clear();
    }
}

impl<E: TElement> StyleBloom<E> {
    /// Create an empty `StyleBloom`. Because StyleBloom acquires the thread-
    /// local filter buffer, creating multiple live StyleBloom instances at
    /// the same time on the same thread will panic.
    pub fn new() -> Self {
        let bloom_arc = BLOOM_KEY.with(|b| b.clone());
        let filter = OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
        debug_assert!(filter.is_zeroed(), "Forgot to zero the bloom filter last time");
        StyleBloom {
            filter: filter,
            elements: Default::default(),
            pushed_hashes: Default::default(),
        }
    }

    /// Return the bloom filter used properly by the `selectors` crate.
    pub fn filter(&self) -> &BloomFilter {
        &*self.filter
    }

    /// Push an element to the bloom filter, knowing that it's a child of the
    /// last element parent.
    pub fn push(&mut self, element: E) {
        if cfg!(debug_assertions) {
            if self.elements.is_empty() {
                assert!(element.traversal_parent().is_none());
            }
        }
        self.push_internal(element);
    }

    /// Same as `push`, but without asserting, in order to use it from
    /// `rebuild`.
    fn push_internal(&mut self, element: E) {
        let mut count = 0;
        each_relevant_element_hash(element, |hash| {
            count += 1;
            self.filter.insert_hash(hash);
            self.pushed_hashes.push(hash);
        });
        self.elements.push(PushedElement::new(element, count));
    }

    /// Pop the last element in the bloom filter and return it.
    #[inline]
    fn pop(&mut self) -> Option<E> {
        let (popped_element, num_hashes)  = match self.elements.pop() {
            None => return None,
            Some(x) => (*x.element, x.num_hashes),
        };

        // Verify that the pushed hashes match the ones we'd get from the element.
        let mut expected_hashes = vec![];
        if cfg!(debug_assertions) {
            each_relevant_element_hash(popped_element, |hash| expected_hashes.push(hash));
        }

        for _ in 0..num_hashes {
            let hash = self.pushed_hashes.pop().unwrap();
            debug_assert_eq!(expected_hashes.pop().unwrap(), hash);
            self.filter.remove_hash(hash);
        }

        Some(popped_element)
    }

    /// Returns true if the bloom filter is empty.
    pub fn is_empty(&self) -> bool {
        self.elements.is_empty()
    }

    /// Returns the DOM depth of elements that can be correctly
    /// matched against the bloom filter (that is, the number of
    /// elements in our list).
    pub fn matching_depth(&self) -> usize {
        self.elements.len()
    }

    /// Clears the bloom filter.
    pub fn clear(&mut self) {
        self.elements.clear();

        if self.pushed_hashes.len() > MEMSET_CLEAR_THRESHOLD {
            self.filter.clear();
            self.pushed_hashes.clear();
        } else {
            for hash in self.pushed_hashes.drain() {
                self.filter.remove_hash(hash);
            }
            debug_assert!(self.filter.is_zeroed());
        }
    }

    /// Rebuilds the bloom filter up to the parent of the given element.
    pub fn rebuild(&mut self, mut element: E) {
        self.clear();

        let mut parents_to_insert = SmallVec::<[E; 16]>::new();
        while let Some(parent) = element.traversal_parent() {
            parents_to_insert.push(parent);
            element = parent;
        }

        for parent in parents_to_insert.drain().rev() {
            self.push(parent);
        }
    }

    /// In debug builds, asserts that all the parents of `element` are in the
    /// bloom filter.
    ///
    /// Goes away in release builds.
    pub fn assert_complete(&self, mut element: E) {
        if cfg!(debug_assertions) {
            let mut checked = 0;
            while let Some(parent) = element.traversal_parent() {
                assert_eq!(parent, *(self.elements[self.elements.len() - 1 - checked].element));
                element = parent;
                checked += 1;
            }
            assert_eq!(checked, self.elements.len());
        }
    }

    /// Get the element that represents the chain of things inserted
    /// into the filter right now.  That chain is the given element
    /// (if any) and its ancestors.
    #[inline]
    pub fn current_parent(&self) -> Option<E> {
        self.elements.last().map(|ref el| *el.element)
    }

    /// Insert the parents of an element in the bloom filter, trying to recover
    /// the filter if the last element inserted doesn't match.
    ///
    /// Gets the element depth in the dom, to make it efficient, or if not
    /// provided always rebuilds the filter from scratch.
    ///
    /// Returns the new bloom filter depth, that the traversal code is
    /// responsible to keep around if it wants to get an effective filter.
    pub fn insert_parents_recovering(&mut self,
                                     element: E,
                                     element_depth: usize)
    {
        // Easy case, we're in a different restyle, or we're empty.
        if self.elements.is_empty() {
            self.rebuild(element);
            return;
        }

        let traversal_parent = match element.traversal_parent() {
            Some(parent) => parent,
            None => {
                // Yay, another easy case.
                self.clear();
                return;
            }
        };

        if self.current_parent() == Some(traversal_parent) {
            // Ta da, cache hit, we're all done.
            return;
        }

        if element_depth == 0 {
            self.clear();
            return;
        }

        // We should've early exited above.
        debug_assert!(element_depth != 0,
                      "We should have already cleared the bloom filter");
        debug_assert!(!self.elements.is_empty(),
                      "How! We should've just rebuilt!");

        // Now the fun begins: We have the depth of the dom and the depth of the
        // last element inserted in the filter, let's try to find a common
        // parent.
        //
        // The current depth, that is, the depth of the last element inserted in
        // the bloom filter, is the number of elements _minus one_, that is: if
        // there's one element, it must be the root -> depth zero.
        let mut current_depth = self.elements.len() - 1;

        // If the filter represents an element too deep in the dom, we need to
        // pop ancestors.
        while current_depth > element_depth - 1 {
            self.pop().expect("Emilio is bad at math");
            current_depth -= 1;
        }

        // Now let's try to find a common parent in the bloom filter chain,
        // starting with traversal_parent.
        let mut common_parent = traversal_parent;
        let mut common_parent_depth = element_depth - 1;

        // Let's collect the parents we are going to need to insert once we've
        // found the common one.
        let mut parents_to_insert = SmallVec::<[E; 16]>::new();

        // If the bloom filter still doesn't have enough elements, the common
        // parent is up in the dom.
        while common_parent_depth > current_depth {
            // TODO(emilio): Seems like we could insert parents here, then
            // reverse the slice.
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.traversal_parent().expect("We were lied to");
            common_parent_depth -= 1;
        }

        // Now the two depths are the same.
        debug_assert_eq!(common_parent_depth, current_depth);

        // Happy case: The parents match, we only need to push the ancestors
        // we've collected and we'll never enter in this loop.
        //
        // Not-so-happy case: Parent's don't match, so we need to keep going up
        // until we find a common ancestor.
        //
        // Gecko currently models native anonymous content that conceptually
        // hangs off the document (such as scrollbars) as a separate subtree
        // from the document root.
        //
        // Thus it's possible with Gecko that we do not find any common
        // ancestor.
        while *(self.elements.last().unwrap().element) != common_parent {
            parents_to_insert.push(common_parent);
            self.pop().unwrap();
            common_parent = match common_parent.traversal_parent() {
                Some(parent) => parent,
                None => {
                    debug_assert!(self.elements.is_empty());
                    if cfg!(feature = "gecko") {
                        break;
                    } else {
                        panic!("should have found a common ancestor");
                    }
                }
            }
        }

        // Now the parents match, so insert the stack of elements we have been
        // collecting so far.
        for parent in parents_to_insert.drain().rev() {
            self.push(parent);
        }

        debug_assert_eq!(self.elements.len(), element_depth);

        // We're done! Easy.
    }
}
<|endoftext|>


<commit_before>use entropy::shannon_entropy;
mod entropy;

fn main() {
    println!("{:>2s}:{:>10s} {:s}", "N", "length", "entropy");

    let mut previous = ~"1";
    println!("{:>2i}:{:>10u} {:f}", 1, previous.len(), shannon_entropy(previous));

    let mut next = ~"0";
    println!("{:>2i}:{:>10u} {:f}", 2, next.len(), shannon_entropy(next));

    for i in range(3, 38) {
        let temp = next.clone();
        next.push_str(previous);
        previous = temp;
        println!("{:>2i}:{:>10u} {:.15f}", i, next.len(), shannon_entropy(next));
    }
}<commit_msg>Update fibonacci_word.rs<commit_after>// Implements http://rosettacode.org/wiki/Fibonacci_word

use entropy::shannon_entropy;
mod entropy;

fn main() {
    println!("{:>2s}:{:>10s} {:s}", "N", "length", "entropy");

    let mut previous = ~"1";
    println!("{:>2i}:{:>10u} {:f}", 1, previous.len(), shannon_entropy(previous));

    let mut next = ~"0";
    println!("{:>2i}:{:>10u} {:f}", 2, next.len(), shannon_entropy(next));

    for i in range(3, 38) {
        let temp = next.clone();
        next.push_str(previous);
        previous = temp;
        println!("{:>2i}:{:>10u} {:.15f}", i, next.len(), shannon_entropy(next));
    }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

use protocol::{self, MessageType, Protocol, Type};
use transport::Transport;
use {Result, Error};

use podio::{ReadPodExt, WritePodExt, BigEndian};

static BINARY_PROTOCOL_VERSION_1: u16 = 0x8001;

#[derive(Copy, Clone, Debug)]
pub struct BinaryProtocol;

impl BinaryProtocol {
    fn write_type<T: Transport>(&mut self, transport: &mut T, type_: Type) -> Result<()> {
        self.write_byte(transport, type_ as i8)
    }

    fn read_type<T: Transport>(&mut self, transport: &mut T) -> Result<Type> {
        let raw = try!(self.read_byte(transport));
        match Type::from_num(raw as u64) {
            Some(type_) => Ok(type_),
            None => Err(Error::from(protocol::Error::ProtocolViolation)),
        }
    }
}

impl Protocol for BinaryProtocol {
    fn write_message_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        name: &str,
        message_type: MessageType,
        sequence_id: i32
    ) -> Result<()> {
        let version = ((BINARY_PROTOCOL_VERSION_1 as i32) << 16) | message_type as i32;
        try!(self.write_i32(transport, version));
        try!(self.write_str(transport, name));
        self.write_i32(transport, sequence_id)
    }

    fn write_message_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_struct_begin<T: Transport>(&mut self, _transport: &mut T, _name: &str) -> Result<()> {
        Ok(())
    }

    fn write_struct_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_field_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        _name: &str,
        field_type: Type,
        field_id: i16
    ) -> Result<()> {
        try!(self.write_type(transport, field_type));
        self.write_i16(transport, field_id)
    }

    fn write_field_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_field_stop<T: Transport>(&mut self, transport: &mut T) -> Result<()> {
        self.write_byte(transport, protocol::Type::Stop as i8)
    }

    fn write_map_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        key_type: Type,
        value_type: Type,
        size: usize
    ) -> Result<()> {
        try!(self.write_type(transport, key_type));
        try!(self.write_type(transport, value_type));
        self.write_i32(transport, size as i32)
    }

    fn write_map_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_list_begin<T: Transport>(&mut self, transport: &mut T, elem_type: Type, size: usize) -> Result<()> {
        try!(self.write_type(transport, elem_type));
        self.write_i32(transport, size as i32)
    }

    fn write_list_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_set_begin<T: Transport>(&mut self, transport: &mut T, elem_type: Type, size: usize) -> Result<()> {
        try!(self.write_type(transport, elem_type));
        self.write_i32(transport, size as i32)
    }

    fn write_set_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_bool<T: Transport>(&mut self, transport: &mut T, value: bool) -> Result<()> {
        self.write_byte(transport, value as i8)
    }

    fn write_byte<T: Transport>(&mut self, mut transport: &mut T, value: i8) -> Result<()> {
        Ok(try!(transport.write_i8(value)))
    }

    fn write_i16<T: Transport>(&mut self, mut transport: &mut T, value: i16) -> Result<()> {
        Ok(try!(transport.write_i16::<BigEndian>(value)))
    }

    fn write_i32<T: Transport>(&mut self, mut transport: &mut T, value: i32) -> Result<()> {
        Ok(try!(transport.write_i32::<BigEndian>(value)))
    }

    fn write_i64<T: Transport>(&mut self, mut transport: &mut T, value: i64) -> Result<()> {
        Ok(try!(transport.write_i64::<BigEndian>(value)))
    }

    fn write_double<T: Transport>(&mut self, mut transport: &mut T, value: f64) -> Result<()> {
        Ok(try!(transport.write_f64::<BigEndian>(value)))
    }

    fn write_str<T: Transport>(&mut self, transport: &mut T, value: &str) -> Result<()> {
        self.write_binary(transport, value.as_bytes())
    }

    fn write_string<T: Transport>(&mut self, transport: &mut T, value: &String) -> Result<()> {
        self.write_binary(transport, (&value[..]).as_bytes())
    }

    fn write_binary<T: Transport>(&mut self, transport: &mut T, value: &[u8]) -> Result<()> {
        try!(self.write_i32(transport, value.len() as i32));
        Ok(try!(transport.write_all(value)))
    }

    fn read_message_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(String, MessageType, i32)> {
        let header = try!(self.read_i32(transport));
        let version = (header >> 16) as u16;
        if version != BINARY_PROTOCOL_VERSION_1 {
            return Err(Error::from(protocol::Error::BadVersion));
        };
        let name = try!(self.read_string(transport));
        let raw_type = header & 0xff;
        let message_type = match MessageType::from_num(raw_type as u64) {
            Some(t) => t,
            None => return Err(Error::from(protocol::Error::ProtocolViolation)),
        };
        let sequence_id = try!(self.read_i32(transport));
        Ok((name, message_type, sequence_id))
    }

    fn read_message_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_struct_begin<T: Transport>(&mut self, _transport: &mut T) -> Result<String> {
        Ok(String::new())
    }

    fn read_struct_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_field_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(String, Type, i16)> {
        let field_type = try!(self.read_type(transport));
        let field_id = match field_type {
            protocol::Type::Stop => 0,
            _ => try!(self.read_i16(transport)),
        };
        Ok((String::new(), field_type, field_id))
    }

    fn read_field_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_map_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, Type, i32)> {
        let key_type = try!(self.read_type(transport));
        let value_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((key_type, value_type, size))
    }

    fn read_map_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_list_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, i32)> {
        let elem_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((elem_type, size))
    }

    fn read_list_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_set_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, i32)> {
        let elem_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((elem_type, size))
    }

    fn read_set_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_bool<T: Transport>(&mut self, transport: &mut T) -> Result<bool> {
        match try!(self.read_byte(transport)) {
            0 => Ok(false),
            _ => Ok(true),
        }
    }

    fn read_byte<T: Transport>(&mut self, transport: &mut T) -> Result<i8> {
        Ok(try!(transport.read_i8()))
    }

    fn read_i16<T: Transport>(&mut self, transport: &mut T) -> Result<i16> {
        Ok(try!(transport.read_i16::<BigEndian>()))
    }

    fn read_i32<T: Transport>(&mut self, transport: &mut T) -> Result<i32> {
        Ok(try!(transport.read_i32::<BigEndian>()))
    }

    fn read_i64<T: Transport>(&mut self, transport: &mut T) -> Result<i64> {
        Ok(try!(transport.read_i64::<BigEndian>()))
    }

    fn read_double<T: Transport>(&mut self, transport: &mut T) -> Result<f64> {
        Ok(try!(transport.read_f64::<BigEndian>()))
    }

    fn read_string<T: Transport>(&mut self, transport: &mut T) -> Result<String> {
        let bytes = try!(self.read_binary(transport));
        Ok(try!(String::from_utf8(bytes).map_err(|e| protocol::Error::from(e.utf8_error()))))
    }

    fn read_binary<T: Transport>(&mut self, transport: &mut T) -> Result<Vec<u8>> {
        let len = try!(self.read_i32(transport)) as usize;
        Ok(try!(transport.read_exact(len)))
    }

    fn skip<T: Transport>(&mut self, transport: &mut T, type_: Type) -> Result<()> {
        match type_ {
            Type::Bool => { try!(self.read_bool(transport)); }
            Type::Byte => { try!(self.read_byte(transport)); }
            Type::I16 => { try!(self.read_i16(transport)); }
            Type::I32 => { try!(self.read_i32(transport)); }
            Type::I64 => { try!(self.read_i64(transport)); }
            Type::Double => { try!(self.read_double(transport)); }
            Type::String => { try!(self.read_binary(transport)); }
            Type::Struct => {
                try!(self.read_struct_begin(transport));
                loop {
                    let (_, field_type, _) = try!(self.read_field_begin(transport));
                    if field_type == Type::Stop {
                        break;
                    }
                    try!(self.skip(transport, field_type));
                    try!(self.read_field_end(transport));
                }
                try!(self.read_struct_end(transport));
            }
            Type::Map => {
                let (key_type, value_type, size) = try!(self.read_map_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, key_type));
                    try!(self.skip(transport, value_type));
                }
                try!(self.read_map_end(transport));
            }
            Type::Set => {
                let (elem_type, size) = try!(self.read_set_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, elem_type));
                }
                try!(self.read_set_end(transport));
            }
            Type::List => {
                let (elem_type, size) = try!(self.read_list_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, elem_type));
                }
                try!(self.read_list_end(transport));
            }
            Type::Void => { }
            Type::Stop => { }
        };

        Ok(())
    }
}

#[cfg(test)]
pub mod test;
<commit_msg>Fix for new method on io::Read.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

use protocol::{self, MessageType, Protocol, Type};
use transport::Transport;
use {Result, Error};

use podio::{ReadPodExt, WritePodExt, BigEndian};

static BINARY_PROTOCOL_VERSION_1: u16 = 0x8001;

#[derive(Copy, Clone, Debug)]
pub struct BinaryProtocol;

impl BinaryProtocol {
    fn write_type<T: Transport>(&mut self, transport: &mut T, type_: Type) -> Result<()> {
        self.write_byte(transport, type_ as i8)
    }

    fn read_type<T: Transport>(&mut self, transport: &mut T) -> Result<Type> {
        let raw = try!(self.read_byte(transport));
        match Type::from_num(raw as u64) {
            Some(type_) => Ok(type_),
            None => Err(Error::from(protocol::Error::ProtocolViolation)),
        }
    }
}

impl Protocol for BinaryProtocol {
    fn write_message_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        name: &str,
        message_type: MessageType,
        sequence_id: i32
    ) -> Result<()> {
        let version = ((BINARY_PROTOCOL_VERSION_1 as i32) << 16) | message_type as i32;
        try!(self.write_i32(transport, version));
        try!(self.write_str(transport, name));
        self.write_i32(transport, sequence_id)
    }

    fn write_message_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_struct_begin<T: Transport>(&mut self, _transport: &mut T, _name: &str) -> Result<()> {
        Ok(())
    }

    fn write_struct_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_field_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        _name: &str,
        field_type: Type,
        field_id: i16
    ) -> Result<()> {
        try!(self.write_type(transport, field_type));
        self.write_i16(transport, field_id)
    }

    fn write_field_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_field_stop<T: Transport>(&mut self, transport: &mut T) -> Result<()> {
        self.write_byte(transport, protocol::Type::Stop as i8)
    }

    fn write_map_begin<T: Transport>(
        &mut self,
        transport: &mut T,
        key_type: Type,
        value_type: Type,
        size: usize
    ) -> Result<()> {
        try!(self.write_type(transport, key_type));
        try!(self.write_type(transport, value_type));
        self.write_i32(transport, size as i32)
    }

    fn write_map_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_list_begin<T: Transport>(&mut self, transport: &mut T, elem_type: Type, size: usize) -> Result<()> {
        try!(self.write_type(transport, elem_type));
        self.write_i32(transport, size as i32)
    }

    fn write_list_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_set_begin<T: Transport>(&mut self, transport: &mut T, elem_type: Type, size: usize) -> Result<()> {
        try!(self.write_type(transport, elem_type));
        self.write_i32(transport, size as i32)
    }

    fn write_set_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn write_bool<T: Transport>(&mut self, transport: &mut T, value: bool) -> Result<()> {
        self.write_byte(transport, value as i8)
    }

    fn write_byte<T: Transport>(&mut self, mut transport: &mut T, value: i8) -> Result<()> {
        Ok(try!(transport.write_i8(value)))
    }

    fn write_i16<T: Transport>(&mut self, mut transport: &mut T, value: i16) -> Result<()> {
        Ok(try!(transport.write_i16::<BigEndian>(value)))
    }

    fn write_i32<T: Transport>(&mut self, mut transport: &mut T, value: i32) -> Result<()> {
        Ok(try!(transport.write_i32::<BigEndian>(value)))
    }

    fn write_i64<T: Transport>(&mut self, mut transport: &mut T, value: i64) -> Result<()> {
        Ok(try!(transport.write_i64::<BigEndian>(value)))
    }

    fn write_double<T: Transport>(&mut self, mut transport: &mut T, value: f64) -> Result<()> {
        Ok(try!(transport.write_f64::<BigEndian>(value)))
    }

    fn write_str<T: Transport>(&mut self, transport: &mut T, value: &str) -> Result<()> {
        self.write_binary(transport, value.as_bytes())
    }

    fn write_string<T: Transport>(&mut self, transport: &mut T, value: &String) -> Result<()> {
        self.write_binary(transport, (&value[..]).as_bytes())
    }

    fn write_binary<T: Transport>(&mut self, transport: &mut T, value: &[u8]) -> Result<()> {
        try!(self.write_i32(transport, value.len() as i32));
        Ok(try!(transport.write_all(value)))
    }

    fn read_message_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(String, MessageType, i32)> {
        let header = try!(self.read_i32(transport));
        let version = (header >> 16) as u16;
        if version != BINARY_PROTOCOL_VERSION_1 {
            return Err(Error::from(protocol::Error::BadVersion));
        };
        let name = try!(self.read_string(transport));
        let raw_type = header & 0xff;
        let message_type = match MessageType::from_num(raw_type as u64) {
            Some(t) => t,
            None => return Err(Error::from(protocol::Error::ProtocolViolation)),
        };
        let sequence_id = try!(self.read_i32(transport));
        Ok((name, message_type, sequence_id))
    }

    fn read_message_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_struct_begin<T: Transport>(&mut self, _transport: &mut T) -> Result<String> {
        Ok(String::new())
    }

    fn read_struct_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_field_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(String, Type, i16)> {
        let field_type = try!(self.read_type(transport));
        let field_id = match field_type {
            protocol::Type::Stop => 0,
            _ => try!(self.read_i16(transport)),
        };
        Ok((String::new(), field_type, field_id))
    }

    fn read_field_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_map_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, Type, i32)> {
        let key_type = try!(self.read_type(transport));
        let value_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((key_type, value_type, size))
    }

    fn read_map_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_list_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, i32)> {
        let elem_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((elem_type, size))
    }

    fn read_list_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_set_begin<T: Transport>(&mut self, transport: &mut T) -> Result<(Type, i32)> {
        let elem_type = try!(self.read_type(transport));
        let size = try!(self.read_i32(transport));
        Ok((elem_type, size))
    }

    fn read_set_end<T: Transport>(&mut self, _transport: &mut T) -> Result<()> {
        Ok(())
    }

    fn read_bool<T: Transport>(&mut self, transport: &mut T) -> Result<bool> {
        match try!(self.read_byte(transport)) {
            0 => Ok(false),
            _ => Ok(true),
        }
    }

    fn read_byte<T: Transport>(&mut self, transport: &mut T) -> Result<i8> {
        Ok(try!(transport.read_i8()))
    }

    fn read_i16<T: Transport>(&mut self, transport: &mut T) -> Result<i16> {
        Ok(try!(transport.read_i16::<BigEndian>()))
    }

    fn read_i32<T: Transport>(&mut self, transport: &mut T) -> Result<i32> {
        Ok(try!(transport.read_i32::<BigEndian>()))
    }

    fn read_i64<T: Transport>(&mut self, transport: &mut T) -> Result<i64> {
        Ok(try!(transport.read_i64::<BigEndian>()))
    }

    fn read_double<T: Transport>(&mut self, transport: &mut T) -> Result<f64> {
        Ok(try!(transport.read_f64::<BigEndian>()))
    }

    fn read_string<T: Transport>(&mut self, transport: &mut T) -> Result<String> {
        let bytes = try!(self.read_binary(transport));
        Ok(try!(String::from_utf8(bytes).map_err(|e| protocol::Error::from(e.utf8_error()))))
    }

    fn read_binary<T: Transport>(&mut self, transport: &mut T) -> Result<Vec<u8>> {
        let len = try!(self.read_i32(transport)) as usize;
        Ok(try!(ReadPodExt::read_exact(transport, len)))
    }

    fn skip<T: Transport>(&mut self, transport: &mut T, type_: Type) -> Result<()> {
        match type_ {
            Type::Bool => { try!(self.read_bool(transport)); }
            Type::Byte => { try!(self.read_byte(transport)); }
            Type::I16 => { try!(self.read_i16(transport)); }
            Type::I32 => { try!(self.read_i32(transport)); }
            Type::I64 => { try!(self.read_i64(transport)); }
            Type::Double => { try!(self.read_double(transport)); }
            Type::String => { try!(self.read_binary(transport)); }
            Type::Struct => {
                try!(self.read_struct_begin(transport));
                loop {
                    let (_, field_type, _) = try!(self.read_field_begin(transport));
                    if field_type == Type::Stop {
                        break;
                    }
                    try!(self.skip(transport, field_type));
                    try!(self.read_field_end(transport));
                }
                try!(self.read_struct_end(transport));
            }
            Type::Map => {
                let (key_type, value_type, size) = try!(self.read_map_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, key_type));
                    try!(self.skip(transport, value_type));
                }
                try!(self.read_map_end(transport));
            }
            Type::Set => {
                let (elem_type, size) = try!(self.read_set_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, elem_type));
                }
                try!(self.read_set_end(transport));
            }
            Type::List => {
                let (elem_type, size) = try!(self.read_list_begin(transport));
                for _ in 0..size {
                    try!(self.skip(transport, elem_type));
                }
                try!(self.read_list_end(transport));
            }
            Type::Void => { }
            Type::Stop => { }
        };

        Ok(())
    }
}

#[cfg(test)]
pub mod test;
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

use self::imp::{drop_handler, make_handler};

pub use self::imp::cleanup;
pub use self::imp::init;

pub struct Handler {
    _data: *mut libc::c_void,
}

impl Handler {
    pub unsafe fn new() -> Handler {
        make_handler()
    }

    fn null() -> Handler {
        Handler { _data: crate::ptr::null_mut() }
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            drop_handler(self);
        }
    }
}

#[cfg(any(
    target_os = "linux",
    target_os = "macos",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "netbsd",
    target_os = "openbsd"
))]
mod imp {
    use super::Handler;
    use crate::io;
    use crate::mem;
    use crate::ptr;
    use crate::thread;

    use libc::MAP_FAILED;
    use libc::{mmap, munmap};
    use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
    use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
    use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};

    use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
    use crate::sys::unix::os::page_size;
    use crate::sys_common::thread_info;

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
        #[repr(C)]
        struct siginfo_t {
            a: [libc::c_int; 3], // si_signo, si_errno, si_code
            si_addr: *mut libc::c_void,
        }

        (*(info as *const siginfo_t)).si_addr as usize
    }

    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
        (*info).si_addr as usize
    }

    // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
    // (unmapped pages) at the end of every thread's stack, so if a thread ends
    // up running into the guard page it'll trigger this handler. We want to
    // detect these cases and print out a helpful error saying that the stack
    // has overflowed. All other signals, however, should go back to what they
    // were originally supposed to do.
    //
    // This handler currently exists purely to print an informative message
    // whenever a thread overflows its stack. We then abort to exit and
    // indicate a crash, but to avoid a misleading SIGSEGV that might lead
    // users to believe that unsafe code has accessed an invalid pointer; the
    // SIGSEGV encountered when overflowing the stack is expected and
    // well-defined.
    //
    // If this is not a stack overflow, the handler un-registers itself and
    // then returns (to allow the original signal to be delivered again).
    // Returning from this kind of signal handler is technically not defined
    // to work when reading the POSIX spec strictly, but in practice it turns
    // out many large systems and all implementations allow returning from a
    // signal handler to work. For a more detailed explanation see the
    // comments on #26458.
    unsafe extern "C" fn signal_handler(
        signum: libc::c_int,
        info: *mut libc::siginfo_t,
        _data: *mut libc::c_void,
    ) {
        let guard = thread_info::stack_guard().unwrap_or(0..0);
        let addr = siginfo_si_addr(info);

        // If the faulting address is within the guard page, then we print a
        // message saying so and abort.
        if guard.start <= addr && addr < guard.end {
            rtprintpanic!(
                "\nthread '{}' has overflowed its stack\n",
                thread::current().name().unwrap_or("<unknown>")
            );
            rtabort!("stack overflow");
        } else {
            // Unregister ourselves by reverting back to the default behavior.
            let mut action: sigaction = mem::zeroed();
            action.sa_sigaction = SIG_DFL;
            sigaction(signum, &action, ptr::null_mut());

            // See comment above for why this function returns.
        }
    }

    static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
    static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);

    pub unsafe fn init() {
        let mut action: sigaction = mem::zeroed();
        for &signal in &[SIGSEGV, SIGBUS] {
            sigaction(signal, ptr::null_mut(), &mut action);
            // Configure our signal handler if one is not already set.
            if action.sa_sigaction == SIG_DFL {
                action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                action.sa_sigaction = signal_handler as sighandler_t;
                sigaction(signal, &action, ptr::null_mut());
                NEED_ALTSTACK.store(true, Ordering::Relaxed);
            }
        }

        let handler = make_handler();
        MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed);
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) };
    }

    unsafe fn get_stackp() -> *mut libc::c_void {
        let stackp = mmap(
            ptr::null_mut(),
            SIGSTKSZ + page_size(),
            PROT_READ | PROT_WRITE,
            MAP_PRIVATE | MAP_ANON,
            -1,
            0,
        );
        if stackp == MAP_FAILED {
            panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
        }
        let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
        if guard_result != 0 {
            panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error());
        }
        stackp.add(page_size())
    }

    unsafe fn get_stack() -> libc::stack_t {
        libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
    }

    pub unsafe fn make_handler() -> Handler {
        if !NEED_ALTSTACK.load(Ordering::Relaxed) {
            return Handler::null();
        }
        let mut stack = mem::zeroed();
        sigaltstack(ptr::null(), &mut stack);
        // Configure alternate signal stack, if one is not already set.
        if stack.ss_flags & SS_DISABLE != 0 {
            stack = get_stack();
            sigaltstack(&stack, ptr::null_mut());
            Handler { _data: stack.ss_sp as *mut libc::c_void }
        } else {
            Handler::null()
        }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        if !handler._data.is_null() {
            let stack = libc::stack_t {
                ss_sp: ptr::null_mut(),
                ss_flags: SS_DISABLE,
                // Workaround for bug in macOS implementation of sigaltstack
                // UNIX2003 which returns ENOMEM when disabling a stack while
                // passing ss_size smaller than MINSIGSTKSZ. According to POSIX
                // both ss_sp and ss_size should be ignored in this case.
                ss_size: SIGSTKSZ,
            };
            sigaltstack(&stack, ptr::null_mut());
            // We know from `get_stackp` that the alternate stack we installed is part of a mapping
            // that started one page earlier, so walk back a page and unmap from there.
            munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
        }
    }
}

#[cfg(not(any(
    target_os = "linux",
    target_os = "macos",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "netbsd",
    target_os = "openbsd",
)))]
mod imp {
    pub unsafe fn init() {}

    pub unsafe fn cleanup() {}

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler::null()
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
}
<commit_msg>Rollup merge of #87528 - :stack_overflow_obsd, r=joshtriplett<commit_after>#![cfg_attr(test, allow(dead_code))]

use self::imp::{drop_handler, make_handler};

pub use self::imp::cleanup;
pub use self::imp::init;

pub struct Handler {
    _data: *mut libc::c_void,
}

impl Handler {
    pub unsafe fn new() -> Handler {
        make_handler()
    }

    fn null() -> Handler {
        Handler { _data: crate::ptr::null_mut() }
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            drop_handler(self);
        }
    }
}

#[cfg(any(
    target_os = "linux",
    target_os = "macos",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "netbsd",
    target_os = "openbsd"
))]
mod imp {
    use super::Handler;
    use crate::io;
    use crate::mem;
    use crate::ptr;
    use crate::thread;

    use libc::MAP_FAILED;
    use libc::{mmap, munmap};
    use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
    use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
    use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};

    use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
    use crate::sys::unix::os::page_size;
    use crate::sys_common::thread_info;

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
        #[repr(C)]
        struct siginfo_t {
            a: [libc::c_int; 3], // si_signo, si_errno, si_code
            si_addr: *mut libc::c_void,
        }

        (*(info as *const siginfo_t)).si_addr as usize
    }

    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
        (*info).si_addr as usize
    }

    // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
    // (unmapped pages) at the end of every thread's stack, so if a thread ends
    // up running into the guard page it'll trigger this handler. We want to
    // detect these cases and print out a helpful error saying that the stack
    // has overflowed. All other signals, however, should go back to what they
    // were originally supposed to do.
    //
    // This handler currently exists purely to print an informative message
    // whenever a thread overflows its stack. We then abort to exit and
    // indicate a crash, but to avoid a misleading SIGSEGV that might lead
    // users to believe that unsafe code has accessed an invalid pointer; the
    // SIGSEGV encountered when overflowing the stack is expected and
    // well-defined.
    //
    // If this is not a stack overflow, the handler un-registers itself and
    // then returns (to allow the original signal to be delivered again).
    // Returning from this kind of signal handler is technically not defined
    // to work when reading the POSIX spec strictly, but in practice it turns
    // out many large systems and all implementations allow returning from a
    // signal handler to work. For a more detailed explanation see the
    // comments on #26458.
    unsafe extern "C" fn signal_handler(
        signum: libc::c_int,
        info: *mut libc::siginfo_t,
        _data: *mut libc::c_void,
    ) {
        let guard = thread_info::stack_guard().unwrap_or(0..0);
        let addr = siginfo_si_addr(info);

        // If the faulting address is within the guard page, then we print a
        // message saying so and abort.
        if guard.start <= addr && addr < guard.end {
            rtprintpanic!(
                "\nthread '{}' has overflowed its stack\n",
                thread::current().name().unwrap_or("<unknown>")
            );
            rtabort!("stack overflow");
        } else {
            // Unregister ourselves by reverting back to the default behavior.
            let mut action: sigaction = mem::zeroed();
            action.sa_sigaction = SIG_DFL;
            sigaction(signum, &action, ptr::null_mut());

            // See comment above for why this function returns.
        }
    }

    static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
    static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);

    pub unsafe fn init() {
        let mut action: sigaction = mem::zeroed();
        for &signal in &[SIGSEGV, SIGBUS] {
            sigaction(signal, ptr::null_mut(), &mut action);
            // Configure our signal handler if one is not already set.
            if action.sa_sigaction == SIG_DFL {
                action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                action.sa_sigaction = signal_handler as sighandler_t;
                sigaction(signal, &action, ptr::null_mut());
                NEED_ALTSTACK.store(true, Ordering::Relaxed);
            }
        }

        let handler = make_handler();
        MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed);
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) };
    }

    unsafe fn get_stackp() -> *mut libc::c_void {
        // OpenBSD requires this flag for stack mapping
        // otherwise the said mapping will fail as a no-op on most systems
        // and has a different meaning on FreeBSD
        #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",))]
        let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK;
        #[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))]
        let flags = MAP_PRIVATE | MAP_ANON;
        let stackp =
            mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
        if stackp == MAP_FAILED {
            panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
        }
        let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
        if guard_result != 0 {
            panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error());
        }
        stackp.add(page_size())
    }

    unsafe fn get_stack() -> libc::stack_t {
        libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
    }

    pub unsafe fn make_handler() -> Handler {
        if !NEED_ALTSTACK.load(Ordering::Relaxed) {
            return Handler::null();
        }
        let mut stack = mem::zeroed();
        sigaltstack(ptr::null(), &mut stack);
        // Configure alternate signal stack, if one is not already set.
        if stack.ss_flags & SS_DISABLE != 0 {
            stack = get_stack();
            sigaltstack(&stack, ptr::null_mut());
            Handler { _data: stack.ss_sp as *mut libc::c_void }
        } else {
            Handler::null()
        }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        if !handler._data.is_null() {
            let stack = libc::stack_t {
                ss_sp: ptr::null_mut(),
                ss_flags: SS_DISABLE,
                // Workaround for bug in macOS implementation of sigaltstack
                // UNIX2003 which returns ENOMEM when disabling a stack while
                // passing ss_size smaller than MINSIGSTKSZ. According to POSIX
                // both ss_sp and ss_size should be ignored in this case.
                ss_size: SIGSTKSZ,
            };
            sigaltstack(&stack, ptr::null_mut());
            // We know from `get_stackp` that the alternate stack we installed is part of a mapping
            // that started one page earlier, so walk back a page and unmap from there.
            munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
        }
    }
}

#[cfg(not(any(
    target_os = "linux",
    target_os = "macos",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "netbsd",
    target_os = "openbsd",
)))]
mod imp {
    pub unsafe fn init() {}

    pub unsafe fn cleanup() {}

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler::null()
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
}
<|endoftext|>