<commit_before>use std::io;
use std::io::prelude::*;
use std::result;
use crypto::digest::Digest;
use crypto::sha2::Sha512;
use crypto::aes;
use crypto::blockmodes;
use crypto::symmetriccipher::SymmetricCipherError;
use crypto::buffer::{ReadBuffer, WriteBuffer, BufferResult, RefReadBuffer, RefWriteBuffer};

use patch_file::CryptFileMetadata;
use constants::{PATCH_SALT_ITG2, DECRYPT_MAGIC_ITG2};

pub fn derive_aes_key(metadata: &CryptFileMetadata,
                      output: &mut [u8; 24]) {
    let mut sh = Sha512::new();
    sh.input(&metadata.subkey);
    sh.input(&PATCH_SALT_ITG2);
    {
        let mut ws = [0u8; 64];
        sh.result(&mut ws);
        output.copy_from_slice(&ws[0..24]);
    }
}

pub fn verify_crypt_metadata(metadata: &CryptFileMetadata,
                             aes_key: &[u8; 24])
                            -> result::Result<bool, &'static str> {
    let mut decryptor = aes::ecb_decryptor(
            aes::KeySize::KeySize192,
            &aes_key[..],
            blockmodes::NoPadding);
    let mut dec_block = [0u8; 16];
    let mut verify_block = RefReadBuffer::new(&metadata.verify_block[..]);
    let mut dec_buf = RefWriteBuffer::new(&mut dec_block[..]);
    let res = decryptor.decrypt(&mut verify_block,
                                &mut dec_buf,
                                true)
        .map(|r: BufferResult| {
            r
        })
        .map_err(|_: SymmetricCipherError| {
            "Decrypt error"
        })
        .and_then(|_: BufferResult| {
            let mut dreadbuf = dec_buf.take_read_buffer();
            let dmagic = dreadbuf.take_remaining();
            print!("dmagic: ");
            let dmagic_iter = dmagic.into_iter();
            for x in dmagic_iter {
                print!("{0:x} ", x);
            }
            println!("");
            Ok(dmagic[0..2] == DECRYPT_MAGIC_ITG2[0..2])
        });
    res
}

pub fn decrypt_file<T: Read, U: Write>(metadata: &CryptFileMetadata,
                                       aes_key: &[u8; 24],
                                       src: &mut T,
                                       dst: &mut U)
                                      -> io::Result<u32> {
    Ok(metadata.file_size)
}
<commit_msg>sorta implement decrypt_file<commit_after>use std::io;
use std::io::prelude::*;
use std::result;
use std::cmp;
use crypto::digest::Digest;
use crypto::sha2::Sha512;
use crypto::aes;
use crypto::blockmodes;
use crypto::symmetriccipher::SymmetricCipherError;
use crypto::buffer::{ReadBuffer, WriteBuffer, BufferResult, RefReadBuffer, RefWriteBuffer};

use patch_file::CryptFileMetadata;
use constants::{PATCH_SALT_ITG2, DECRYPT_MAGIC_ITG2};

pub fn derive_aes_key(metadata: &CryptFileMetadata,
                      output: &mut [u8; 24]) {
    let mut sh = Sha512::new();
    sh.input(&metadata.subkey);
    sh.input(&PATCH_SALT_ITG2);
    {
        let mut ws = [0u8; 64];
        sh.result(&mut ws);
        output.copy_from_slice(&ws[0..24]);
    }
}

pub fn verify_crypt_metadata(metadata: &CryptFileMetadata,
                             aes_key: &[u8; 24])
                            -> result::Result<bool, &'static str> {
    let mut decryptor = aes::ecb_decryptor(
            aes::KeySize::KeySize192,
            &aes_key[..],
            blockmodes::NoPadding);
    let mut dec_block = [0u8; 16];
    let mut verify_block = RefReadBuffer::new(&metadata.verify_block[..]);
    let mut dec_buf = RefWriteBuffer::new(&mut dec_block[..]);
    let res = decryptor.decrypt(&mut verify_block,
                                &mut dec_buf,
                                true)
        .map(|r: BufferResult| {
            r
        })
        .map_err(|_: SymmetricCipherError| {
            "Cipher error during verification"
        })
        .and_then(|_: BufferResult| {
            let mut dreadbuf = dec_buf.take_read_buffer();
            let dmagic = dreadbuf.take_remaining();
            print!("dmagic: ");
            let dmagic_iter = dmagic.into_iter();
            for x in dmagic_iter {
                print!("{0:x} ", x);
            }
            println!("");
            Ok(dmagic[0..2] == DECRYPT_MAGIC_ITG2[0..2])
        });
    res
}

pub fn decrypt_file<T: Read, U: Write>(metadata: &CryptFileMetadata,
                                       aes_key: &[u8; 24],
                                       src: &mut T,
                                       dst: &mut U)
                                      -> Result<usize, &'static str> {
    let mut decryptor = aes::ecb_decryptor(
            aes::KeySize::KeySize192,
            &aes_key[..],
            blockmodes::NoPadding);
    let mut prev_block = [0u8; 16];
    let mut cur_block = [0u8; 16];
    let mut cur_cipher = [0u8; 16];
    let mut cur_buf = RefWriteBuffer::new(&mut cur_block);
    let mut total_bytes: usize = 0;
    let mut last_read_count: usize = 0;
    let mut bytes_written: usize = 0;

    /*
     * Decrypt in blocks of 16 bytes.
     * XOR the current decrypted block with the previous block.
     * Null out the previous block every 4080 bytes.
     */
    loop {
        try!(src.read(&mut cur_cipher)
            .or_else(|err: io::Error| {
                Err("I/O error during read")
            })
            .and_then(|read_count: usize| {
                last_read_count = read_count;
                total_bytes += read_count;
                let mut cipher_buf = RefReadBuffer::new(&mut cur_cipher);
                decryptor.decrypt(&mut cipher_buf, &mut cur_buf, true)
                .or_else(|_: SymmetricCipherError| {
                    Err("Cipher error during decryption")
                })
                .and_then(|_: BufferResult| {
                    let mut cur_buf_read_buffer = cur_buf.take_read_buffer();
                    let mut dec_block: &[u8] = cur_buf_read_buffer.take_next(16);
                    for i in 0..16 {
                        //cur_block[i] ^= prev_block[i] - i as u8;
                        prev_block[i] = (dec_block[i] ^ prev_block[i]) - i as u8;
                    }
                    // TODO: 4080 check
                    bytes_written = cmp::min(
                            cmp::min(16, last_read_count),
                            metadata.file_size as usize - total_bytes
                            );
                    dst.write_all(&prev_block[0..bytes_written])
                    .or_else(|r: io::Error| {
                        Err("Write error")
                    })
                })
            }));
        if bytes_written < 16 {
            break;
        }
    }
    Ok(metadata.file_size as usize)
}
<|endoftext|>


<commit_before>use std::fmt;
use std::mem;

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {
    let mut life = Life::from_str(DATA);
    let lcount = life.nth(100).unwrap().lcount();

    let mut life = Life::from_str(DATA);
    life.stick(0, 0);
    life.stick(0, 99);
    life.stick(99, 0);
    life.stick(99, 99);
    let lcount2 = life.nth(100).unwrap().lcount();

    vec![lcount.to_string(), lcount2.to_string()]
}

struct Life {
    arr: [[bool; 100]; 100],
    stuck: Vec<(usize, usize)>,
}

impl Life {
    fn new() -> Life {
        Life {
            arr: [[false; 100]; 100],
            stuck: Vec::new(),
        }
    }

    fn stick(&mut self, x: usize, y: usize) {
        self.stuck.push((x, y));
    }

    fn from_str(data: &str) -> Life {
        let mut life = Life::new();
        {
            for (l, c) in data.lines()
                              .enumerate()
                              .flat_map(move |(l, s)| {
                                  s.chars()
                                   .enumerate()
                                   .filter(|&(_, z)| z == '#')
                                   .map(move |(c, _)| (l, c))
                              }) {
                life.arr[l][c] = true;
            }
        }
        life
    }

    fn to_string(&self) -> String {
        self.arr
            .iter()
            .map(|l| {
                l.iter()
                 .map(|v| {
                     match *v {
                         true => '#',
                         false => '.',
                     }
                 })
                 .collect::<String>()
            })
            .collect::<Vec<String>>()
            .join("\n")
    }

    fn neighbors(x: usize, y: usize) -> Vec<(usize, usize)> {
        let mut n = Vec::new();
        if x != 0 {
            if y != 0 {
                n.push((x - 1, y - 1));
            }
            n.push((x - 1, y));
            if y != 99 {
                n.push((x - 1, y + 1));
            }
        }
        if y != 0 {
            n.push((x, y - 1));
        }
        if y != 99 {
            n.push((x, y + 1));
        }
        if x != 99 {
            if y != 0 {
                n.push((x + 1, y - 1));
            }
            n.push((x + 1, y));
            if y != 99 {
                n.push((x + 1, y + 1));
            }
        }
        n
    }

    fn lcount(&self) -> usize {
        self.arr
            .iter()
            .flat_map(|x| x.iter().filter(|&&b| b == true))
            .count()
    }
}

impl fmt::Display for Life {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(&self.to_string(), f)
    }
}

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let mut next = [[false; 100]; 100];

        for x in 0..100 {
            for y in 0..100 {
                let count = Life::neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| {
                                    let a = self.arr.get(x);
                                    let b = a.and_then(|a| a.get(y));
                                    b.unwrap_or(&false).to_owned()
                                })
                                .filter(|b| *b == true)
                                .count();
                match (self.arr[x][y], count) {
                    (true, 2) | (true, 3) => next[x][y] = true,
                    (true, _) => next[x][y] = false,
                    (false, 3) => next[x][y] = true,
                    (false, _) => next[x][y] = false,
                }
            }
        }
        for &(x, y) in self.stuck.iter() {
            next[x][y] = true;
        }

        mem::swap(&mut self.arr, &mut next);

        Some(Life {
            arr: next,
            stuck: self.stuck.clone(),
        })
    }
}
<commit_msg>day 18: move to a single array with index calculations<commit_after>use std::fmt;
use std::mem;

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {
    let mut life = Life::from_str(DATA);
    let lcount = life.nth(100).unwrap().lcount();

    let mut life = Life::from_str(DATA);
    life.stick(0, 0);
    life.stick(0, 99);
    life.stick(99, 0);
    life.stick(99, 99);
    let lcount2 = life.nth(100).unwrap().lcount();

    vec![lcount.to_string(), lcount2.to_string()]
}

struct Life {
    size: (usize, usize),
    arr: [bool; 100 * 100],
    stuck: Vec<(usize, usize)>,
}

impl Life {
    fn new() -> Life {
        Life {
            size: (100, 100),
            arr: [false; 100 * 100],
            stuck: Vec::new(),
        }
    }

    fn stick(&mut self, x: usize, y: usize) {
        self.stuck.push((x, y));
    }

    fn from_str(data: &str) -> Life {
        let mut life = Life::new();
        {
            for (l, c) in data.lines()
                              .enumerate()
                              .flat_map(move |(l, s)| {
                                  s.chars()
                                   .enumerate()
                                   .filter(|&(_, z)| z == '#')
                                   .map(move |(c, _)| (l, c))
                              }) {
                life.arr[l * life.size.0 + c] = true;
            }
        }
        life
    }

    fn to_string(&self) -> String {
        self.arr
            .chunks(self.size.0)
            .map(|l| {
                l.iter()
                 .map(|v| {
                     match *v {
                         true => '#',
                         false => '.',
                     }
                 })
                 .collect::<String>()
            })
            .collect::<Vec<String>>()
            .join("\n")
    }

    fn neighbors(x: usize, y: usize) -> Vec<(usize, usize)> {
        let mut n = Vec::new();
        if x != 0 {
            if y != 0 {
                n.push((x - 1, y - 1));
            }
            n.push((x - 1, y));
            if y != 99 {
                n.push((x - 1, y + 1));
            }
        }
        if y != 0 {
            n.push((x, y - 1));
        }
        if y != 99 {
            n.push((x, y + 1));
        }
        if x != 99 {
            if y != 0 {
                n.push((x + 1, y - 1));
            }
            n.push((x + 1, y));
            if y != 99 {
                n.push((x + 1, y + 1));
            }
        }
        n
    }

    fn lcount(&self) -> usize {
        self.arr
            .iter()
            .filter(|&&b| b == true)
            .count()
    }
}

impl fmt::Display for Life {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(&self.to_string(), f)
    }
}

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let mut next = [false; 100 * 100];

        for x in 0..100 {
            for y in 0..100 {
                let count = Life::neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| {
                                    let b = self.arr.get(x * self.size.0 + y);
                                    b.unwrap_or(&false).to_owned()
                                })
                                .filter(|b| *b == true)
                                .count();
                match (self.arr[x * self.size.0 + y], count) {
                    (true, 2) | (true, 3) => next[x * 100 + y] = true,
                    (true, _) => next[x * 100 + y] = false,
                    (false, 3) => next[x * 100 + y] = true,
                    (false, _) => next[x * 100 + y] = false,
                }
            }
        }
        for &(x, y) in self.stuck.iter() {
            next[x * 100 + y] = true;
        }

        mem::swap(&mut self.arr, &mut next);

        Some(Life {
            size: self.size,
            arr: next,
            stuck: self.stuck.clone(),
        })
    }
}
<|endoftext|>


<commit_before>extern crate libproc;
extern crate libc;

use std::io::Write;
use libproc::libproc::kmesg_buffer;

fn main() {
    if kmesg_buffer::am_root() {
        match kmesg_buffer::kmsgbuf() {
            Ok(message) => println!("{}", message),
            Err(err) => writeln!(&mut std::io::stderr(), "Error: {}", err).unwrap()
        }
    } else {
        writeln!(&mut std::io::stderr(), "Must be run as root").unwrap()
    }
}<commit_msg>Added a comment<commit_after>extern crate libproc;
extern crate libc;

use std::io::Write;
use libproc::libproc::kmesg_buffer;

/*
    A `dmesg` commands as a simple demonstration program of using libproc-rs
*/
fn main() {
    if kmesg_buffer::am_root() {
        match kmesg_buffer::kmsgbuf() {
            Ok(message) => println!("{}", message),
            Err(err) => writeln!(&mut std::io::stderr(), "Error: {}", err).unwrap()
        }
    } else {
        writeln!(&mut std::io::stderr(), "Must be run as root").unwrap()
    }
}<|endoftext|>


<commit_before>//! Functions for detecting edges in images.

use std::f32;
use image::{GenericImage, GrayImage, ImageBuffer, Luma};
use gradients::{vertical_sobel, horizontal_sobel};
use definitions::{HasWhite, HasBlack};
use filter::gaussian_blur_f32;

/// Runs the canny edge detection algorithm on the provided `ImageBuffer`.
///
/// # Params
///
/// - `low_threshold`: Low threshold for the hysteresis procedure.
/// Edges with a strength higher than the low threshold will appear
/// in the output image, if there are strong edges nearby.
/// - `high_threshold`: High threshold for the hysteresis procedure.
/// Edges with a strength higher than the high threshold will always
/// appear as edges in the output image.
///
/// Returns a binary image, where edge pixels have a value of 255 and non-edge pixels a value of 0.
pub fn canny(image: &GrayImage,
             low_threshold: f32,
             high_threshold: f32)
             -> GrayImage {
    assert!(high_threshold >= low_threshold);
    // Heavily based on the implementation proposed by wikipedia.
    // 1. Gaussian blur.
    const SIGMA: f32 = 1.4;
    let blurred = gaussian_blur_f32(image, SIGMA);

    // 2. Intensity of gradients.
    let gx = horizontal_sobel(&blurred);
    let gy = vertical_sobel(&blurred);
    let g = ImageBuffer::from_fn(image.width(), image.height(), |x, y| {
        let g = (gx[(x, y)][0] as f32).hypot(gy[(x, y)][0] as f32);
        Luma { data: [g] }
    });

    // 3. Non-maximum-suppression (Make edges thinner)
    let thinned = non_maximum_suppression(&g, &gx, &gy);

    // 4. Hysteresis to filter out edges based on thresholds.
    hysteresis(&thinned, low_threshold, high_threshold)
}

/// Finds local maxima to make the edges thinner.
fn non_maximum_suppression(g: &ImageBuffer<Luma<f32>, Vec<f32>>,
                           gx: &ImageBuffer<Luma<i16>, Vec<i16>>,
                           gy: &ImageBuffer<Luma<i16>, Vec<i16>>)
                           -> ImageBuffer<Luma<f32>, Vec<f32>> {
    const RADIANS_TO_DEGREES: f32 = 180f32 / f32::consts::PI;
    let mut out = ImageBuffer::from_pixel(g.width(), g.height(), Luma { data: [0.0] });
    for y in 1..g.height() - 1 {
        for x in 1..g.width() - 1 {
            let x_gradient = gx[(x, y)][0] as f32;
            let y_gradient = gy[(x, y)][0] as f32;
            let mut angle = (y_gradient).atan2(x_gradient) * RADIANS_TO_DEGREES;
            if angle < 0.0 {
                angle += 180.0
            }
            // Clamp angle.
            let clamped_angle = if angle >= 157.5 || angle < 22.5 {
                0
            } else if angle >= 22.5 && angle < 67.5 {
                45
            } else if angle >= 67.5 && angle < 112.5 {
                90
            } else if angle >= 112.5 && angle < 157.5 {
                135
            } else {
                unreachable!()
            };

            // Get the two perpendicular neighbors.
            let (cmp1, cmp2) = unsafe {
                match clamped_angle {
                    0 => (g.unsafe_get_pixel(x - 1, y), g.unsafe_get_pixel(x + 1, y)),
                    45 => {
                        (g.unsafe_get_pixel(x + 1, y + 1),
                         g.unsafe_get_pixel(x - 1, y - 1))
                    }
                    90 => (g.unsafe_get_pixel(x, y - 1), g.unsafe_get_pixel(x, y + 1)),
                    135 => {
                        (g.unsafe_get_pixel(x - 1, y + 1),
                         g.unsafe_get_pixel(x + 1, y - 1))
                    }
                    _ => unreachable!(),
                }
            };
            let pixel = *g.get_pixel(x, y);
            // If the pixel is not a local maximum, suppress it.
            if pixel[0] < cmp1[0] || pixel[0] < cmp2[0] {
                out.put_pixel(x, y, Luma { data: [0.0] });
            } else {
                out.put_pixel(x, y, pixel);
            }
        }
    }
    out
}

/// Filter out edges with the thresholds.
/// Non-recursive breadth-first search.
fn hysteresis(input: &ImageBuffer<Luma<f32>, Vec<f32>>,
              low_thresh: f32,
              high_thresh: f32)
              -> ImageBuffer<Luma<u8>, Vec<u8>> {

    let max_brightness = Luma::white();
    let min_brightness = Luma::black();
    // Init output image as all black.
    let mut out = ImageBuffer::from_pixel(input.width(), input.height(), min_brightness);
    // Stack. Possible optimization: Use previously allocated memory, i.e. gx.
    let mut edges = Vec::with_capacity(((input.width() * input.height()) / 2) as usize);
    for y in 1..input.height() - 1 {
        for x in 1..input.width() - 1 {
            let inp_pix = *input.get_pixel(x, y);
            let out_pix = *out.get_pixel(x, y);
            // If the edge strength is higher than high_thresh, mark it as an edge.
            if inp_pix[0] >= high_thresh && out_pix[0] == 0 {
                out.put_pixel(x, y, max_brightness);
                edges.push((x, y));
                // Track neighbors until no neighbor is >= low_thresh.
                while !edges.is_empty() {
                    let (nx, ny) = edges.pop().unwrap();
                    let neighbor_indices = [(nx + 1, ny),
                                            (nx + 1, ny + 1),
                                            (nx, ny + 1),
                                            (nx - 1, ny - 1),
                                            (nx - 1, ny),
                                            (nx - 1, ny + 1)];

                    for neighbor_idx in &neighbor_indices {
                        let in_neighbor = *input.get_pixel(neighbor_idx.0, neighbor_idx.1);
                        let out_neighbor = *out.get_pixel(neighbor_idx.0, neighbor_idx.1);
                        if in_neighbor[0] >= low_thresh && out_neighbor[0] == 0 {
                            out.put_pixel(neighbor_idx.0, neighbor_idx.1, max_brightness);
                            edges.push((neighbor_idx.0, neighbor_idx.1));
                        }
                    }
                }
            }
        }
    }
    out
}

#[cfg(test)]
mod test {
    use super::canny;
    use drawing::{draw_filled_rect_mut};
    use rect::Rect;
    use image::{GrayImage, Luma};
    use test;

    fn edge_detect_bench_image(width: u32, height: u32) -> GrayImage {
        let mut image = GrayImage::new(width, height);
        let (w, h) = (width as i32, height as i32);
        let large = Rect::at(w / 4, h / 4).of_size(width / 2, height / 2);
        let small = Rect::at(9, 9).of_size(3, 3);

        draw_filled_rect_mut(&mut image, large, Luma([255]));
        draw_filled_rect_mut(&mut image, small, Luma([255]));

        image
    }

    #[bench]
    fn bench_canny(b: &mut test::Bencher) {
        let image = edge_detect_bench_image(250, 250);
        b.iter(|| {
            let output = canny(&image, 250.0, 300.0);
            test::black_box(output);
        });
    }
}
<commit_msg>Improve speed of canny<commit_after>//! Functions for detecting edges in images.

use std::f32;
use image::{GenericImage, GrayImage, ImageBuffer, Luma};
use gradients::{vertical_sobel, horizontal_sobel};
use definitions::{HasWhite, HasBlack};
use filter::gaussian_blur_f32;

/// Runs the canny edge detection algorithm on the provided `ImageBuffer`.
///
/// # Params
///
/// - `low_threshold`: Low threshold for the hysteresis procedure.
/// Edges with a strength higher than the low threshold will appear
/// in the output image, if there are strong edges nearby.
/// - `high_threshold`: High threshold for the hysteresis procedure.
/// Edges with a strength higher than the high threshold will always
/// appear as edges in the output image.
///
/// Returns a binary image, where edge pixels have a value of 255 and non-edge pixels a value of 0.
pub fn canny(image: &GrayImage,
             low_threshold: f32,
             high_threshold: f32)
             -> GrayImage {
    assert!(high_threshold >= low_threshold);
    // Heavily based on the implementation proposed by wikipedia.
    // 1. Gaussian blur.
    const SIGMA: f32 = 1.4;
    let blurred = gaussian_blur_f32(image, SIGMA);

    // 2. Intensity of gradients.
    let gx = horizontal_sobel(&blurred);
    let gy = vertical_sobel(&blurred);
    let g: Vec<f32> = gx.iter()
                        .zip(gy.iter())
                        .map(|(h, v)| (*h as f32).hypot(*v as f32))
                        .collect::<Vec<f32>>();

    let g = ImageBuffer::from_raw(image.width(), image.height(), g).unwrap();

    // 3. Non-maximum-suppression (Make edges thinner)
    let thinned = non_maximum_suppression(&g, &gx, &gy);

    // 4. Hysteresis to filter out edges based on thresholds.
    hysteresis(&thinned, low_threshold, high_threshold)
}

/// Finds local maxima to make the edges thinner.
fn non_maximum_suppression(g: &ImageBuffer<Luma<f32>, Vec<f32>>,
                           gx: &ImageBuffer<Luma<i16>, Vec<i16>>,
                           gy: &ImageBuffer<Luma<i16>, Vec<i16>>)
                           -> ImageBuffer<Luma<f32>, Vec<f32>> {
    const RADIANS_TO_DEGREES: f32 = 180f32 / f32::consts::PI;
    let mut out = ImageBuffer::from_pixel(g.width(), g.height(), Luma { data: [0.0] });
    for y in 1..g.height() - 1 {
        for x in 1..g.width() - 1 {
            let x_gradient = gx[(x, y)][0] as f32;
            let y_gradient = gy[(x, y)][0] as f32;
            let mut angle = (y_gradient).atan2(x_gradient) * RADIANS_TO_DEGREES;
            if angle < 0.0 {
                angle += 180.0
            }
            // Clamp angle.
            let clamped_angle = if angle >= 157.5 || angle < 22.5 {
                0
            } else if angle >= 22.5 && angle < 67.5 {
                45
            } else if angle >= 67.5 && angle < 112.5 {
                90
            } else if angle >= 112.5 && angle < 157.5 {
                135
            } else {
                unreachable!()
            };

            // Get the two perpendicular neighbors.
            let (cmp1, cmp2) = unsafe {
                match clamped_angle {
                    0 => (g.unsafe_get_pixel(x - 1, y), g.unsafe_get_pixel(x + 1, y)),
                    45 => {
                        (g.unsafe_get_pixel(x + 1, y + 1),
                         g.unsafe_get_pixel(x - 1, y - 1))
                    }
                    90 => (g.unsafe_get_pixel(x, y - 1), g.unsafe_get_pixel(x, y + 1)),
                    135 => {
                        (g.unsafe_get_pixel(x - 1, y + 1),
                         g.unsafe_get_pixel(x + 1, y - 1))
                    }
                    _ => unreachable!(),
                }
            };
            let pixel = *g.get_pixel(x, y);
            // If the pixel is not a local maximum, suppress it.
            if pixel[0] < cmp1[0] || pixel[0] < cmp2[0] {
                out.put_pixel(x, y, Luma { data: [0.0] });
            } else {
                out.put_pixel(x, y, pixel);
            }
        }
    }
    out
}

/// Filter out edges with the thresholds.
/// Non-recursive breadth-first search.
fn hysteresis(input: &ImageBuffer<Luma<f32>, Vec<f32>>,
              low_thresh: f32,
              high_thresh: f32)
              -> ImageBuffer<Luma<u8>, Vec<u8>> {

    let max_brightness = Luma::white();
    let min_brightness = Luma::black();
    // Init output image as all black.
    let mut out = ImageBuffer::from_pixel(input.width(), input.height(), min_brightness);
    // Stack. Possible optimization: Use previously allocated memory, i.e. gx.
    let mut edges = Vec::with_capacity(((input.width() * input.height()) / 2) as usize);
    for y in 1..input.height() - 1 {
        for x in 1..input.width() - 1 {
            let inp_pix = *input.get_pixel(x, y);
            let out_pix = *out.get_pixel(x, y);
            // If the edge strength is higher than high_thresh, mark it as an edge.
            if inp_pix[0] >= high_thresh && out_pix[0] == 0 {
                out.put_pixel(x, y, max_brightness);
                edges.push((x, y));
                // Track neighbors until no neighbor is >= low_thresh.
                while !edges.is_empty() {
                    let (nx, ny) = edges.pop().unwrap();
                    let neighbor_indices = [(nx + 1, ny),
                                            (nx + 1, ny + 1),
                                            (nx, ny + 1),
                                            (nx - 1, ny - 1),
                                            (nx - 1, ny),
                                            (nx - 1, ny + 1)];

                    for neighbor_idx in &neighbor_indices {
                        let in_neighbor = *input.get_pixel(neighbor_idx.0, neighbor_idx.1);
                        let out_neighbor = *out.get_pixel(neighbor_idx.0, neighbor_idx.1);
                        if in_neighbor[0] >= low_thresh && out_neighbor[0] == 0 {
                            out.put_pixel(neighbor_idx.0, neighbor_idx.1, max_brightness);
                            edges.push((neighbor_idx.0, neighbor_idx.1));
                        }
                    }
                }
            }
        }
    }
    out
}

#[cfg(test)]
mod test {
    use super::canny;
    use drawing::{draw_filled_rect_mut};
    use rect::Rect;
    use image::{GrayImage, Luma};
    use test;

    fn edge_detect_bench_image(width: u32, height: u32) -> GrayImage {
        let mut image = GrayImage::new(width, height);
        let (w, h) = (width as i32, height as i32);
        let large = Rect::at(w / 4, h / 4).of_size(width / 2, height / 2);
        let small = Rect::at(9, 9).of_size(3, 3);

        draw_filled_rect_mut(&mut image, large, Luma([255]));
        draw_filled_rect_mut(&mut image, small, Luma([255]));

        image
    }

    #[bench]
    fn bench_canny(b: &mut test::Bencher) {
        let image = edge_detect_bench_image(250, 250);
        b.iter(|| {
            let output = canny(&image, 250.0, 300.0);
            test::black_box(output);
        });
    }
}
<|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/. */

#![allow(non_camel_case_types)]

macro_rules! VG_USERREQ_TOOL_BASE ( ($a:expr, $b:expr) => (
    ((($a as int) & 0xff) << 24)
  | ((($b as int) & 0xff) << 16)))

#[repr(C)]
pub enum Vg_ClientRequest {
    VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
    VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
    VG_USERREQ__CLIENT_CALL0 = 0x1101,
    VG_USERREQ__CLIENT_CALL1 = 0x1102,
    VG_USERREQ__CLIENT_CALL2 = 0x1103,
    VG_USERREQ__CLIENT_CALL3 = 0x1104,
    VG_USERREQ__COUNT_ERRORS = 0x1201,
    VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
    VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
    VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
    VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
    VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
    VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
    VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
    VG_USERREQ__MEMPOOL_FREE     = 0x1306,
    VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
    VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
    VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
    VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
    VG_USERREQ__PRINTF           = 0x1401,
    VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
    VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
    VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
    VG_USERREQ__STACK_REGISTER   = 0x1501,
    VG_USERREQ__STACK_DEREGISTER = 0x1502,
    VG_USERREQ__STACK_CHANGE     = 0x1503,
    VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
    VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
    VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
}

#[repr(C)]
pub enum Vg_MemCheckClientRequest {
    VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE!('M','C'),
    VG_USERREQ__MAKE_MEM_UNDEFINED,
    VG_USERREQ__MAKE_MEM_DEFINED,
    VG_USERREQ__DISCARD,
    VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
    VG_USERREQ__CHECK_MEM_IS_DEFINED,
    VG_USERREQ__DO_LEAK_CHECK,
    VG_USERREQ__COUNT_LEAKS,
    VG_USERREQ__GET_VBITS,
    VG_USERREQ__SET_VBITS,
    VG_USERREQ__CREATE_BLOCK,
    VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
    VG_USERREQ__COUNT_LEAK_BLOCKS,
}

#[repr(C)]
pub enum Vg_CallgrindClientRequest {
    VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE!('C','T'),
    VG_USERREQ__ZERO_STATS,
    VG_USERREQ__TOGGLE_COLLECT,
    VG_USERREQ__DUMP_STATS_AT,
    VG_USERREQ__START_INSTRUMENTATION,
    VG_USERREQ__STOP_INSTRUMENTATION,
}

#[repr(C)]
pub enum Vg_TCheckClientRequest {
    VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),
    _Vg_TCheckClientRequest_dummy, // suppress error about univariant enum repr
}

#[repr(C)]
pub enum Vg_DRDClientRequest {
   // Binary compatible with the similar Helgrind request above
   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),

   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE!('D','R'),
   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
   VG_USERREQ__DRD_START_SUPPRESSION,
   VG_USERREQ__DRD_FINISH_SUPPRESSION,
   VG_USERREQ__DRD_START_TRACE_ADDR,
   VG_USERREQ__DRD_STOP_TRACE_ADDR,
   VG_USERREQ__DRD_RECORD_LOADS,
   VG_USERREQ__DRD_RECORD_STORES,
   VG_USERREQ__DRD_SET_THREAD_NAME,
}
<commit_msg>Don't warn about request enums we haven't wrapped yet<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/. */

#![allow(non_camel_case_types, dead_code)]

macro_rules! VG_USERREQ_TOOL_BASE ( ($a:expr, $b:expr) => (
    ((($a as int) & 0xff) << 24)
  | ((($b as int) & 0xff) << 16)))

#[repr(C)]
pub enum Vg_ClientRequest {
    VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
    VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
    VG_USERREQ__CLIENT_CALL0 = 0x1101,
    VG_USERREQ__CLIENT_CALL1 = 0x1102,
    VG_USERREQ__CLIENT_CALL2 = 0x1103,
    VG_USERREQ__CLIENT_CALL3 = 0x1104,
    VG_USERREQ__COUNT_ERRORS = 0x1201,
    VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
    VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
    VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
    VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
    VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
    VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
    VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
    VG_USERREQ__MEMPOOL_FREE     = 0x1306,
    VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
    VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
    VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
    VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
    VG_USERREQ__PRINTF           = 0x1401,
    VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
    VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
    VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
    VG_USERREQ__STACK_REGISTER   = 0x1501,
    VG_USERREQ__STACK_DEREGISTER = 0x1502,
    VG_USERREQ__STACK_CHANGE     = 0x1503,
    VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
    VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
    VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
}

#[repr(C)]
pub enum Vg_MemCheckClientRequest {
    VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE!('M','C'),
    VG_USERREQ__MAKE_MEM_UNDEFINED,
    VG_USERREQ__MAKE_MEM_DEFINED,
    VG_USERREQ__DISCARD,
    VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
    VG_USERREQ__CHECK_MEM_IS_DEFINED,
    VG_USERREQ__DO_LEAK_CHECK,
    VG_USERREQ__COUNT_LEAKS,
    VG_USERREQ__GET_VBITS,
    VG_USERREQ__SET_VBITS,
    VG_USERREQ__CREATE_BLOCK,
    VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
    VG_USERREQ__COUNT_LEAK_BLOCKS,
}

#[repr(C)]
pub enum Vg_CallgrindClientRequest {
    VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE!('C','T'),
    VG_USERREQ__ZERO_STATS,
    VG_USERREQ__TOGGLE_COLLECT,
    VG_USERREQ__DUMP_STATS_AT,
    VG_USERREQ__START_INSTRUMENTATION,
    VG_USERREQ__STOP_INSTRUMENTATION,
}

#[repr(C)]
pub enum Vg_TCheckClientRequest {
    VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),
    _Vg_TCheckClientRequest_dummy, // suppress error about univariant enum repr
}

#[repr(C)]
pub enum Vg_DRDClientRequest {
   // Binary compatible with the similar Helgrind request above
   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),

   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE!('D','R'),
   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
   VG_USERREQ__DRD_START_SUPPRESSION,
   VG_USERREQ__DRD_FINISH_SUPPRESSION,
   VG_USERREQ__DRD_START_TRACE_ADDR,
   VG_USERREQ__DRD_STOP_TRACE_ADDR,
   VG_USERREQ__DRD_RECORD_LOADS,
   VG_USERREQ__DRD_RECORD_STORES,
   VG_USERREQ__DRD_SET_THREAD_NAME,
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::{fmt, io};
use rustc_serialize::{json, base64};
use hyper;

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum Error {
    ApiError(ApiError),
    ContentTypeError(String),
    DataTypeError(String),
    DataPathError(String),
    HttpError(hyper::error::Error),
    DecoderError(json::DecoderError),
    EncoderError(json::EncoderError),
    FromBase64Error(base64::FromBase64Error),
    IoError(io::Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

pub fn decode(json_str: &str) -> Error {
    match json::decode::<ApiErrorResponse>(json_str) {
        Ok(err_res) => err_res.error.into(),
        Err(err) => Error::DecoderError(err),
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ApiError(ref e) => e.description(),
            Error::ContentTypeError(ref msg) => &msg,
            Error::DataTypeError(ref msg) => &msg,
            Error::DataPathError(ref msg) => &msg,
            Error::HttpError(ref e) => e.description(),
            Error::DecoderError(ref e) => e.description(),
            Error::EncoderError(ref e) => e.description(),
            Error::FromBase64Error(ref e) => e.description(),
            Error::IoError(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::HttpError(ref e) => Some(e),
            Error::DecoderError(ref e) => Some(e),
            Error::EncoderError(ref e) => Some(e),
            Error::FromBase64Error(ref e) => Some(e),
            Error::IoError(ref e) => Some(e),
            _ => None,
        }
    }
}

//
// Implement Display trait
//

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

//
// Implement From trait (used by try! macro)
//

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

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

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

impl From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::DecoderError(err)
    }
}

impl From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::EncoderError(err)
    }
}

impl From<base64::FromBase64Error> for Error {
    fn from(err: base64::FromBase64Error) -> Error {
        Error::FromBase64Error(err)
    }
}
<commit_msg>More error types<commit_after>use std::error::Error as StdError;
use std::{fmt, io, str, string};
use rustc_serialize::{json, base64};
use hyper;

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum Error {
    ApiError(ApiError),
    ContentTypeError(String),
    DataTypeError(String),
    DataPathError(String),
    HttpError(hyper::error::Error),
    DecoderError(json::DecoderError),
    EncoderError(json::EncoderError),
    FromBase64Error(base64::FromBase64Error),
    IoError(io::Error),
    Utf8Error(str::Utf8Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

pub fn decode(json_str: &str) -> Error {
    match json::decode::<ApiErrorResponse>(json_str) {
        Ok(err_res) => err_res.error.into(),
        Err(err) => Error::DecoderError(err),
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ApiError(ref e) => e.description(),
            Error::ContentTypeError(ref msg) => &msg,
            Error::DataTypeError(ref msg) => &msg,
            Error::DataPathError(ref msg) => &msg,
            Error::HttpError(ref e) => e.description(),
            Error::DecoderError(ref e) => e.description(),
            Error::EncoderError(ref e) => e.description(),
            Error::FromBase64Error(ref e) => e.description(),
            Error::IoError(ref e) => e.description(),
            Error::Utf8Error(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::HttpError(ref e) => Some(e),
            Error::DecoderError(ref e) => Some(e),
            Error::EncoderError(ref e) => Some(e),
            Error::FromBase64Error(ref e) => Some(e),
            Error::IoError(ref e) => Some(e),
            Error::Utf8Error(ref e) => Some(e),
            _ => None,
        }
    }
}

//
// Implement Display trait
//

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

//
// Implement From trait (used by try! macro)
//

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

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

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

impl From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::DecoderError(err)
    }
}

impl From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::EncoderError(err)
    }
}

impl From<base64::FromBase64Error> for Error {
    fn from(err: base64::FromBase64Error) -> Error {
        Error::FromBase64Error(err)
    }
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<string::FromUtf8Error> for Error {
    fn from(err: string::FromUtf8Error) -> Error {
        Error::Utf8Error(err.utf8_error())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::io;
use serde::{Deserializer, Deserialize};
use reqwest;

#[derive(Fail, Debug)]
pub enum Error {
    #[fail(display = "{:?}", _0)]
    Codes(HashSet<Code>),
    #[fail(display = "{}", _0)]
    Reqwest(#[cause] reqwest::Error),
    #[fail(display = "{}", _0)]
    Io(#[cause] io::Error),
}

impl From<reqwest::Error> for Error {
    fn from(err: reqwest::Error) -> Error {
        Error::Reqwest(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Code {
    MissingSecret,
    InvalidSecret,
    MissingResponse,
    InvalidResponse,
    BadRequest,
    Unknown(String)
}

impl<'de> Deserialize<'de> for Code {
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>
    {
        let code = String::deserialize(de)?;
        Ok(match &*code {
            "missing-input-secret" => Code::MissingSecret,
            "invalid-input-secret" => Code::InvalidSecret,
            "missing-input-response" => Code::MissingResponse,
            "invalid-input-response" => Code::InvalidResponse,
            "bad-request" => Code::BadRequest,
            _ => Code::Unknown(code),
        })
    }
}
<commit_msg>On the "https://developers.google.com/recaptcha/docs/verify" website there is a new error code "timeout-or-duplicate".<commit_after>use std::collections::HashSet;
use std::io;
use serde::{Deserializer, Deserialize};
use reqwest;

#[derive(Fail, Debug)]
pub enum Error {
    #[fail(display = "{:?}", _0)]
    Codes(HashSet<Code>),
    #[fail(display = "{}", _0)]
    Reqwest(#[cause] reqwest::Error),
    #[fail(display = "{}", _0)]
    Io(#[cause] io::Error),
}

impl From<reqwest::Error> for Error {
    fn from(err: reqwest::Error) -> Error {
        Error::Reqwest(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Code {
    MissingSecret,
    InvalidSecret,
    MissingResponse,
    InvalidResponse,
    BadRequest,
    TimeoutOrDuplicate,
    Unknown(String)
}

impl<'de> Deserialize<'de> for Code {
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>
    {
        let code = String::deserialize(de)?;
        Ok(match &*code {
            "missing-input-secret" => Code::MissingSecret,
            "invalid-input-secret" => Code::InvalidSecret,
            "missing-input-response" => Code::MissingResponse,
            "invalid-input-response" => Code::InvalidResponse,
            "bad-request" => Code::BadRequest,
            "timeout-or-duplicate" => Code::TimeoutOrDuplicate,
            _ => Code::Unknown(code),
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
use std::fmt::Debug;

use std::io;
use thiserror::Error;

#[derive(Error, Debug, Clone, PartialEq, PartialOrd, Copy, Eq)]
#[non_exhaustive]
pub enum Error {
    #[error("No Memory")]
    NoMemory,
    #[error("Invalid Restore")]
    InvalidRestore,
    #[error("Invalid Pop Group")]
    InvalidPopGroup,
    #[error("No Current Point")]
    NoCurrentPoint,
    #[error("Invalid Matrix")]
    InvalidMatrix,
    #[error("Invalid Status")]
    InvalidStatus,
    #[error("Null Pointer")]
    NullPointer,
    #[error("Invalid String")]
    InvalidString,
    #[error("Invalid Path Data")]
    InvalidPathData,
    #[error("Cairo : Read Error")]
    ReadError,
    #[error("Write Error")]
    WriteError,
    #[error("Surface Finishied")]
    SurfaceFinished,
    #[error("Surface Type Mismatch")]
    SurfaceTypeMismatch,
    #[error("Pattern Type Mismatch")]
    PatternTypeMismatch,
    #[error("Invalid Content")]
    InvalidContent,
    #[error("Invalid Format")]
    InvalidFormat,
    #[error("Invalid Visual")]
    InvalidVisual,
    #[error("File Not Found")]
    FileNotFound,
    #[error("Invalid Dash")]
    InvalidDash,
    #[error("Invalid Dash Comment")]
    InvalidDscComment,
    #[error("Invalid Index")]
    InvalidIndex,
    #[error("Clip Not Representable")]
    ClipNotRepresentable,
    #[error("Temp File Error")]
    TempFileError,
    #[error("Invalid Stride")]
    InvalidStride,
    #[error("Font Type Mismatch")]
    FontTypeMismatch,
    #[error("User Font Immutable")]
    UserFontImmutable,
    #[error("User Font Error")]
    UserFontError,
    #[error("Negative Count")]
    NegativeCount,
    #[error("Invalid Clusters")]
    InvalidClusters,
    #[error("Invalid Slant")]
    InvalidSlant,
    #[error("Invalid Weight")]
    InvalidWeight,
    #[error("Ivalid Size")]
    InvalidSize,
    #[error("User Font Not Implemented")]
    UserFontNotImplemented,
    #[error("Device Type Mismatch")]
    DeviceTypeMismatch,
    #[error("Device Error")]
    DeviceError,
    #[error("Invalid Mesh Construction")]
    InvalidMeshConstruction,
    #[error("Device Finished")]
    DeviceFinished,
    #[error("JBig2Global Missing")]
    JBig2GlobalMissing,
    #[error("PNG Error")]
    PngError,
    #[error("Freetype Error")]
    FreetypeError,
    #[error("Win32Gdi Error")]
    Win32GdiError,
    #[error("LastStatus")]
    LastStatus,
    #[error("Unknown {0}")]
    #[doc(hidden)]
    __Unknown(i32),
}
#[doc(hidden)]
impl Into<ffi::cairo_status_t> for Error {
    fn into(self) -> ffi::cairo_status_t {
        match self {
            Error::NoMemory => ffi::STATUS_NO_MEMORY,
            Error::InvalidRestore => ffi::STATUS_INVALID_RESTORE,
            Error::InvalidPopGroup => ffi::STATUS_INVALID_POP_GROUP,
            Error::NoCurrentPoint => ffi::STATUS_NO_CURRENT_POINT,
            Error::InvalidMatrix => ffi::STATUS_INVALID_MATRIX,
            Error::InvalidStatus => ffi::STATUS_INVALID_STATUS,
            Error::NullPointer => ffi::STATUS_NULL_POINTER,
            Error::InvalidString => ffi::STATUS_INVALID_STRING,
            Error::InvalidPathData => ffi::STATUS_INVALID_PATH_DATA,
            Error::ReadError => ffi::STATUS_READ_ERROR,
            Error::WriteError => ffi::STATUS_WRITE_ERROR,
            Error::SurfaceFinished => ffi::STATUS_SURFACE_FINISHED,
            Error::SurfaceTypeMismatch => ffi::STATUS_SURFACE_TYPE_MISMATCH,
            Error::PatternTypeMismatch => ffi::STATUS_PATTERN_TYPE_MISMATCH,
            Error::InvalidContent => ffi::STATUS_INVALID_CONTENT,
            Error::InvalidFormat => ffi::STATUS_INVALID_FORMAT,
            Error::InvalidVisual => ffi::STATUS_INVALID_VISUAL,
            Error::FileNotFound => ffi::STATUS_FILE_NOT_FOUND,
            Error::InvalidDash => ffi::STATUS_INVALID_DASH,
            Error::InvalidDscComment => ffi::STATUS_INVALID_DSC_COMMENT,
            Error::InvalidIndex => ffi::STATUS_INVALID_INDEX,
            Error::ClipNotRepresentable => ffi::STATUS_CLIP_NOT_REPRESENTABLE,
            Error::TempFileError => ffi::STATUS_TEMP_FILE_ERROR,
            Error::InvalidStride => ffi::STATUS_INVALID_STRIDE,
            Error::FontTypeMismatch => ffi::STATUS_FONT_TYPE_MISMATCH,
            Error::UserFontImmutable => ffi::STATUS_USER_FONT_IMMUTABLE,
            Error::UserFontError => ffi::STATUS_USER_FONT_ERROR,
            Error::NegativeCount => ffi::STATUS_NEGATIVE_COUNT,
            Error::InvalidClusters => ffi::STATUS_INVALID_CLUSTERS,
            Error::InvalidSlant => ffi::STATUS_INVALID_SLANT,
            Error::InvalidWeight => ffi::STATUS_INVALID_WEIGHT,
            Error::InvalidSize => ffi::STATUS_INVALID_SIZE,
            Error::UserFontNotImplemented => ffi::STATUS_USER_FONT_NOT_IMPLEMENTED,
            Error::DeviceTypeMismatch => ffi::STATUS_DEVICE_TYPE_MISMATCH,
            Error::DeviceError => ffi::STATUS_DEVICE_ERROR,
            Error::InvalidMeshConstruction => ffi::STATUS_INVALID_MESH_CONSTRUCTION,
            Error::DeviceFinished => ffi::STATUS_DEVICE_FINISHED,
            Error::JBig2GlobalMissing => ffi::STATUS_J_BIG2_GLOBAL_MISSING,
            Error::PngError => ffi::STATUS_PNG_ERROR,
            Error::FreetypeError => ffi::STATUS_FREETYPE_ERROR,
            Error::Win32GdiError => ffi::STATUS_WIN32_GDI_ERROR,
            Error::LastStatus => ffi::STATUS_LAST_STATUS,
            Error::__Unknown(value) => value,
        }
    }
}

#[doc(hidden)]
impl From<ffi::cairo_status_t> for Error {
    fn from(value: ffi::cairo_status_t) -> Self {
        match value {
            ffi::STATUS_NO_MEMORY => Error::NoMemory,
            ffi::STATUS_INVALID_RESTORE => Error::InvalidRestore,
            ffi::STATUS_INVALID_POP_GROUP => Error::InvalidPopGroup,
            ffi::STATUS_NO_CURRENT_POINT => Error::NoCurrentPoint,
            ffi::STATUS_INVALID_MATRIX => Error::InvalidMatrix,
            ffi::STATUS_INVALID_STATUS => Error::InvalidStatus,
            ffi::STATUS_NULL_POINTER => Error::NullPointer,
            ffi::STATUS_INVALID_STRING => Error::InvalidString,
            ffi::STATUS_INVALID_PATH_DATA => Error::InvalidPathData,
            ffi::STATUS_READ_ERROR => Error::ReadError,
            ffi::STATUS_WRITE_ERROR => Error::WriteError,
            ffi::STATUS_SURFACE_FINISHED => Error::SurfaceFinished,
            ffi::STATUS_SURFACE_TYPE_MISMATCH => Error::SurfaceTypeMismatch,
            ffi::STATUS_PATTERN_TYPE_MISMATCH => Error::PatternTypeMismatch,
            ffi::STATUS_INVALID_CONTENT => Error::InvalidContent,
            ffi::STATUS_INVALID_FORMAT => Error::InvalidFormat,
            ffi::STATUS_INVALID_VISUAL => Error::InvalidVisual,
            ffi::STATUS_FILE_NOT_FOUND => Error::FileNotFound,
            ffi::STATUS_INVALID_DASH => Error::InvalidDash,
            ffi::STATUS_INVALID_DSC_COMMENT => Error::InvalidDscComment,
            ffi::STATUS_INVALID_INDEX => Error::InvalidIndex,
            ffi::STATUS_CLIP_NOT_REPRESENTABLE => Error::ClipNotRepresentable,
            ffi::STATUS_TEMP_FILE_ERROR => Error::TempFileError,
            ffi::STATUS_INVALID_STRIDE => Error::InvalidStride,
            ffi::STATUS_FONT_TYPE_MISMATCH => Error::FontTypeMismatch,
            ffi::STATUS_USER_FONT_IMMUTABLE => Error::UserFontImmutable,
            ffi::STATUS_USER_FONT_ERROR => Error::UserFontError,
            ffi::STATUS_NEGATIVE_COUNT => Error::NegativeCount,
            ffi::STATUS_INVALID_CLUSTERS => Error::InvalidClusters,
            ffi::STATUS_INVALID_SLANT => Error::InvalidSlant,
            ffi::STATUS_INVALID_WEIGHT => Error::InvalidWeight,
            ffi::STATUS_INVALID_SIZE => Error::InvalidSize,
            ffi::STATUS_USER_FONT_NOT_IMPLEMENTED => Error::UserFontNotImplemented,
            ffi::STATUS_DEVICE_TYPE_MISMATCH => Error::DeviceTypeMismatch,
            ffi::STATUS_DEVICE_ERROR => Error::DeviceError,
            ffi::STATUS_INVALID_MESH_CONSTRUCTION => Error::InvalidMeshConstruction,
            ffi::STATUS_DEVICE_FINISHED => Error::DeviceFinished,
            ffi::STATUS_J_BIG2_GLOBAL_MISSING => Error::JBig2GlobalMissing,
            ffi::STATUS_PNG_ERROR => Error::PngError,
            ffi::STATUS_FREETYPE_ERROR => Error::FreetypeError,
            ffi::STATUS_WIN32_GDI_ERROR => Error::Win32GdiError,
            ffi::STATUS_LAST_STATUS => Error::LastStatus,
            value => Error::__Unknown(value),
        }
    }
}

#[derive(Error, Debug)]
pub enum IoError {
    #[error("Cairo error: {0}")]
    Cairo(#[from] Error),
    #[error("IO error: {0}")]
    Io(#[from] io::Error),
}

#[derive(Error, Debug)]
pub enum BorrowError {
    #[error("Failed to borrow with Cairo error: {0}")]
    Cairo(#[from] ::Error),
    #[error("Can't get exclusive access")]
    NonExclusive,
}
<commit_msg>errors: don't derive PartialOrd<commit_after>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
use std::fmt::Debug;

use std::io;
use thiserror::Error;

#[derive(Error, Debug, Clone, PartialEq, Copy, Eq)]
#[non_exhaustive]
pub enum Error {
    #[error("No Memory")]
    NoMemory,
    #[error("Invalid Restore")]
    InvalidRestore,
    #[error("Invalid Pop Group")]
    InvalidPopGroup,
    #[error("No Current Point")]
    NoCurrentPoint,
    #[error("Invalid Matrix")]
    InvalidMatrix,
    #[error("Invalid Status")]
    InvalidStatus,
    #[error("Null Pointer")]
    NullPointer,
    #[error("Invalid String")]
    InvalidString,
    #[error("Invalid Path Data")]
    InvalidPathData,
    #[error("Cairo : Read Error")]
    ReadError,
    #[error("Write Error")]
    WriteError,
    #[error("Surface Finishied")]
    SurfaceFinished,
    #[error("Surface Type Mismatch")]
    SurfaceTypeMismatch,
    #[error("Pattern Type Mismatch")]
    PatternTypeMismatch,
    #[error("Invalid Content")]
    InvalidContent,
    #[error("Invalid Format")]
    InvalidFormat,
    #[error("Invalid Visual")]
    InvalidVisual,
    #[error("File Not Found")]
    FileNotFound,
    #[error("Invalid Dash")]
    InvalidDash,
    #[error("Invalid Dash Comment")]
    InvalidDscComment,
    #[error("Invalid Index")]
    InvalidIndex,
    #[error("Clip Not Representable")]
    ClipNotRepresentable,
    #[error("Temp File Error")]
    TempFileError,
    #[error("Invalid Stride")]
    InvalidStride,
    #[error("Font Type Mismatch")]
    FontTypeMismatch,
    #[error("User Font Immutable")]
    UserFontImmutable,
    #[error("User Font Error")]
    UserFontError,
    #[error("Negative Count")]
    NegativeCount,
    #[error("Invalid Clusters")]
    InvalidClusters,
    #[error("Invalid Slant")]
    InvalidSlant,
    #[error("Invalid Weight")]
    InvalidWeight,
    #[error("Ivalid Size")]
    InvalidSize,
    #[error("User Font Not Implemented")]
    UserFontNotImplemented,
    #[error("Device Type Mismatch")]
    DeviceTypeMismatch,
    #[error("Device Error")]
    DeviceError,
    #[error("Invalid Mesh Construction")]
    InvalidMeshConstruction,
    #[error("Device Finished")]
    DeviceFinished,
    #[error("JBig2Global Missing")]
    JBig2GlobalMissing,
    #[error("PNG Error")]
    PngError,
    #[error("Freetype Error")]
    FreetypeError,
    #[error("Win32Gdi Error")]
    Win32GdiError,
    #[error("LastStatus")]
    LastStatus,
    #[error("Unknown {0}")]
    #[doc(hidden)]
    __Unknown(i32),
}
#[doc(hidden)]
impl Into<ffi::cairo_status_t> for Error {
    fn into(self) -> ffi::cairo_status_t {
        match self {
            Error::NoMemory => ffi::STATUS_NO_MEMORY,
            Error::InvalidRestore => ffi::STATUS_INVALID_RESTORE,
            Error::InvalidPopGroup => ffi::STATUS_INVALID_POP_GROUP,
            Error::NoCurrentPoint => ffi::STATUS_NO_CURRENT_POINT,
            Error::InvalidMatrix => ffi::STATUS_INVALID_MATRIX,
            Error::InvalidStatus => ffi::STATUS_INVALID_STATUS,
            Error::NullPointer => ffi::STATUS_NULL_POINTER,
            Error::InvalidString => ffi::STATUS_INVALID_STRING,
            Error::InvalidPathData => ffi::STATUS_INVALID_PATH_DATA,
            Error::ReadError => ffi::STATUS_READ_ERROR,
            Error::WriteError => ffi::STATUS_WRITE_ERROR,
            Error::SurfaceFinished => ffi::STATUS_SURFACE_FINISHED,
            Error::SurfaceTypeMismatch => ffi::STATUS_SURFACE_TYPE_MISMATCH,
            Error::PatternTypeMismatch => ffi::STATUS_PATTERN_TYPE_MISMATCH,
            Error::InvalidContent => ffi::STATUS_INVALID_CONTENT,
            Error::InvalidFormat => ffi::STATUS_INVALID_FORMAT,
            Error::InvalidVisual => ffi::STATUS_INVALID_VISUAL,
            Error::FileNotFound => ffi::STATUS_FILE_NOT_FOUND,
            Error::InvalidDash => ffi::STATUS_INVALID_DASH,
            Error::InvalidDscComment => ffi::STATUS_INVALID_DSC_COMMENT,
            Error::InvalidIndex => ffi::STATUS_INVALID_INDEX,
            Error::ClipNotRepresentable => ffi::STATUS_CLIP_NOT_REPRESENTABLE,
            Error::TempFileError => ffi::STATUS_TEMP_FILE_ERROR,
            Error::InvalidStride => ffi::STATUS_INVALID_STRIDE,
            Error::FontTypeMismatch => ffi::STATUS_FONT_TYPE_MISMATCH,
            Error::UserFontImmutable => ffi::STATUS_USER_FONT_IMMUTABLE,
            Error::UserFontError => ffi::STATUS_USER_FONT_ERROR,
            Error::NegativeCount => ffi::STATUS_NEGATIVE_COUNT,
            Error::InvalidClusters => ffi::STATUS_INVALID_CLUSTERS,
            Error::InvalidSlant => ffi::STATUS_INVALID_SLANT,
            Error::InvalidWeight => ffi::STATUS_INVALID_WEIGHT,
            Error::InvalidSize => ffi::STATUS_INVALID_SIZE,
            Error::UserFontNotImplemented => ffi::STATUS_USER_FONT_NOT_IMPLEMENTED,
            Error::DeviceTypeMismatch => ffi::STATUS_DEVICE_TYPE_MISMATCH,
            Error::DeviceError => ffi::STATUS_DEVICE_ERROR,
            Error::InvalidMeshConstruction => ffi::STATUS_INVALID_MESH_CONSTRUCTION,
            Error::DeviceFinished => ffi::STATUS_DEVICE_FINISHED,
            Error::JBig2GlobalMissing => ffi::STATUS_J_BIG2_GLOBAL_MISSING,
            Error::PngError => ffi::STATUS_PNG_ERROR,
            Error::FreetypeError => ffi::STATUS_FREETYPE_ERROR,
            Error::Win32GdiError => ffi::STATUS_WIN32_GDI_ERROR,
            Error::LastStatus => ffi::STATUS_LAST_STATUS,
            Error::__Unknown(value) => value,
        }
    }
}

#[doc(hidden)]
impl From<ffi::cairo_status_t> for Error {
    fn from(value: ffi::cairo_status_t) -> Self {
        match value {
            ffi::STATUS_NO_MEMORY => Error::NoMemory,
            ffi::STATUS_INVALID_RESTORE => Error::InvalidRestore,
            ffi::STATUS_INVALID_POP_GROUP => Error::InvalidPopGroup,
            ffi::STATUS_NO_CURRENT_POINT => Error::NoCurrentPoint,
            ffi::STATUS_INVALID_MATRIX => Error::InvalidMatrix,
            ffi::STATUS_INVALID_STATUS => Error::InvalidStatus,
            ffi::STATUS_NULL_POINTER => Error::NullPointer,
            ffi::STATUS_INVALID_STRING => Error::InvalidString,
            ffi::STATUS_INVALID_PATH_DATA => Error::InvalidPathData,
            ffi::STATUS_READ_ERROR => Error::ReadError,
            ffi::STATUS_WRITE_ERROR => Error::WriteError,
            ffi::STATUS_SURFACE_FINISHED => Error::SurfaceFinished,
            ffi::STATUS_SURFACE_TYPE_MISMATCH => Error::SurfaceTypeMismatch,
            ffi::STATUS_PATTERN_TYPE_MISMATCH => Error::PatternTypeMismatch,
            ffi::STATUS_INVALID_CONTENT => Error::InvalidContent,
            ffi::STATUS_INVALID_FORMAT => Error::InvalidFormat,
            ffi::STATUS_INVALID_VISUAL => Error::InvalidVisual,
            ffi::STATUS_FILE_NOT_FOUND => Error::FileNotFound,
            ffi::STATUS_INVALID_DASH => Error::InvalidDash,
            ffi::STATUS_INVALID_DSC_COMMENT => Error::InvalidDscComment,
            ffi::STATUS_INVALID_INDEX => Error::InvalidIndex,
            ffi::STATUS_CLIP_NOT_REPRESENTABLE => Error::ClipNotRepresentable,
            ffi::STATUS_TEMP_FILE_ERROR => Error::TempFileError,
            ffi::STATUS_INVALID_STRIDE => Error::InvalidStride,
            ffi::STATUS_FONT_TYPE_MISMATCH => Error::FontTypeMismatch,
            ffi::STATUS_USER_FONT_IMMUTABLE => Error::UserFontImmutable,
            ffi::STATUS_USER_FONT_ERROR => Error::UserFontError,
            ffi::STATUS_NEGATIVE_COUNT => Error::NegativeCount,
            ffi::STATUS_INVALID_CLUSTERS => Error::InvalidClusters,
            ffi::STATUS_INVALID_SLANT => Error::InvalidSlant,
            ffi::STATUS_INVALID_WEIGHT => Error::InvalidWeight,
            ffi::STATUS_INVALID_SIZE => Error::InvalidSize,
            ffi::STATUS_USER_FONT_NOT_IMPLEMENTED => Error::UserFontNotImplemented,
            ffi::STATUS_DEVICE_TYPE_MISMATCH => Error::DeviceTypeMismatch,
            ffi::STATUS_DEVICE_ERROR => Error::DeviceError,
            ffi::STATUS_INVALID_MESH_CONSTRUCTION => Error::InvalidMeshConstruction,
            ffi::STATUS_DEVICE_FINISHED => Error::DeviceFinished,
            ffi::STATUS_J_BIG2_GLOBAL_MISSING => Error::JBig2GlobalMissing,
            ffi::STATUS_PNG_ERROR => Error::PngError,
            ffi::STATUS_FREETYPE_ERROR => Error::FreetypeError,
            ffi::STATUS_WIN32_GDI_ERROR => Error::Win32GdiError,
            ffi::STATUS_LAST_STATUS => Error::LastStatus,
            value => Error::__Unknown(value),
        }
    }
}

#[derive(Error, Debug)]
pub enum IoError {
    #[error("Cairo error: {0}")]
    Cairo(#[from] Error),
    #[error("IO error: {0}")]
    Io(#[from] io::Error),
}

#[derive(Error, Debug)]
pub enum BorrowError {
    #[error("Failed to borrow with Cairo error: {0}")]
    Cairo(#[from] ::Error),
    #[error("Can't get exclusive access")]
    NonExclusive,
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use libc::c_int;
use {ffi, errmsg_to_string};

/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
pub enum Error {
    /// An error from an underlying SQLite call.
    SqliteFailure(ffi::Error, Option<String>),

    /// Error reported when attempting to open a connection when SQLite was configured to
    /// allow single-threaded use only.
    SqliteSingleThreadedMode,

    /// An error case available for implementors of the `FromSql` trait.
    FromSqlConversionFailure(Box<error::Error + Send + Sync>),

    /// Error converting a string to UTF-8.
    Utf8Error(str::Utf8Error),

    /// Error converting a string to a C-compatible string because it contained an embedded nul.
    NulError(::std::ffi::NulError),

    /// Error when using SQL named parameters and passing a parameter name not present in the SQL.
    InvalidParameterName(String),

    /// Error converting a file path to a string.
    InvalidPath(PathBuf),

    /// Error returned when an `execute` call returns rowss.
    ExecuteReturnedResults,

    /// Error when a query that was expected to return at least one row (e.g., for `query_row`)
    /// did not return any.
    QueryReturnedNoRows,

    /// Error when trying to access a `Row` after stepping past it. See the discussion on
    /// the `Rows` type for more details.
    GetFromStaleRow,

    /// Error when the value of a particular column is requested, but the index is out of range
    /// for the statement.
    InvalidColumnIndex(c_int),

    /// Error when the value of a named column is requested, but no column matches the name
    /// for the statement.
    InvalidColumnName(String),

    /// Error when the value of a particular column is requested, but the type of the result in
    /// that column cannot be converted to the requested Rust type.
    InvalidColumnType,

    /// Error returned by `functions::Context::get` when the function argument cannot be converted
    /// to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType,

    /// An error case available for implementors of custom user functions (e.g.,
    /// `create_scalar_function`).
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<error::Error + Send + Sync>),
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::SqliteFailure(ref err, None) => err.fmt(f),
            &Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            &Error::SqliteSingleThreadedMode => write!(f, "SQLite was compiled or configured for single-threaded use only"),
            &Error::FromSqlConversionFailure(ref err) => err.fmt(f),
            &Error::Utf8Error(ref err) => err.fmt(f),
            &Error::NulError(ref err) => err.fmt(f),
            &Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            &Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            &Error::ExecuteReturnedResults => write!(f, "Execute returned results - did you mean to call query?"),
            &Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            &Error::GetFromStaleRow => write!(f, "Attempted to get a value from a stale row"),
            &Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            &Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name),
            &Error::InvalidColumnType => write!(f, "Invalid column type"),

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"),
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SqliteFailure(ref err, None) => err.description(),
            &Error::SqliteFailure(_, Some(ref s)) => s,
            &Error::SqliteSingleThreadedMode => "SQLite was compiled or configured for single-threaded use only",
            &Error::FromSqlConversionFailure(ref err) => err.description(),
            &Error::Utf8Error(ref err) => err.description(),
            &Error::InvalidParameterName(_) => "invalid parameter name",
            &Error::NulError(ref err) => err.description(),
            &Error::InvalidPath(_) => "invalid path",
            &Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?",
            &Error::QueryReturnedNoRows => "query returned no rows",
            &Error::GetFromStaleRow => "attempted to get a value from a stale row",
            &Error::InvalidColumnIndex(_) => "invalid column index",
            &Error::InvalidColumnName(_) => "invalid column name",
            &Error::InvalidColumnType => "invalid column type",

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => "invalid function parameter type",
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::SqliteFailure(ref err, _) => Some(err),
            &Error::SqliteSingleThreadedMode => None,
            &Error::FromSqlConversionFailure(ref err) => Some(&**err),
            &Error::Utf8Error(ref err) => Some(err),
            &Error::NulError(ref err) => Some(err),
            &Error::InvalidParameterName(_) => None,
            &Error::InvalidPath(_) => None,
            &Error::ExecuteReturnedResults => None,
            &Error::QueryReturnedNoRows => None,
            &Error::GetFromStaleRow => None,
            &Error::InvalidColumnIndex(_) => None,
            &Error::InvalidColumnName(_) => None,
            &Error::InvalidColumnType => None,

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => None,
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => Some(&**err),
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}
<commit_msg>Fix typo "rowss" in docs.<commit_after>use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use libc::c_int;
use {ffi, errmsg_to_string};

/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
pub enum Error {
    /// An error from an underlying SQLite call.
    SqliteFailure(ffi::Error, Option<String>),

    /// Error reported when attempting to open a connection when SQLite was configured to
    /// allow single-threaded use only.
    SqliteSingleThreadedMode,

    /// An error case available for implementors of the `FromSql` trait.
    FromSqlConversionFailure(Box<error::Error + Send + Sync>),

    /// Error converting a string to UTF-8.
    Utf8Error(str::Utf8Error),

    /// Error converting a string to a C-compatible string because it contained an embedded nul.
    NulError(::std::ffi::NulError),

    /// Error when using SQL named parameters and passing a parameter name not present in the SQL.
    InvalidParameterName(String),

    /// Error converting a file path to a string.
    InvalidPath(PathBuf),

    /// Error returned when an `execute` call returns rows.
    ExecuteReturnedResults,

    /// Error when a query that was expected to return at least one row (e.g., for `query_row`)
    /// did not return any.
    QueryReturnedNoRows,

    /// Error when trying to access a `Row` after stepping past it. See the discussion on
    /// the `Rows` type for more details.
    GetFromStaleRow,

    /// Error when the value of a particular column is requested, but the index is out of range
    /// for the statement.
    InvalidColumnIndex(c_int),

    /// Error when the value of a named column is requested, but no column matches the name
    /// for the statement.
    InvalidColumnName(String),

    /// Error when the value of a particular column is requested, but the type of the result in
    /// that column cannot be converted to the requested Rust type.
    InvalidColumnType,

    /// Error returned by `functions::Context::get` when the function argument cannot be converted
    /// to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType,

    /// An error case available for implementors of custom user functions (e.g.,
    /// `create_scalar_function`).
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<error::Error + Send + Sync>),
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::SqliteFailure(ref err, None) => err.fmt(f),
            &Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            &Error::SqliteSingleThreadedMode => write!(f, "SQLite was compiled or configured for single-threaded use only"),
            &Error::FromSqlConversionFailure(ref err) => err.fmt(f),
            &Error::Utf8Error(ref err) => err.fmt(f),
            &Error::NulError(ref err) => err.fmt(f),
            &Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            &Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            &Error::ExecuteReturnedResults => write!(f, "Execute returned results - did you mean to call query?"),
            &Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            &Error::GetFromStaleRow => write!(f, "Attempted to get a value from a stale row"),
            &Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            &Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name),
            &Error::InvalidColumnType => write!(f, "Invalid column type"),

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"),
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SqliteFailure(ref err, None) => err.description(),
            &Error::SqliteFailure(_, Some(ref s)) => s,
            &Error::SqliteSingleThreadedMode => "SQLite was compiled or configured for single-threaded use only",
            &Error::FromSqlConversionFailure(ref err) => err.description(),
            &Error::Utf8Error(ref err) => err.description(),
            &Error::InvalidParameterName(_) => "invalid parameter name",
            &Error::NulError(ref err) => err.description(),
            &Error::InvalidPath(_) => "invalid path",
            &Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?",
            &Error::QueryReturnedNoRows => "query returned no rows",
            &Error::GetFromStaleRow => "attempted to get a value from a stale row",
            &Error::InvalidColumnIndex(_) => "invalid column index",
            &Error::InvalidColumnName(_) => "invalid column name",
            &Error::InvalidColumnType => "invalid column type",

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => "invalid function parameter type",
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::SqliteFailure(ref err, _) => Some(err),
            &Error::SqliteSingleThreadedMode => None,
            &Error::FromSqlConversionFailure(ref err) => Some(&**err),
            &Error::Utf8Error(ref err) => Some(err),
            &Error::NulError(ref err) => Some(err),
            &Error::InvalidParameterName(_) => None,
            &Error::InvalidPath(_) => None,
            &Error::ExecuteReturnedResults => None,
            &Error::QueryReturnedNoRows => None,
            &Error::GetFromStaleRow => None,
            &Error::InvalidColumnIndex(_) => None,
            &Error::InvalidColumnName(_) => None,
            &Error::InvalidColumnType => None,

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => None,
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => Some(&**err),
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}
<|endoftext|>


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

#[cfg(backtrace)]
use std::backtrace::{Backtrace, BacktraceStatus};

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does 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,
    {
        // Captured here instead of in Error::construct to have one fewer layer
        // of wrapping visible in the backtrace.
        #[cfg(backtrace)]
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::construct(error, TypeId::of::<E>(), backtrace)
    }

    pub(crate) fn new_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>(), backtrace)
    }

    fn construct<E>(error: E, type_id: TypeId, backtrace: Option<Backtrace>) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        #[cfg(not(backtrace))]
        let _ = backtrace;

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

    /// Wrap the error value with additional context.
    ///
    /// For attaching context to a `Result` as it is propagated, the
    /// [`Context`][crate::Context] extension trait may be more convenient than
    /// this function.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// Get the backtrace for this Error.
    ///
    /// Backtraces are only available on the nightly channel. Tracking issue:
    /// [rust-lang/rust#53487][tracking].
    ///
    /// In order for the backtrace to be meaningful, the environment variable
    /// `RUST_LIB_BACKTRACE=1` must be defined. Backtraces are somewhat
    /// expensive to capture in Rust, so we don't necessarily want to be
    /// capturing them all over the place all the time.
    ///
    /// [tracking]: https://github.com/rust-lang/rust/issues/53487
    #[cfg(backtrace)]
    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
        }
    }
}

#[cfg(not(backtrace))]
pub(crate) enum Backtrace {}

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 chain = self.chain().skip(1).enumerate();
        if let Some((n, error)) = chain.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in chain {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        #[cfg(backtrace)]
        {
            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,
    #[cfg(backtrace)]
    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;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::sync::Arc;

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

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn drop_works() {
        #[derive(Debug)]
        struct DetectDrop {
            has_dropped: Arc<AtomicBool>,
        }

        impl StdError for DetectDrop {}

        impl Display for DetectDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }

        impl Drop for DetectDrop {
            fn drop(&mut self) {
                let already_dropped = self.has_dropped.swap(true, SeqCst);
                assert!(!already_dropped);
            }
        }

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

        drop(Error::from(DetectDrop {
            has_dropped: has_dropped.clone(),
        }));

        assert!(has_dropped.load(SeqCst));
    }
}
<commit_msg>Unconditionally store Option<Backtrace><commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

#[cfg(backtrace)]
use std::backtrace::{Backtrace, BacktraceStatus};

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does 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,
    {
        // Captured here instead of in Error::construct to have one fewer layer
        // of wrapping visible in the backtrace.
        #[cfg(backtrace)]
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::construct(error, TypeId::of::<E>(), backtrace)
    }

    pub(crate) fn new_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>(), backtrace)
    }

    fn construct<E>(error: E, type_id: TypeId, backtrace: Option<Backtrace>) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let inner = Box::new(ErrorImpl {
                vtable: obj.vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    ///
    /// For attaching context to a `Result` as it is propagated, the
    /// [`Context`][crate::Context] extension trait may be more convenient than
    /// this function.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// Get the backtrace for this Error.
    ///
    /// Backtraces are only available on the nightly channel. Tracking issue:
    /// [rust-lang/rust#53487][tracking].
    ///
    /// In order for the backtrace to be meaningful, the environment variable
    /// `RUST_LIB_BACKTRACE=1` must be defined. Backtraces are somewhat
    /// expensive to capture in Rust, so we don't necessarily want to be
    /// capturing them all over the place all the time.
    ///
    /// [tracking]: https://github.com/rust-lang/rust/issues/53487
    #[cfg(backtrace)]
    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
        }
    }
}

#[cfg(not(backtrace))]
pub(crate) enum Backtrace {}

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 chain = self.chain().skip(1).enumerate();
        if let Some((n, error)) = chain.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in chain {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        #[cfg(backtrace)]
        {
            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;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::sync::Arc;

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

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn drop_works() {
        #[derive(Debug)]
        struct DetectDrop {
            has_dropped: Arc<AtomicBool>,
        }

        impl StdError for DetectDrop {}

        impl Display for DetectDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }

        impl Drop for DetectDrop {
            fn drop(&mut self) {
                let already_dropped = self.has_dropped.swap(true, SeqCst);
                assert!(!already_dropped);
            }
        }

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

        drop(Error::from(DetectDrop {
            has_dropped: has_dropped.clone(),
        }));

        assert!(has_dropped.load(SeqCst));
    }
}
<|endoftext|>


<commit_before>//! Modulo responsável por reportar os erros
#![macro_use]

/// Emite um aviso a respeito de um problema, mas continua a execução do programa
#[macro_export]
macro_rules! warn {
    ($($tt:tt)*) => {{
        print!("Aviso: ");
        println!($($tt)*);
    }}
}
<commit_msg>Remove modulo desnecessário<commit_after><|endoftext|>