<commit_before>use std::net::SocketAddr;
use std::str::FromStr;

use hyper::header;
use hyper::method::Method;

use url::Host;
use url::SchemeData;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

pub struct XForwardedMiddleware;

fn get_one_raw(r: &mut Request, key: &str) -> Option<String> {
    r.headers
        .get_raw(key)
        .and_then(|vals| if vals.len() > 0 { vals.to_owned().pop() } else { None })
        .and_then(|x| String::from_utf8(x).ok())
}

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, r: &mut Request) -> IronResult<()> {
        get_one_raw(r, "X-Forwarded-Host")
            .and_then(|host| Host::parse(&host[..]).ok())
            .map(|x| r.url.host = x);

        get_one_raw(r, "X-Forwarded-Port")
            .and_then(|s| u16::from_str(&s[..]).ok())
            .map(|port| r.url.port = port);

        get_one_raw(r, "X-Forwarded-For")
            .and_then(parse_remote_addrs)
            .map(|ip| r.remote_addr = ip);

        get_one_raw(r, "X-Forwarded-Proto")
            .map(|scheme| r.url.scheme = scheme.to_lowercase());

        Ok(())
    }
}

fn parse_remote_addrs(s: String) -> Option<SocketAddr> {
    let split = s.split(',');
    let mut iter_ips = split.map(|x| x.trim()).filter(|x| x.len() > 0);
    iter_ips.next().and_then(|ip| SocketAddr::from_str(ip).ok())
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        set_cors_headers(&request, &mut response);
        set_frame_options(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        set_cors_headers(&request, &mut error.response);
        set_frame_options(&request, &mut error.response);
        Err(error)
    }
}

/// Required by remoteStorage spec
fn set_cors_headers(rq: &Request, r: &mut Response) {
    match &rq.url.path[0][..] {
        ".well-known" | "storage" => (),
        _ => return
    };

    let origin = match rq.headers.get_raw("Origin") {
        Some(x) => if x.len() == 1 {
            match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                Ok(x) => x,
                Err(_) => return
            }
        } else {
            return;
        },
        None => return
    };

    r.headers.set(header::AccessControlAllowOrigin::Value(origin));
    // FIXME: https://github.com/hyperium/hyper/issues/673
    r.headers.set_raw("Access-Control-Expose-Headers", vec![b"ETag".to_vec()]);
    r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
    r.headers.set(header::AccessControlAllowHeaders(vec![
        UniCase("Authorization".to_owned()),
        UniCase("Content-Type".to_owned()),
        UniCase("Origin".to_owned()),
        UniCase("If-Match".to_owned()),
        UniCase("If-None-Match".to_owned()),
    ]));
}

/// Prevent clickjacking attacks like described in OAuth RFC
/// https://tools.ietf.org/html/rfc6749#section-10.13
fn set_frame_options(rq: &Request, r: &mut Response) {
    match &rq.url.path[0][..] {
        // It's probably fine to embed user storage data into other documents
        "storage" => return,
        _ => ()
    };

    r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    match request.headers.get::<header::IfNoneMatch>() {
        Some(header) => if header.matches_etag(etag) { return false; },
        None => ()
    };

    match request.headers.get::<header::IfMatch>() {
        Some(header) => if !header.matches_etag(etag) { return false; },
        None => ()
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    let url = request.url.clone().into_generic_url();
    let scheme_data = match url.scheme_data {
        SchemeData::Relative(ref x) => x,
        _ => panic!("Expected relative scheme data.")
    };

    let mut rv = format!("{}@{}", user.userid, scheme_data.host);
    if let Some(port) = scheme_data.port {
        if Some(port) != scheme_data.default_port {
            rv.push_str(&format!(":{}", port)[..]);
        }
    };

    rv
}
<commit_msg>Filed #15<commit_after>use std::net::SocketAddr;
use std::str::FromStr;

use hyper::header;
use hyper::method::Method;

use url::Host;
use url::SchemeData;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

pub struct XForwardedMiddleware;

fn get_one_raw(r: &mut Request, key: &str) -> Option<String> {
    r.headers
        .get_raw(key)
        .and_then(|vals| if vals.len() > 0 { vals.to_owned().pop() } else { None })
        .and_then(|x| String::from_utf8(x).ok())
}

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, r: &mut Request) -> IronResult<()> {
        get_one_raw(r, "X-Forwarded-Host")
            .and_then(|host| Host::parse(&host[..]).ok())
            .map(|x| r.url.host = x);

        get_one_raw(r, "X-Forwarded-Port")
            .and_then(|s| u16::from_str(&s[..]).ok())
            .map(|port| r.url.port = port);

        get_one_raw(r, "X-Forwarded-For")
            .and_then(parse_remote_addrs)
            .map(|ip| r.remote_addr = ip);

        get_one_raw(r, "X-Forwarded-Proto")
            .map(|scheme| r.url.scheme = scheme.to_lowercase());

        Ok(())
    }
}

fn parse_remote_addrs(s: String) -> Option<SocketAddr> {
    let split = s.split(',');
    let mut iter_ips = split.map(|x| x.trim()).filter(|x| x.len() > 0);
    iter_ips.next().and_then(|ip| SocketAddr::from_str(ip).ok())
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        set_cors_headers(&request, &mut response);
        set_frame_options(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        set_cors_headers(&request, &mut error.response);
        set_frame_options(&request, &mut error.response);
        Err(error)
    }
}

/// Required by remoteStorage spec
fn set_cors_headers(rq: &Request, r: &mut Response) {
    match &rq.url.path[0][..] {
        ".well-known" | "storage" => (),
        _ => return
    };

    let origin = match rq.headers.get_raw("Origin") {
        Some(x) => if x.len() == 1 {
            match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                Ok(x) => x,
                Err(_) => return
            }
        } else {
            return;
        },
        None => return
    };

    r.headers.set(header::AccessControlAllowOrigin::Value(origin));
    r.headers.set_raw("Access-Control-Expose-Headers", vec![b"ETag".to_vec()]);
    r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
    r.headers.set(header::AccessControlAllowHeaders(vec![
        UniCase("Authorization".to_owned()),
        UniCase("Content-Type".to_owned()),
        UniCase("Origin".to_owned()),
        UniCase("If-Match".to_owned()),
        UniCase("If-None-Match".to_owned()),
    ]));
}

/// Prevent clickjacking attacks like described in OAuth RFC
/// https://tools.ietf.org/html/rfc6749#section-10.13
fn set_frame_options(rq: &Request, r: &mut Response) {
    match &rq.url.path[0][..] {
        // It's probably fine to embed user storage data into other documents
        "storage" => return,
        _ => ()
    };

    r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    match request.headers.get::<header::IfNoneMatch>() {
        Some(header) => if header.matches_etag(etag) { return false; },
        None => ()
    };

    match request.headers.get::<header::IfMatch>() {
        Some(header) => if !header.matches_etag(etag) { return false; },
        None => ()
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    let url = request.url.clone().into_generic_url();
    let scheme_data = match url.scheme_data {
        SchemeData::Relative(ref x) => x,
        _ => panic!("Expected relative scheme data.")
    };

    let mut rv = format!("{}@{}", user.userid, scheme_data.host);
    if let Some(port) = scheme_data.port {
        if Some(port) != scheme_data.default_port {
            rv.push_str(&format!(":{}", port)[..]);
        }
    };

    rv
}
<|endoftext|>


<commit_before>use image_lib;
use image_lib::Pixel as PixelTrait;

use byte_utils::*;
use k_means::{SimpleInput, Input, Output, Grouped};

pub type Pixel = image_lib::Rgba<u8>;

pub trait Color {
    fn new(components: (u8, u8, u8, u8)) -> Self;

    fn as_pixel(self) -> Pixel;

    fn components(&self) -> (u8, u8, u8, u8);
    fn simple_distance_to<T: Color>(&self, other: &T) -> u64 {
        let (r1, g1, b1, a1) = self.components();
        let (r2, g2, b2, a2) = other.components();

        let opaque_distance = ((r1 as i32) - (r2 as i32)).pow(2) +
                              ((g1 as i32) - (g2 as i32)).pow(2) +
                              ((b1 as i32) - (b2 as i32)).pow(2);

        let alpha_distance = ((a1 as i32) - (a2 as i32)).pow(2) * 3;

        ((opaque_distance as u64) * (a1 as u64) * (a2 as u64)) + ((alpha_distance as u64) * 255 * 255)
    }
}

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Rgba8 {
    pub data: Pixel,
}

impl Color for Rgba8 {
    fn new(components: (u8, u8, u8, u8)) -> Rgba8 {
        let (r, g, b, a) = components;
        if a > 0 {
            Rgba8 { data: Pixel { data: [r, g, b, a] } }
        } else {
            Rgba8 { data: Pixel { data: [0, 0, 0, 0] } }
        }
    }

    fn as_pixel(self) -> Pixel {
        self.data
    }

    fn components(&self) -> (u8, u8, u8, u8) {
        self.data.channels4()
    }
}

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Rgb5a3 {
    pub data: Pixel,
}

impl Color for Rgb5a3 {
    fn new(components: (u8, u8, u8, u8)) -> Rgb5a3 {
        let (r, g, b, a) = components;
        let data = match approximate_3_bits(a) {
            0x00 => [0, 0, 0, 0],
            0xFF => [approximate_5_bits(r), approximate_5_bits(g), approximate_5_bits(b), 0xFF],
            new_a => [approximate_4_bits(r), approximate_4_bits(g), approximate_4_bits(b), new_a],
        };
        Rgb5a3 { data: Pixel { data: data } }
    }

    fn as_pixel(self) -> Pixel {
        self.data
    }

    fn components(&self) -> (u8, u8, u8, u8) {
        self.data.channels4()
    }
}

// impl SimpleInput<Rgba8> for Rgba8 {
//     fn distance_to(&self, other: &Rgba8) -> u64 {
//         self.simple_distance_to(other)
//     }

//     fn as_output(&self) -> Rgba8 {
//         *self
//     }
// }

impl<O: Color + Output> SimpleInput<O> for Rgba8 {
    fn distance_to(&self, other: &O) -> u64 {
        let closest_possible_distance = self.simple_distance_to::<O>(&self.as_output());
        self.simple_distance_to(other) - closest_possible_distance
    }

    fn as_output(&self) -> O {
        O::new(self.components())
    }
}

impl<O: Color + Output> Input<O> for Grouped<Rgba8> {
    fn mean_of(grouped_colors: &Vec<&Grouped<Rgba8>>) -> O {
        O::new(mean_of_colors_as_vec(grouped_colors))
    }
}

impl Output for Rgba8 {}
impl Output for Rgb5a3 {}

fn mean_of_colors_as_vec(grouped_colors: &Vec<&Grouped<Rgba8>>) -> (u8, u8, u8, u8) {
    mean_of_colors(grouped_colors.iter().map(|&&group| group))
}

pub fn mean_of_colors<I>(grouped_colors: I) -> (u8, u8, u8, u8)
    where I: Iterator<Item = Grouped<Rgba8>> {
    let mut r_sum = 0;
    let mut g_sum = 0;
    let mut b_sum = 0;
    let mut a_sum = 0;
    let mut total_count = 0;

    for Grouped { data, count } in grouped_colors {
        let (r, g, b, a) = data.components();
        let weighted_a = (a as u32) * count;

        r_sum += (r as u32) * weighted_a;
        g_sum += (g as u32) * weighted_a;
        b_sum += (b as u32) * weighted_a;
        a_sum += weighted_a;
        total_count += count;
    }

    if a_sum > 0 {
        let r = ((r_sum + (a_sum / 2)) / a_sum) as u8;
        let g = ((g_sum + (a_sum / 2)) / a_sum) as u8;
        let b = ((b_sum + (a_sum / 2)) / a_sum) as u8;
        let a = ((a_sum + (total_count / 2)) / total_count) as u8;

        (r, g, b, a)
    } else {
        (0, 0, 0, 0)
    }
}
<commit_msg>Fixed crashes in non-release mode; added diagnostic message to gather info for better fix.<commit_after>use image_lib;
use image_lib::Pixel as PixelTrait;

use byte_utils::*;
use k_means::{SimpleInput, Input, Output, Grouped};

pub type Pixel = image_lib::Rgba<u8>;

pub trait Color {
    fn new(components: (u8, u8, u8, u8)) -> Self;

    fn as_pixel(self) -> Pixel;

    fn components(&self) -> (u8, u8, u8, u8);
    fn simple_distance_to<T: Color>(&self, other: &T) -> u64 {
        let (r1, g1, b1, a1) = self.components();
        let (r2, g2, b2, a2) = other.components();

        let opaque_distance = ((r1 as i32) - (r2 as i32)).pow(2) +
                              ((g1 as i32) - (g2 as i32)).pow(2) +
                              ((b1 as i32) - (b2 as i32)).pow(2);

        let alpha_distance = ((a1 as i32) - (a2 as i32)).pow(2) * 3;

        ((opaque_distance as u64) * (a1 as u64) * (a2 as u64)) + ((alpha_distance as u64) * 255 * 255)
    }
}

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Rgba8 {
    pub data: Pixel,
}

impl Color for Rgba8 {
    fn new(components: (u8, u8, u8, u8)) -> Rgba8 {
        let (r, g, b, a) = components;
        if a > 0 {
            Rgba8 { data: Pixel { data: [r, g, b, a] } }
        } else {
            Rgba8 { data: Pixel { data: [0, 0, 0, 0] } }
        }
    }

    fn as_pixel(self) -> Pixel {
        self.data
    }

    fn components(&self) -> (u8, u8, u8, u8) {
        self.data.channels4()
    }
}

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Rgb5a3 {
    pub data: Pixel,
}

impl Color for Rgb5a3 {
    fn new(components: (u8, u8, u8, u8)) -> Rgb5a3 {
        let (r, g, b, a) = components;
        let data = match approximate_3_bits(a) {
            0x00 => [0, 0, 0, 0],
            0xFF => [approximate_5_bits(r), approximate_5_bits(g), approximate_5_bits(b), 0xFF],
            new_a => [approximate_4_bits(r), approximate_4_bits(g), approximate_4_bits(b), new_a],
        };
        Rgb5a3 { data: Pixel { data: data } }
    }

    fn as_pixel(self) -> Pixel {
        self.data
    }

    fn components(&self) -> (u8, u8, u8, u8) {
        self.data.channels4()
    }
}

// impl SimpleInput<Rgba8> for Rgba8 {
//     fn distance_to(&self, other: &Rgba8) -> u64 {
//         self.simple_distance_to(other)
//     }

//     fn as_output(&self) -> Rgba8 {
//         *self
//     }
// }

impl<O: Color + Output> SimpleInput<O> for Rgba8 {
    fn distance_to(&self, other: &O) -> u64 {
        let closest_possible_distance = self.simple_distance_to::<O>(&self.as_output());
        let distance = self.simple_distance_to(other);

        if distance < closest_possible_distance {
            println!("Distance from {:?} to {:?} is closer than to RGB5A3 version {:?}", self, other, SimpleInput::<O>::as_output(self));
            return 0;
        }

        distance - closest_possible_distance
    }

    fn as_output(&self) -> O {
        O::new(self.components())
    }
}

impl<O: Color + Output> Input<O> for Grouped<Rgba8> {
    fn mean_of(grouped_colors: &Vec<&Grouped<Rgba8>>) -> O {
        O::new(mean_of_colors_as_vec(grouped_colors))
    }
}

impl Output for Rgba8 {}
impl Output for Rgb5a3 {}

fn mean_of_colors_as_vec(grouped_colors: &Vec<&Grouped<Rgba8>>) -> (u8, u8, u8, u8) {
    mean_of_colors(grouped_colors.iter().map(|&&group| group))
}

pub fn mean_of_colors<I>(grouped_colors: I) -> (u8, u8, u8, u8)
    where I: Iterator<Item = Grouped<Rgba8>> {
    let mut r_sum = 0;
    let mut g_sum = 0;
    let mut b_sum = 0;
    let mut a_sum = 0;
    let mut total_count = 0;

    for Grouped { data, count } in grouped_colors {
        let (r, g, b, a) = data.components();
        let weighted_a = (a as u32) * count;

        r_sum += (r as u32) * weighted_a;
        g_sum += (g as u32) * weighted_a;
        b_sum += (b as u32) * weighted_a;
        a_sum += weighted_a;
        total_count += count;
    }

    if a_sum > 0 {
        let r = ((r_sum + (a_sum / 2)) / a_sum) as u8;
        let g = ((g_sum + (a_sum / 2)) / a_sum) as u8;
        let b = ((b_sum + (a_sum / 2)) / a_sum) as u8;
        let a = ((a_sum + (total_count / 2)) / total_count) as u8;

        (r, g, b, a)
    } else {
        (0, 0, 0, 0)
    }
}
<|endoftext|>


<commit_before>//! Error types and conversion functions.
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use rodio::decoder::DecoderError;
use rodio::PlayError;

/// An enum containing all kinds of game framework errors.
#[derive(Debug, Clone)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `winit::event_loop::EventLoopProxy` attempts to
    /// wake up an `winit::event_loop::EventLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to load a resource, such as getting an invalid image file.
    ResourceLoadError(String),
    /// Unable to find a resource; the `Vec` is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(Option<Arc<dyn Error + 'static>>, String),
    /// Something went wrong trying to set or get window properties.
    WindowError(String),
    /// Something went wrong trying to create a window
    WindowCreationError(Arc<glutin::CreationError>),
    /// Something went wrong trying to read from a file
    IOError(Arc<std::io::Error>),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    /// Something went wrong with the `gilrs` gamepad-input library.
    GamepadError(Arc<gilrs::Error>),
    /// Something went wrong with the `lyon` shape-tesselation library.
    LyonError(String),
    /// A custom error type for use by users of ggez.
    /// This lets you handle custom errors that may happen during your game (such as, trying to load a malformed file for a level)
    /// using the same mechanism you handle ggez's other errors.
    ///
    /// Please include an informative message with the error.
    CustomError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            GameError::CustomError(ref s) => write!(f, "Custom error: {}", s),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            GameError::WindowCreationError(ref e) => Some(&**e),
            GameError::IOError(ref e) => Some(&**e),
            GameError::ShaderProgramError(ref e) => Some(e),
            GameError::GamepadError(ref e) => Some(&**e),
            GameError::AudioError(Some(ref e), _) => Some(&**e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(Arc::new(e))
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.to_string());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.to_string());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(Some(Arc::new(e)), errstr)
    }
}

impl From<PlayError> for GameError {
    fn from(e: PlayError) -> GameError {
        let errstr = format!("Audio playing error: {:?}", e);
        GameError::AudioError(Some(Arc::new(e)), errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.to_string());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

impl<T> From<winit::event_loop::EventLoopClosed<T>> for GameError {
    fn from(_: glutin::event_loop::EventLoopClosed<T>) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowCreationError(Arc::new(s))
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    fn from(s: gilrs::Error) -> GameError {
        GameError::GamepadError(Arc::new(s))
    }
}

impl From<lyon::lyon_tessellation::TessellationError> for GameError {
    fn from(s: lyon::lyon_tessellation::TessellationError) -> GameError {
        let errstr = format!(
            "Error while tesselating shape (did you give it an infinity or NaN?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}

impl From<lyon::lyon_tessellation::geometry_builder::GeometryBuilderError> for GameError {
    fn from(s: lyon::lyon_tessellation::geometry_builder::GeometryBuilderError) -> GameError {
        let errstr = format!(
            "Error while building geometry (did you give it too many vertices?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}
<commit_msg>Make `GameError` impl `Send`<commit_after>//! Error types and conversion functions.
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use rodio::decoder::DecoderError;
use rodio::PlayError;

/// An enum containing all kinds of game framework errors.
#[derive(Debug, Clone)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `winit::event_loop::EventLoopProxy` attempts to
    /// wake up an `winit::event_loop::EventLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to load a resource, such as getting an invalid image file.
    ResourceLoadError(String),
    /// Unable to find a resource; the `Vec` is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(Option<Arc<dyn Error + Send + 'static>>, String),
    /// Something went wrong trying to set or get window properties.
    WindowError(String),
    /// Something went wrong trying to create a window
    WindowCreationError(Arc<glutin::CreationError>),
    /// Something went wrong trying to read from a file
    IOError(Arc<std::io::Error>),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    /// Something went wrong with the `gilrs` gamepad-input library.
    GamepadError(Arc<gilrs::Error>),
    /// Something went wrong with the `lyon` shape-tesselation library.
    LyonError(String),
    /// A custom error type for use by users of ggez.
    /// This lets you handle custom errors that may happen during your game (such as, trying to load a malformed file for a level)
    /// using the same mechanism you handle ggez's other errors.
    ///
    /// Please include an informative message with the error.
    CustomError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            GameError::CustomError(ref s) => write!(f, "Custom error: {}", s),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            GameError::WindowCreationError(ref e) => Some(&**e),
            GameError::IOError(ref e) => Some(&**e),
            GameError::ShaderProgramError(ref e) => Some(e),
            GameError::GamepadError(ref e) => Some(&**e),
            GameError::AudioError(Some(ref e), _) => Some(&**e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(Arc::new(e))
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.to_string());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.to_string());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(Some(Arc::new(e)), errstr)
    }
}

impl From<PlayError> for GameError {
    fn from(e: PlayError) -> GameError {
        let errstr = format!("Audio playing error: {:?}", e);
        GameError::AudioError(Some(Arc::new(e)), errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.to_string());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

impl<T> From<winit::event_loop::EventLoopClosed<T>> for GameError {
    fn from(_: glutin::event_loop::EventLoopClosed<T>) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowCreationError(Arc::new(s))
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    fn from(s: gilrs::Error) -> GameError {
        GameError::GamepadError(Arc::new(s))
    }
}

impl From<lyon::lyon_tessellation::TessellationError> for GameError {
    fn from(s: lyon::lyon_tessellation::TessellationError) -> GameError {
        let errstr = format!(
            "Error while tesselating shape (did you give it an infinity or NaN?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}

impl From<lyon::lyon_tessellation::geometry_builder::GeometryBuilderError> for GameError {
    fn from(s: lyon::lyon_tessellation::geometry_builder::GeometryBuilderError) -> GameError {
        let errstr = format!(
            "Error while building geometry (did you give it too many vertices?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}
<|endoftext|>


<commit_before>//! Error types and converters.

use data_encoding::DecodeError;
use std::io;
use std::path::Path;
use thiserror::Error;

use crate::metadata::Role;

/// Error type for all TUF related errors.
#[derive(Error, Debug, PartialEq, Eq)]
pub enum Error {
    /// The metadata had a bad signature.
    #[error("bad signature")]
    BadSignature,

    /// There was a problem encoding or decoding.
    #[error("encoding: {0}")]
    Encoding(String),

    /// Metadata was expired.
    #[error("expired {0} metadata")]
    ExpiredMetadata(Role),

    /// An illegal argument was passed into a function.
    #[error("illegal argument: {0}")]
    IllegalArgument(String),

    /// Generic error for HTTP connections.
    #[error("http: {0}")]
    Http(String),

    /// Errors that can occur parsing HTTP streams.
    #[error("hyper: {0}")]
    Hyper(String),

    /// The metadata was missing, so an operation could not be completed.
    #[error("missing {0} metadata")]
    MissingMetadata(Role),

    /// There were no available hash algorithms.
    #[error("no supported hash algorithm")]
    NoSupportedHashAlgorithm,

    /// The metadata or target was not found.
    #[error("not found")]
    NotFound,

    /// Opaque error type, to be interpreted similar to HTTP 500. Something went wrong, and you may
    /// or may not be able to do anything about it.
    #[error("opaque: {0}")]
    Opaque(String),

    /// There was a library internal error. These errors are *ALWAYS* bugs and should be reported.
    #[error("programming: {0}")]
    Programming(String),

    /// The target is unavailable. This may mean it is either not in the metadata or the metadata
    /// chain to the target cannot be fully verified.
    #[error("target unavailable")]
    TargetUnavailable,

    /// There is no known or available hash algorithm.
    #[error("unknown hash algorithm: {0}")]
    UnknownHashAlgorithm(String),

    /// There is no known or available key type.
    #[error("unknown key type: {0}")]
    UnknownKeyType(String),

    /// The metadata or target failed to verify.
    #[error("verification failure: {0}")]
    VerificationFailure(String),
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Error {
        Error::Encoding(format!("JSON: {:?}", err))
    }
}

impl Error {
    /// Helper to include the path that causd the error for FS I/O errors.
    pub fn from_io(err: &io::Error, path: &Path) -> Error {
        Error::Opaque(format!("Path {:?} : {:?}", path, err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        match err.kind() {
            std::io::ErrorKind::NotFound => Error::NotFound,
            _ => Error::Opaque(format!("IO: {:?}", err)),
        }
    }
}

impl From<http::Error> for Error {
    fn from(err: http::Error) -> Error {
        Error::Http(format!("Http: {:?}", err))
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Error {
        Error::Hyper(format!("Hyper: {:?}", err))
    }
}

impl From<DecodeError> for Error {
    fn from(err: DecodeError) -> Error {
        Error::Encoding(format!("{:?}", err))
    }
}

impl From<derp::Error> for Error {
    fn from(err: derp::Error) -> Error {
        Error::Encoding(format!("DER: {:?}", err))
    }
}

impl From<tempfile::PersistError> for Error {
    fn from(err: tempfile::PersistError) -> Error {
        Error::Opaque(format!("Error persisting temp file: {:?}", err))
    }
}

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

    #[test]
    fn verify_io_error_display_string() {
        let err = Error::from(io::Error::from(std::io::ErrorKind::NotFound));
        assert_eq!(err.to_string(), "not found");
        assert_eq!(Error::NotFound.to_string(), "not found");

        let err = Error::from(io::Error::from(std::io::ErrorKind::PermissionDenied));
        assert_eq!(err.to_string(), "opaque: IO: Kind(PermissionDenied)");
    }
}
<commit_msg>propagating errors<commit_after>//! Error types and converters.

use data_encoding::DecodeError;
use std::io;
use std::path::Path;
use thiserror::Error;

use crate::metadata::Role;

/// Error type for all TUF related errors.
#[non_exhaustive]
#[derive(Error, Debug, PartialEq, Eq)]
pub enum Error {
    /// The metadata had a bad signature.
    #[error("bad signature")]
    BadSignature,

    /// There was a problem encoding or decoding.
    #[error("encoding: {0}")]
    Encoding(String),

    /// Metadata was expired.
    #[error("expired {0} metadata")]
    ExpiredMetadata(Role),

    /// An illegal argument was passed into a function.
    #[error("illegal argument: {0}")]
    IllegalArgument(String),

    /// Generic error for HTTP connections.
    #[error("http: {0}")]
    Http(http::Error),

    /// Errors that can occur parsing HTTP streams.
    #[error("hyper: {0}")]
    Hyper(hyper::Error),

    /// The metadata was missing, so an operation could not be completed.
    #[error("missing {0} metadata")]
    MissingMetadata(Role),

    /// There were no available hash algorithms.
    #[error("no supported hash algorithm")]
    NoSupportedHashAlgorithm,

    /// The metadata or target was not found.
    #[error("not found")]
    NotFound,

    /// Opaque error type, to be interpreted similar to HTTP 500. Something went wrong, and you may
    /// or may not be able to do anything about it.
    #[error("opaque: {0}")]
    Opaque(String),

    /// There was a library internal error. These errors are *ALWAYS* bugs and should be reported.
    #[error("programming: {0}")]
    Programming(String),

    /// The target is unavailable. This may mean it is either not in the metadata or the metadata
    /// chain to the target cannot be fully verified.
    #[error("target unavailable")]
    TargetUnavailable,

    /// There is no known or available key type.
    #[error("unknown key type: {0}")]
    UnknownKeyType(String),

    /// The metadata or target failed to verify.
    #[error("verification failure: {0}")]
    VerificationFailure(String),
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Error {
        Error::Encoding(format!("JSON: {:?}", err))
    }
}

impl Error {
    /// Helper to include the path that causd the error for FS I/O errors.
    pub fn from_io(err: &io::Error, path: &Path) -> Error {
        Error::Opaque(format!("Path {:?} : {:?}", path, err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        match err.kind() {
            std::io::ErrorKind::NotFound => Error::NotFound,
            _ => Error::Opaque(format!("IO: {:?}", err)),
        }
    }
}

impl From<http::Error> for Error {
    fn from(err: http::Error) -> Error {
        Error::Http(err)
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Error {
        Error::Hyper(err)
    }
}

impl From<DecodeError> for Error {
    fn from(err: DecodeError) -> Error {
        Error::Encoding(format!("{:?}", err))
    }
}

impl From<derp::Error> for Error {
    fn from(err: derp::Error) -> Error {
        Error::Encoding(format!("DER: {:?}", err))
    }
}

impl From<tempfile::PersistError> for Error {
    fn from(err: tempfile::PersistError) -> Error {
        Error::Opaque(format!("Error persisting temp file: {:?}", err))
    }
}

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

    #[test]
    fn verify_io_error_display_string() {
        let err = Error::from(io::Error::from(std::io::ErrorKind::NotFound));
        assert_eq!(err.to_string(), "not found");
        assert_eq!(Error::NotFound.to_string(), "not found");

        let err = Error::from(io::Error::from(std::io::ErrorKind::PermissionDenied));
        assert_eq!(err.to_string(), "opaque: IO: Kind(PermissionDenied)");
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::result;
use std::error::Error;
use std::io;

use crate::prelude::*;

#[derive(Debug)]
pub enum BertError {
    // io errors
    IoError(io::Error),

    // parsing errors
    InvalidMagicNumber { offset: usize, actual: u8 },
    InvalidTag(usize, u8),
    InvalidFloat(usize),
    InvalidUTF8Atom(usize),
    InvalidLatin1Atom(usize),
    VarintTooLarge(usize),
    NotEnoughData { offset: usize, needed: usize, available: usize },
    InvalidDiskLogMagic { offset: usize, actual: u32 },
    InvalidDiskLogTermMagic { offset: usize, actual: u32 },
    InvalidDiskLogOpenedStatus { offset: usize, actual: u32 },
}

impl BertError {
    fn offset(&self) -> Option<usize> {
        use self::BertError::*;
        match *self {
            InvalidMagicNumber { offset, .. }
            | InvalidTag(offset, _)
            | InvalidFloat(offset)
            | InvalidUTF8Atom(offset)
            | InvalidLatin1Atom(offset)
            | VarintTooLarge(offset)
            | InvalidDiskLogMagic { offset, .. }
            | InvalidDiskLogTermMagic { offset, .. }
            | InvalidDiskLogOpenedStatus { offset, .. }
            | NotEnoughData { offset, .. } => Some(offset),
            _ => None
        }
    }

    fn extra_info(&self) -> Option<String> {
        use self::BertError::*;
        match *self {
            InvalidTag(_, tag) => Some(format!("{}", tag)),
            InvalidMagicNumber { actual, .. } =>
                Some(format!("expected 0x{:02x}, found 0x{:02x}", BERT_MAGIC_NUMBER, actual)),
            InvalidDiskLogMagic { actual, .. } =>
                Some(format!("expected 0x{:08x}, found 0x{:08x}", DISK_LOG_MAGIC, actual)),
            InvalidDiskLogTermMagic { actual, .. } =>
                Some(format!("expected 0x{:08x}, found 0x{:08x}", DISK_LOG_TERM_MAGIC, actual)),
            InvalidDiskLogOpenedStatus { actual, .. } =>
                Some(format!("expected 0x{:08x}, found 0x{:08x}", DISK_LOG_OPENED, actual)),
            NotEnoughData { needed, available, .. } =>
                Some(format!("bytes needed: {}; bytes available: {}", needed, available)),
            _ => None
        }
    }
}

impl fmt::Display for BertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::BertError::*;
        match *self {
            IoError(ref io_err) => write!(f, "{}", io_err)?,
            InvalidMagicNumber { .. } => write!(f, "invalid magic number")?,
            InvalidTag(_, _) => write!(f, "invalid tag")?,
            InvalidFloat(_) => write!(f, "invalid float")?,
            InvalidUTF8Atom(_) => write!(f, "UTF-8 atom is not correctly encoded")?,
            InvalidLatin1Atom(_) => write!(f, "Latin-1 atom is not correctly encoded")?,
            VarintTooLarge(_) => write!(f, "varint is too large (greater than 2^64-1)")?,
            NotEnoughData { .. } => write!(f, "no enough data available")?,
            InvalidDiskLogMagic { .. } => write!(f, "invalid disk_log magic")?,
            InvalidDiskLogTermMagic { .. } => write!(f, "invalid file disk_log term magic")?,
            InvalidDiskLogOpenedStatus { .. } => write!(f, "invalid file opened status")?,
        }

        match self.offset() {
            Some(offset) => write!(f, " at offset {}", offset)?,
            None => (),
        }
        match self.extra_info() {
            Some(ref s) => write!(f, ": {}", s),
            None => Ok(()),
        }
    }
}

impl Error for BertError {}

pub type Result<T> = result::Result<T, BertError>;

impl From<io::Error> for BertError {
    fn from(io_err: io::Error) -> BertError {
        BertError::IoError(io_err)
    }
}
<commit_msg>Simplify error messages<commit_after>use std::fmt;
use std::result;
use std::error::Error;
use std::io;

use crate::prelude::*;

#[derive(Debug)]
pub enum BertError {
    // io errors
    IoError(io::Error),

    // parsing errors
    InvalidMagicNumber { offset: usize, actual: u8 },
    InvalidTag(usize, u8),
    InvalidFloat(usize),
    InvalidUTF8Atom(usize),
    InvalidLatin1Atom(usize),
    VarintTooLarge(usize),
    NotEnoughData { offset: usize, needed: usize, available: usize },
    InvalidDiskLogMagic { offset: usize, actual: u32 },
    InvalidDiskLogTermMagic { offset: usize, actual: u32 },
    InvalidDiskLogOpenedStatus { offset: usize, actual: u32 },
}

impl fmt::Display for BertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::BertError::*;
        match *self {
            IoError(ref io_err) =>
                write!(f, "{}", io_err),
            InvalidMagicNumber { offset, actual } =>
                write!(f, "invalid magic number at offset {}: expected 0x{:02x}, found 0x{:02x}",
                       offset, BERT_MAGIC_NUMBER, actual),
            InvalidTag(offset, byte) =>
                write!(f, "invalid tag at offset {}: 0x{:02x}", offset, byte),
            InvalidFloat(offset) =>
                write!(f, "invalid float at offset {}", offset),
            InvalidUTF8Atom(offset) =>
                write!(f, "UTF-8 atom is not correctly encoded at offset {}", offset),
            InvalidLatin1Atom(offset) =>
                write!(f, "Latin-1 atom is not correctly encoded at offset {}", offset),
            VarintTooLarge(offset) =>
                write!(f, "varint is too large (greater than 2^64-1) at offset {}", offset),
            NotEnoughData { needed, available, offset } =>
                write!(f, "no enough data available at offset {}: needed {} bytes, only {} remaining",
                       offset, needed, available),
            InvalidDiskLogMagic { offset, actual } =>
                write!(f, "invalid disk_log magic at {}: expected 0x{:08x}, found 0x{:08x}",
                       offset, DISK_LOG_MAGIC, actual),
            InvalidDiskLogTermMagic { offset, actual } =>
                write!(f, "invalid disk_log term magic at offset {}: expected 0x{:08x}, found 0x{:08x}",
                       offset, DISK_LOG_TERM_MAGIC, actual),
            InvalidDiskLogOpenedStatus { offset, actual } =>
                write!(f, "invalid disk_log opened status at offset {}: expected 0x{:08x}, found 0x{:08x}",
                       offset, DISK_LOG_OPENED, actual),
        }
    }
}

impl Error for BertError {}

pub type Result<T> = result::Result<T, BertError>;

impl From<io::Error> for BertError {
    fn from(io_err: io::Error) -> BertError {
        BertError::IoError(io_err)
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ffi::CStr;
use super::ErrorType;
use sys;

/// A container for holding any error code.
#[derive(Debug)]
pub struct SBError {
    /// The underlying raw `SBErrorRef`.
    pub raw: sys::SBErrorRef,
}

impl SBError {
    /// Construct a new `SBError`.
    pub fn wrap(raw: sys::SBErrorRef) -> SBError {
        SBError { raw: raw }
    }

    /// Construct a new `Some(SBError)` or `None`.
    pub fn maybe_wrap(raw: sys::SBErrorRef) -> Option<SBError> {
        if unsafe { sys::SBErrorIsValid(raw) != 0 } {
            Some(SBError { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBError` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBErrorIsValid(self.raw) != 0 }
    }

    /// Any textual error message associated with the error.
    pub fn error_string(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBErrorGetCString(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Does this error represent a failure?
    pub fn is_failure(&self) -> bool {
        unsafe { sys::SBErrorFail(self.raw) != 0 }
    }

    /// Does this error represent a success?
    pub fn is_success(&self) -> bool {
        unsafe { sys::SBErrorSuccess(self.raw) != 0 }
    }

    /// The underlying error code. Must be interpreted in conjunction
    /// with the error type.
    pub fn error(&self) -> u32 {
        unsafe { sys::SBErrorGetError(self.raw) }
    }

    /// What type of error is this?
    pub fn error_type(&self) -> ErrorType {
        unsafe { sys::SBErrorGetType(self.raw) }
    }
}

impl Drop for SBError {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBError(self.raw) };
    }
}
<commit_msg>Allow constructing a fresh SBError.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ffi::CStr;
use super::ErrorType;
use sys;

/// A container for holding any error code.
#[derive(Debug)]
pub struct SBError {
    /// The underlying raw `SBErrorRef`.
    pub raw: sys::SBErrorRef,
}

impl SBError {
    /// Construct a new `SBError`.
    pub fn new() -> SBError {
        SBError::wrap(unsafe { sys::CreateSBError() })
    }

    /// Construct a new `SBError`.
    pub fn wrap(raw: sys::SBErrorRef) -> SBError {
        SBError { raw: raw }
    }

    /// Construct a new `Some(SBError)` or `None`.
    pub fn maybe_wrap(raw: sys::SBErrorRef) -> Option<SBError> {
        if unsafe { sys::SBErrorIsValid(raw) != 0 } {
            Some(SBError { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBError` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBErrorIsValid(self.raw) != 0 }
    }

    /// Any textual error message associated with the error.
    pub fn error_string(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBErrorGetCString(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Does this error represent a failure?
    pub fn is_failure(&self) -> bool {
        unsafe { sys::SBErrorFail(self.raw) != 0 }
    }

    /// Does this error represent a success?
    pub fn is_success(&self) -> bool {
        unsafe { sys::SBErrorSuccess(self.raw) != 0 }
    }

    /// The underlying error code. Must be interpreted in conjunction
    /// with the error type.
    pub fn error(&self) -> u32 {
        unsafe { sys::SBErrorGetError(self.raw) }
    }

    /// What type of error is this?
    pub fn error_type(&self) -> ErrorType {
        unsafe { sys::SBErrorGetType(self.raw) }
    }
}

impl Default for SBError {
    fn default() -> SBError {
        SBError::new()
    }
}

impl Drop for SBError {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBError(self.raw) };
    }
}
<|endoftext|>


<commit_before>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

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

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[allow(dead_code)]
    fn assert_error_autotraits()
    where
        Error: Unpin + Send + Sync + 'static,
    {
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<commit_msg>Recommend RUST_LIB_BACKTRACE=1 variable<commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

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

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[allow(dead_code)]
    fn assert_error_autotraits()
    where
        Error: Unpin + Send + Sync + 'static,
    {
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::index_data::{IndexDatum};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<commit_msg>Add `IndexBuffer.buffer()` and `IndexBuffer.buffer_mut()`<commit_after>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::index_data::{IndexDatum};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<|endoftext|>


<commit_before>fn Make() -> Vec<String> {
    vec![
        "aa".to_owned(),
        "dd".to_owned(),
        "cc".to_owned(),
        "Hello".to_owned(),
        "World".to_owned(),
    ]
}

pub fn run() {
    println!("********* vec<String> examples *********");

    let mut v = Make();
    println!("v: {:?}", &v);

    v.sort();
    println!("v after sorting: {:?}", &v);

    let r = v.join(",");
    println!("r after join(): {:?}", &r);

    {
        let r = &mut v[0];
        r.push_str(" Phil!");
    }

    println!("v after changing the first String: {:?}", &v);

    // Convert to another form.
    let v2 : Vec<&str> = v.iter().map(|elem| elem.as_str()).collect();

    let mut v = Make();
    for s in v.iter_mut() {
        s.insert_str(0, "PREFIX ");
    }
    println!("v after prefixing: {:?}", &v);

    // Title algorithm from qork.
    let v = vec![
        "alpha".to_owned(),
        "new".to_owned(),
        "beta".to_owned(),
        "new 1".to_owned(),
        "new whatever".to_owned(),
        "new 3".to_owned(),
    ];

    let proposed = "new";
    let mut titles = v.iter()
        .filter(|s| s.starts_with(&proposed))
        .map(|s| s.as_str())
        .collect::<Vec<_>>();

    let s = get_unique_title(&proposed, &titles);
    println!("s = {:?}", &s);

    let mut v2 = v.iter().map(|s| s.as_str());
    let s = get_unique_title_for_iterator(&proposed, &mut v2);
    println!("s = {:?}", &s);
}

fn get_unique_title(proposed: &str, existing_titles: &[&str]) -> String {
    if !existing_titles.contains(&proposed) {
        return proposed.to_string()
    }

    let mut i = 1;
    loop {
        let proposed = format!("{} {}", &proposed, i);
        if !existing_titles.contains(&proposed.as_str()) {
            return proposed;
        }

        i += 1;
    }
}

// How to write a function that takes an iterator and call it with an iterator,
// a slice, or a vector?
fn get_unique_title_for_iterator<'a, I>(proposed: &str, existing_titles: &mut I) -> String
    where I: Iterator<Item=&'a str> {

    if existing_titles.find(|elem| elem == &proposed).is_none() {
        return proposed.to_string()
    }

    let mut i = 1;
    loop {
        let proposed = format!("{} {}", &proposed, i);
        if existing_titles.find(|elem| elem == &proposed).is_none() {
            return proposed;
        }

        i += 1;
    }
}
<commit_msg>Rust: add a string function that can take a Vec<String> or Vec<str>.<commit_after>fn Make() -> Vec<String> {
    vec![
        "aa".to_owned(),
        "dd".to_owned(),
        "cc".to_owned(),
        "Hello".to_owned(),
        "World".to_owned(),
    ]
}

pub fn run() {
    println!("********* vec<String> examples *********");

    let mut v = Make();
    println!("v: {:?}", &v);

    v.sort();
    println!("v after sorting: {:?}", &v);

    let r = v.join(",");
    println!("r after join(): {:?}", &r);

    {
        let r = &mut v[0];
        r.push_str(" Phil!");
    }

    println!("v after changing the first String: {:?}", &v);

    // Convert to another form.
    let v2 : Vec<&str> = v.iter().map(|elem| elem.as_str()).collect();

    let mut v = Make();
    for s in v.iter_mut() {
        s.insert_str(0, "PREFIX ");
    }
    println!("v after prefixing: {:?}", &v);

    // Title algorithm from qork.
    let v = vec![
        "alpha".to_owned(),
        "new".to_owned(),
        "beta".to_owned(),
        "new 1".to_owned(),
        "new whatever".to_owned(),
        "new 3".to_owned(),
    ];

    let proposed = "new";
    let mut titles = v.iter()
        .filter(|s| s.starts_with(&proposed))
        .map(|s| s.as_str())
        .collect::<Vec<_>>();

    let s = get_unique_title(&proposed, &titles);
    println!("s = {:?}", &s);

    let mut v2 = v.iter().map(|s| s.as_str());
    let s = get_unique_title_for_iterator(&proposed, &mut v2);
    println!("s = {:?}", &s);
}

// Solution taking a vector of &str.
fn get_unique_title(proposed: &str, existing_titles: &[&str]) -> String {
    if !existing_titles.contains(&proposed) {
        return proposed.to_string()
    }

    let mut i = 1;
    loop {
        let prop2 = format!("{} {}", &proposed, i);
        if !existing_titles.contains(&prop2.as_str()) {
            return prop2;
        }

        i += 1;
    }
}

// Solution taking an iterator that yields &strs.
fn get_unique_title_for_iterator<'a, I>(proposed: &str, existing_titles: &mut I) -> String
    where I: Iterator<Item=&'a str> {

    if existing_titles.find(|elem| elem == &proposed).is_none() {
        return proposed.to_string()
    }

    let mut i = 1;
    loop {
        let prop2 = format!("{} {}", &proposed, i);
        if existing_titles.find(|elem| elem == &prop2).is_none() {
            return prop2;
        }

        i += 1;
    }
}

/*
// Aim for a solution that can be called with a Vec<String> or a Vec<str>. Doesn't work yet.
fn get_unique_title2<T: AsRef<str>>(proposed: T, existing_titles: &[T]) -> String
    where T: PartialEq
{
    if !existing_titles.contains(&proposed) {
        return proposed.as_ref().to_string()
    }

    let mut i = 1;
    loop {
        let prop2 = format!("{} {}", proposed.as_ref(), i);
        if !existing_titles.contains(&prop2.as_str()) {
            return prop2;
        }

        i += 1;
    }
}
*/
<|endoftext|>