<commit_before>
use ffi;
use super::r2r::*;
use super::{c64, FLAG, SIGN};
use std::ops::MulAssign;
use super::util::FFTW_MUTEX;

#[derive(Debug)]
pub struct Plan<'a, 'b, A, B>
    where A: 'a,
          B: 'b
{
    pub field: &'a mut [A],
    pub coef: &'b mut [B],
    logical_size: usize,
    forward: ffi::fftw_plan,
    backward: ffi::fftw_plan,
}

impl<'a, 'b, A, B> Plan<'a, 'b, A, B>
    where B: MulAssign<f64>
{
    /// [field] -> [coef]
    pub fn forward(&mut self) {
        unsafe {
            ffi::fftw_execute(self.forward);
        }
        self.normalize_coef();
    }
    /// [field] <- [coef]
    pub fn backward(&mut self) {
        unsafe {
            ffi::fftw_execute(self.backward);
        }
    }
    fn normalize_coef(&mut self) {
        let n = 1.0 / self.logical_size as f64;
        for val in self.coef.iter_mut() {
            *val *= n;
        }
    }
}

impl<'a, 'b, A, B> Drop for Plan<'a, 'b, A, B> {
    #[allow(unused_variables)]
    fn drop(&mut self) {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe {
            ffi::fftw_destroy_plan(self.forward);
            ffi::fftw_destroy_plan(self.backward);
        }
    }
}

impl<'a, 'b> Plan<'a, 'b, f64, f64> {
    pub fn r2r_1d(field: &'a mut [f64], coef: &'b mut [f64], kind: R2R_KIND, flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_r2r_1d(n as i32,
                                  field.as_mut_ptr(),
                                  coef.as_mut_ptr(),
                                  forward(kind),
                                  flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_r2r_1d(n as i32,
                                  coef.as_mut_ptr(),
                                  field.as_mut_ptr(),
                                  backward(kind),
                                  flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: logical_size(n, kind),
            forward: forward,
            backward: backward,
        }
    }
}

impl<'a, 'b> Plan<'a, 'b, c64, c64> {
    pub fn dft_1d(field: &'a mut [c64], coef: &'b mut [c64], sign: SIGN, flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_dft_1d(n as i32,
                                  field.as_mut_ptr() as *mut ffi::fftw_complex,
                                  coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                  sign as i32,
                                  flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_dft_1d(n as i32,
                                  coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                  field.as_mut_ptr() as *mut ffi::fftw_complex,
                                  -(sign as i32),
                                  flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }

    }
}

impl<'a, 'b> Plan<'a, 'b, f64, c64> {
    pub fn r2c_1d(field: &'a mut [f64], coef: &'b mut [c64], flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_dft_r2c_1d(n as i32,
                                      field.as_mut_ptr(),
                                      coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                      flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_dft_c2r_1d(n as i32,
                                      coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                      field.as_mut_ptr(),
                                      flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }

    }
}
<commit_msg>Change normalization<commit_after>
use ffi;
use super::r2r::*;
use super::{c64, FLAG, SIGN};
use std::ops::MulAssign;
use super::util::FFTW_MUTEX;

#[derive(Debug)]
pub struct Plan<'a, 'b, A, B>
    where A: 'a,
          B: 'b
{
    pub field: &'a mut [A],
    pub coef: &'b mut [B],
    logical_size: usize,
    forward: ffi::fftw_plan,
    backward: ffi::fftw_plan,
}

impl<'a, 'b, A, B> Plan<'a, 'b, A, B>
    where A: MulAssign<f64>,
          B: MulAssign<f64>
{
    /// [field] -> [coef]
    pub fn forward(&mut self) {
        unsafe {
            ffi::fftw_execute(self.forward);
        }
    }
    /// [field] <- [coef]
    pub fn backward(&mut self) {
        unsafe {
            ffi::fftw_execute(self.backward);
        }
    }
    pub fn normalize_field_by(&mut self, n: f64) {
        for val in self.field.iter_mut() {
            *val *= n;
        }
    }
    pub fn normalize_coef_by(&mut self, n: f64) {
        for val in self.coef.iter_mut() {
            *val *= n;
        }
    }
}

impl<'a, 'b, A, B> Drop for Plan<'a, 'b, A, B> {
    #[allow(unused_variables)]
    fn drop(&mut self) {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe {
            ffi::fftw_destroy_plan(self.forward);
            ffi::fftw_destroy_plan(self.backward);
        }
    }
}

impl<'a, 'b> Plan<'a, 'b, f64, f64> {
    pub fn r2r_1d(field: &'a mut [f64], coef: &'b mut [f64], kind: R2R_KIND, flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_r2r_1d(n as i32,
                                  field.as_mut_ptr(),
                                  coef.as_mut_ptr(),
                                  forward(kind),
                                  flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_r2r_1d(n as i32,
                                  coef.as_mut_ptr(),
                                  field.as_mut_ptr(),
                                  backward(kind),
                                  flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: logical_size(n, kind),
            forward: forward,
            backward: backward,
        }
    }
}

impl<'a, 'b> Plan<'a, 'b, c64, c64> {
    pub fn dft_1d(field: &'a mut [c64], coef: &'b mut [c64], sign: SIGN, flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_dft_1d(n as i32,
                                  field.as_mut_ptr() as *mut ffi::fftw_complex,
                                  coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                  sign as i32,
                                  flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_dft_1d(n as i32,
                                  coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                  field.as_mut_ptr() as *mut ffi::fftw_complex,
                                  -(sign as i32),
                                  flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }

    }
}

impl<'a, 'b> Plan<'a, 'b, f64, c64> {
    pub fn r2c_1d(field: &'a mut [f64], coef: &'b mut [c64], flag: FLAG) -> Self {
        let n = field.len();
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let forward = unsafe {
            ffi::fftw_plan_dft_r2c_1d(n as i32,
                                      field.as_mut_ptr(),
                                      coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                      flag as u32)
        };
        let backward = unsafe {
            ffi::fftw_plan_dft_c2r_1d(n as i32,
                                      coef.as_mut_ptr() as *mut ffi::fftw_complex,
                                      field.as_mut_ptr(),
                                      flag as u32)
        };
        drop(lock);
        Plan {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }

    }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use XY;
use vec::Vec2;

/// Location of the view on screen
pub type Position = XY<Offset>;

impl Position {
    /// Returns a position centered on both axis.
    pub fn center() -> Self {
        Position::new(Offset::Center, Offset::Center)
    }

    /// Returns a position absolute on both axis.
    pub fn absolute<T: Into<Vec2>>(offset: T) -> Self {
        let offset = offset.into();
        Position::new(Offset::Absolute(offset.x), Offset::Absolute(offset.y))
    }

    /// Returns a position relative to the parent on both axis.
    pub fn parent<T: Into<Vec2>>(offset: T) -> Self {
        let offset = offset.into();
        Position::new(Offset::Parent(offset.x), Offset::Parent(offset.y))
    }

    /// Computes the offset required to draw a view.
    ///
    /// When drawing a view with `size` in a container with `available`,
    /// and a parent with the absolute coordinates `parent`, drawing the
    /// child with its top-left corner at the returned coordinates will
    /// position him appropriately.
    pub fn compute_offset<S, A, P>(&self, size: S, available: A, parent: P)
                                   -> Vec2
        where S: Into<Vec2>,
              A: Into<Vec2>,
              P: Into<Vec2>
    {
        let available = available.into();
        let size = size.into();
        let parent = parent.into();

        Vec2::new(self.x.compute_offset(size.x, available.x, parent.x),
                  self.y.compute_offset(size.y, available.y, parent.y))
    }
}

/// Single-dimensional offset policy.
#[derive(PartialEq,Debug,Clone)]
pub enum Offset {
    /// In the center of the screen
    Center,
    /// Place top-left corner at the given absolute coordinates
    Absolute(usize),

    /// Offset from the previous layer's top-left corner.
    ///
    /// If this is the first layer, behaves like `Absolute`.
    Parent(usize), // TODO: use a signed vec for negative offset?
}

impl Offset {
    /// Computes a single-dimension offset requred to draw a view.
    pub fn compute_offset(&self, size: usize, available: usize, parent: usize)
                          -> usize {
        if size > available {
            0
        } else {
            match *self {
                Offset::Center => (available - size) / 2,
                Offset::Absolute(offset) => min(offset, available - size),
                Offset::Parent(offset) => {
                    min(parent + offset, available - size)
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use vec::Vec2;
    use super::{Offset, Position};

    #[test]
    fn test_center() {
        let center = Position::center();
        assert_eq!(Vec2::new(2, 1), center.compute_offset((1,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(2, 0), center.compute_offset((1,3), (5,3), (0,0)));
        assert_eq!(Vec2::new(1, 1), center.compute_offset((3,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 1), center.compute_offset((5,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 0), center.compute_offset((5,3), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 0), center.compute_offset((5,3), (3,1), (0,0)));
    }
}
<commit_msg>Remove unused import in test module<commit_after>use std::cmp::min;
use XY;
use vec::Vec2;

/// Location of the view on screen
pub type Position = XY<Offset>;

impl Position {
    /// Returns a position centered on both axis.
    pub fn center() -> Self {
        Position::new(Offset::Center, Offset::Center)
    }

    /// Returns a position absolute on both axis.
    pub fn absolute<T: Into<Vec2>>(offset: T) -> Self {
        let offset = offset.into();
        Position::new(Offset::Absolute(offset.x), Offset::Absolute(offset.y))
    }

    /// Returns a position relative to the parent on both axis.
    pub fn parent<T: Into<Vec2>>(offset: T) -> Self {
        let offset = offset.into();
        Position::new(Offset::Parent(offset.x), Offset::Parent(offset.y))
    }

    /// Computes the offset required to draw a view.
    ///
    /// When drawing a view with `size` in a container with `available`,
    /// and a parent with the absolute coordinates `parent`, drawing the
    /// child with its top-left corner at the returned coordinates will
    /// position him appropriately.
    pub fn compute_offset<S, A, P>(&self, size: S, available: A, parent: P)
                                   -> Vec2
        where S: Into<Vec2>,
              A: Into<Vec2>,
              P: Into<Vec2>
    {
        let available = available.into();
        let size = size.into();
        let parent = parent.into();

        Vec2::new(self.x.compute_offset(size.x, available.x, parent.x),
                  self.y.compute_offset(size.y, available.y, parent.y))
    }
}

/// Single-dimensional offset policy.
#[derive(PartialEq,Debug,Clone)]
pub enum Offset {
    /// In the center of the screen
    Center,
    /// Place top-left corner at the given absolute coordinates
    Absolute(usize),

    /// Offset from the previous layer's top-left corner.
    ///
    /// If this is the first layer, behaves like `Absolute`.
    Parent(usize), // TODO: use a signed vec for negative offset?
}

impl Offset {
    /// Computes a single-dimension offset requred to draw a view.
    pub fn compute_offset(&self, size: usize, available: usize, parent: usize)
                          -> usize {
        if size > available {
            0
        } else {
            match *self {
                Offset::Center => (available - size) / 2,
                Offset::Absolute(offset) => min(offset, available - size),
                Offset::Parent(offset) => {
                    min(parent + offset, available - size)
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use vec::Vec2;
    use super::{Position};

    #[test]
    fn test_center() {
        let center = Position::center();
        assert_eq!(Vec2::new(2, 1), center.compute_offset((1,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(2, 0), center.compute_offset((1,3), (5,3), (0,0)));
        assert_eq!(Vec2::new(1, 1), center.compute_offset((3,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 1), center.compute_offset((5,1), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 0), center.compute_offset((5,3), (5,3), (0,0)));
        assert_eq!(Vec2::new(0, 0), center.compute_offset((5,3), (3,1), (0,0)));
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
// The constants CRC24_INIT and CRC24_POLY are defined in section 6.1
// of RFC4880 along with the definition of the CRC octet validator.
const CRC24_INIT: usize = 0xB704CE;
const CRC24_POLY: usize = 0x1864CFB;

pub type Crc24 = usize;

// This is an adaption of the CRC-24 algorithm from section 6.1 of RFC4880.
#[allow(unused_variables)]
pub fn crc_octets(octets: &[u8]) -> Crc24 {
    let mut crc: Crc24 = CRC24_INIT;
    for octet in octets {
        crc ^= (*octet as usize) << 16;
        for i in 0..8 {
            crc <<= 1;
            if crc & 0x1000000 != 0 {
                crc ^= CRC24_POLY;
            }
        }
    }
    // Fit crc24 into 24 bits.
    crc & 0xFFFFFF
}

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

    struct TestCase {
        octets: Vec<u8>,
        crc: Crc24
    }

    struct Test {
        data: Vec<TestCase>
    }

    // An empty octet set should compute the crc as the
    // constant CRC24_INIT.
    fn crc_octets_empty_case() -> Test {
        Test {
            data: vec![
                TestCase {
                    octets: vec![],
                    crc: super::CRC24_INIT
                }
            ]
        }
    }

    fn crc_octets_test_cases() -> Test {
        Test {
            data: vec![
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E],
                    crc: 6927321
                },
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03, 0xD9],
                    crc: 8726480
                },
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03],
                    crc: 15804535
                },
                TestCase {
                    octets: vec![0xD5, 0xF0, 0x32, 0x8A, 0xA0, 0xA9,
                                 0x1F, 0xAD, 0x1D, 0xDC, 0x22, 0xB6],
                    crc: 6688197
                }
            ]
        }
    }

    fn run_tests(test: &Test) {
        for test_case in test.data.iter() {
            let crc24 = super::crc_octets(test_case.octets.as_ref());
            assert_eq!(test_case.crc, crc24);
        }
    }

    #[test]
    fn test_crc_octets() {
        run_tests(&crc_octets_test_cases());
    }

    #[test]
    fn test_crc_octets_empty_case() {
        run_tests(&crc_octets_empty_case());
    }
}
<commit_msg>Remove unused variable in for loop in crc_octets.<commit_after>#![allow(dead_code)]
// The constants CRC24_INIT and CRC24_POLY are defined in section 6.1
// of RFC4880 along with the definition of the CRC octet validator.
const CRC24_INIT: usize = 0xB704CE;
const CRC24_POLY: usize = 0x1864CFB;

pub type Crc24 = usize;

// This is an adaption of the CRC-24 algorithm from section 6.1 of RFC4880.
pub fn crc_octets(octets: &[u8]) -> Crc24 {
    let mut crc: Crc24 = CRC24_INIT;
    for octet in octets {
        crc ^= (*octet as usize) << 16;
        for _ in 0..8 {
            crc <<= 1;
            if crc & 0x1000000 != 0 {
                crc ^= CRC24_POLY;
            }
        }
    }
    // Fit crc24 into 24 bits.
    crc & 0xFFFFFF
}

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

    struct TestCase {
        octets: Vec<u8>,
        crc: Crc24
    }

    struct Test {
        data: Vec<TestCase>
    }

    // An empty octet set should compute the crc as the
    // constant CRC24_INIT.
    fn crc_octets_empty_case() -> Test {
        Test {
            data: vec![
                TestCase {
                    octets: vec![],
                    crc: super::CRC24_INIT
                }
            ]
        }
    }

    fn crc_octets_test_cases() -> Test {
        Test {
            data: vec![
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E],
                    crc: 6927321
                },
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03, 0xD9],
                    crc: 8726480
                },
                TestCase {
                    octets: vec![0x14, 0xFB, 0x9C, 0x03],
                    crc: 15804535
                },
                TestCase {
                    octets: vec![0xD5, 0xF0, 0x32, 0x8A, 0xA0, 0xA9,
                                 0x1F, 0xAD, 0x1D, 0xDC, 0x22, 0xB6],
                    crc: 6688197
                }
            ]
        }
    }

    fn run_tests(test: &Test) {
        for test_case in test.data.iter() {
            let crc24 = super::crc_octets(test_case.octets.as_ref());
            assert_eq!(test_case.crc, crc24);
        }
    }

    #[test]
    fn test_crc_octets() {
        run_tests(&crc_octets_test_cases());
    }

    #[test]
    fn test_crc_octets_empty_case() {
        run_tests(&crc_octets_empty_case());
    }
}
<|endoftext|>


<commit_before>use super::TimerUpdateWidget;
use text::{Attributes, Text};

use std::time::Duration;

use xcb;
use xcb_util;

pub struct Pager {
    conn: xcb_util::ewmh::Connection,
    screen_idx: i32,
    update_interval: Duration,
    active_attr: Attributes,
    inactive_attr: Attributes,
}

impl Pager {
    pub fn new(active_attr: Attributes, inactive_attr: Attributes) -> Pager {
        let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
        let ewmh_conn = xcb_util::ewmh::Connection::connect(conn)
            .map_err(|_| ())
            .unwrap();

        Pager {
            conn: ewmh_conn,
            screen_idx: screen_idx,
            update_interval: Duration::from_secs(1),
            active_attr: active_attr,
            inactive_attr: inactive_attr,
        }
    }

    fn get_desktops_info(&self) -> Vec<(bool, String)> {
        let number = xcb_util::ewmh::get_number_of_desktops(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap() as usize;
        let current = xcb_util::ewmh::get_current_desktop(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap() as usize;
        let names_reply = xcb_util::ewmh::get_desktop_names(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap();
        let mut names = names_reply.strings();

        // EWMH states that `number` may not equal `names.len()`, as there may
        // be unnamed desktops, or more desktops than are currently in use.
        if names.len() > number {
            names.truncate(number);
        } else if number > names.len() {
            for i in 0..(number - names.len()) {
                names.push("?");
            }
        }

        names
            .into_iter()
            .enumerate()
            .map(|(i, name)| (i == current, name.to_owned()))
            .collect()
    }
}

impl TimerUpdateWidget for Pager {
    fn update_interval(&self) -> Duration {
        self.update_interval
    }

    fn tick(&self) -> Vec<Text> {
        self.get_desktops_info()
            .into_iter()
            .map(|(active, name)| {
                Text {
                    attr: if active {
                        self.active_attr.clone()
                    } else {
                        self.inactive_attr.clone()
                    },
                    text: name,
                    stretch: false,
                }
            })
            .collect()
    }
}
<commit_msg>Avoid for loop - vec![] allows non-const number!<commit_after>use super::TimerUpdateWidget;
use text::{Attributes, Text};

use std::time::Duration;

use xcb;
use xcb_util;

pub struct Pager {
    conn: xcb_util::ewmh::Connection,
    screen_idx: i32,
    update_interval: Duration,
    active_attr: Attributes,
    inactive_attr: Attributes,
}

impl Pager {
    pub fn new(active_attr: Attributes, inactive_attr: Attributes) -> Pager {
        let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
        let ewmh_conn = xcb_util::ewmh::Connection::connect(conn)
            .map_err(|_| ())
            .unwrap();

        Pager {
            conn: ewmh_conn,
            screen_idx: screen_idx,
            update_interval: Duration::from_secs(1),
            active_attr: active_attr,
            inactive_attr: inactive_attr,
        }
    }

    fn get_desktops_info(&self) -> Vec<(bool, String)> {
        let number = xcb_util::ewmh::get_number_of_desktops(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap() as usize;
        let current = xcb_util::ewmh::get_current_desktop(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap() as usize;
        let names_reply = xcb_util::ewmh::get_desktop_names(&self.conn, self.screen_idx)
            .get_reply()
            .unwrap();
        let mut names = names_reply.strings();

        // EWMH states that `number` may not equal `names.len()`, as there may
        // be unnamed desktops, or more desktops than are currently in use.
        if names.len() > number {
            names.truncate(number);
        } else if number > names.len() {
            let num_unnamed = number - names.len();
            names.extend(vec!["?"; num_unnamed]);
        }

        names
            .into_iter()
            .enumerate()
            .map(|(i, name)| (i == current, name.to_owned()))
            .collect()
    }
}

impl TimerUpdateWidget for Pager {
    fn update_interval(&self) -> Duration {
        self.update_interval
    }

    fn tick(&self) -> Vec<Text> {
        self.get_desktops_info()
            .into_iter()
            .map(|(active, name)| {
                Text {
                    attr: if active {
                        self.active_attr.clone()
                    } else {
                        self.inactive_attr.clone()
                    },
                    text: name,
                    stretch: false,
                }
            })
            .collect()
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * A type representing values that may be computed concurrently and
 * operations for working with them.
 *
 * # Example
 *
 * ```rust
 * use std::sync::Future;
 * # fn fib(n: uint) -> uint {42};
 * # fn make_a_sandwich() {};
 * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
 * make_a_sandwich();
 * println!("fib(5000) = {}", delayed_fib.get())
 * ```
 */

#![allow(missing_doc)]

use core::prelude::*;
use core::mem::replace;

use comm::{Receiver, channel};
use task::spawn;

/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
    state: FutureState<A>,
}

enum FutureState<A> {
    Pending(proc():Send -> A),
    Evaluating,
    Forced(A)
}

/// Methods on the `future` type
impl<A:Clone> Future<A> {
    pub fn get(&mut self) -> A {
        //! Get the value of the future.
        (*(self.get_ref())).clone()
    }
}

impl<A> Future<A> {
    /// Gets the value from this future, forcing evaluation.
    pub fn unwrap(mut self) -> A {
        self.get_ref();
        let state = replace(&mut self.state, Evaluating);
        match state {
            Forced(v) => v,
            _ => fail!( "Logic error." ),
        }
    }

    pub fn get_ref<'a>(&'a mut self) -> &'a A {
        /*!
        * Executes the future's closure and then returns a reference
        * to the result.  The reference lasts as long as
        * the future.
        */
        match self.state {
            Forced(ref v) => return v,
            Evaluating => fail!("Recursive forcing of future!"),
            Pending(_) => {
                match replace(&mut self.state, Evaluating) {
                    Forced(_) | Evaluating => fail!("Logic error."),
                    Pending(f) => {
                        self.state = Forced(f());
                        self.get_ref()
                    }
                }
            }
        }
    }

    pub fn from_value(val: A) -> Future<A> {
        /*!
         * Create a future from a value.
         *
         * The value is immediately available and calling `get` later will
         * not block.
         */

        Future {state: Forced(val)}
    }

    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a function.
         *
         * The first time that the value is requested it will be retrieved by
         * calling the function.  Note that this function is a local
         * function. It is not spawned into another task.
         */

        Future {state: Pending(f)}
    }
}

impl<A:Send> Future<A> {
    pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
        /*!
         * Create a future from a port
         *
         * The first time that the value is requested the task will block
         * waiting for the result to be received on the port.
         */

        Future::from_fn(proc() {
            rx.recv()
        })
    }

    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a unique closure.
         *
         * The closure will be run in a new task and its result used as the
         * value of the future.
         */

        let (tx, rx) = channel();

        spawn(proc() {
            // Don't fail if the other end has hung up
            let _ = tx.send_opt(blk());
        });

        Future::from_receiver(rx)
    }
}

#[cfg(test)]
mod test {
    use prelude::*;
    use sync::Future;
    use task;
    use comm::{channel, Sender};

    #[test]
    fn test_from_value() {
        let mut f = Future::from_value("snail".to_string());
        assert_eq!(f.get(), "snail".to_string());
    }

    #[test]
    fn test_from_receiver() {
        let (tx, rx) = channel();
        tx.send("whale".to_string());
        let mut f = Future::from_receiver(rx);
        assert_eq!(f.get(), "whale".to_string());
    }

    #[test]
    fn test_from_fn() {
        let mut f = Future::from_fn(proc() "brail".to_string());
        assert_eq!(f.get(), "brail".to_string());
    }

    #[test]
    fn test_interface_get() {
        let mut f = Future::from_value("fail".to_string());
        assert_eq!(f.get(), "fail".to_string());
    }

    #[test]
    fn test_interface_unwrap() {
        let f = Future::from_value("fail".to_string());
        assert_eq!(f.unwrap(), "fail".to_string());
    }

    #[test]
    fn test_get_ref_method() {
        let mut f = Future::from_value(22i);
        assert_eq!(*f.get_ref(), 22);
    }

    #[test]
    fn test_spawn() {
        let mut f = Future::spawn(proc() "bale".to_string());
        assert_eq!(f.get(), "bale".to_string());
    }

    #[test]
    #[should_fail]
    fn test_futurefail() {
        let mut f = Future::spawn(proc() fail!());
        let _x: String = f.get();
    }

    #[test]
    fn test_sendable_future() {
        let expected = "schlorf";
        let f = Future::spawn(proc() { expected });
        task::spawn(proc() {
            let mut f = f;
            let actual = f.get();
            assert_eq!(actual, expected);
        });
    }

    #[test]
    fn test_dropped_future_doesnt_fail() {
        struct Bomb(Sender<bool>);

        local_data_key!(LOCAL: Bomb)

        impl Drop for Bomb {
            fn drop(&mut self) {
                let Bomb(ref tx) = *self;
                tx.send(task::failing());
            }
        }

        // Spawn a future, but drop it immediately. When we receive the result
        // later on, we should never view the task as having failed.
        let (tx, rx) = channel();
        drop(Future::spawn(proc() {
            LOCAL.replace(Some(Bomb(tx)));
        }));

        // Make sure the future didn't fail the task.
        assert!(!rx.recv());
    }
}
<commit_msg>Fix async assertion in test_sendable_future<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * A type representing values that may be computed concurrently and
 * operations for working with them.
 *
 * # Example
 *
 * ```rust
 * use std::sync::Future;
 * # fn fib(n: uint) -> uint {42};
 * # fn make_a_sandwich() {};
 * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
 * make_a_sandwich();
 * println!("fib(5000) = {}", delayed_fib.get())
 * ```
 */

#![allow(missing_doc)]

use core::prelude::*;
use core::mem::replace;

use comm::{Receiver, channel};
use task::spawn;

/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
    state: FutureState<A>,
}

enum FutureState<A> {
    Pending(proc():Send -> A),
    Evaluating,
    Forced(A)
}

/// Methods on the `future` type
impl<A:Clone> Future<A> {
    pub fn get(&mut self) -> A {
        //! Get the value of the future.
        (*(self.get_ref())).clone()
    }
}

impl<A> Future<A> {
    /// Gets the value from this future, forcing evaluation.
    pub fn unwrap(mut self) -> A {
        self.get_ref();
        let state = replace(&mut self.state, Evaluating);
        match state {
            Forced(v) => v,
            _ => fail!( "Logic error." ),
        }
    }

    pub fn get_ref<'a>(&'a mut self) -> &'a A {
        /*!
        * Executes the future's closure and then returns a reference
        * to the result.  The reference lasts as long as
        * the future.
        */
        match self.state {
            Forced(ref v) => return v,
            Evaluating => fail!("Recursive forcing of future!"),
            Pending(_) => {
                match replace(&mut self.state, Evaluating) {
                    Forced(_) | Evaluating => fail!("Logic error."),
                    Pending(f) => {
                        self.state = Forced(f());
                        self.get_ref()
                    }
                }
            }
        }
    }

    pub fn from_value(val: A) -> Future<A> {
        /*!
         * Create a future from a value.
         *
         * The value is immediately available and calling `get` later will
         * not block.
         */

        Future {state: Forced(val)}
    }

    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a function.
         *
         * The first time that the value is requested it will be retrieved by
         * calling the function.  Note that this function is a local
         * function. It is not spawned into another task.
         */

        Future {state: Pending(f)}
    }
}

impl<A:Send> Future<A> {
    pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
        /*!
         * Create a future from a port
         *
         * The first time that the value is requested the task will block
         * waiting for the result to be received on the port.
         */

        Future::from_fn(proc() {
            rx.recv()
        })
    }

    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a unique closure.
         *
         * The closure will be run in a new task and its result used as the
         * value of the future.
         */

        let (tx, rx) = channel();

        spawn(proc() {
            // Don't fail if the other end has hung up
            let _ = tx.send_opt(blk());
        });

        Future::from_receiver(rx)
    }
}

#[cfg(test)]
mod test {
    use prelude::*;
    use sync::Future;
    use task;
    use comm::{channel, Sender};

    #[test]
    fn test_from_value() {
        let mut f = Future::from_value("snail".to_string());
        assert_eq!(f.get(), "snail".to_string());
    }

    #[test]
    fn test_from_receiver() {
        let (tx, rx) = channel();
        tx.send("whale".to_string());
        let mut f = Future::from_receiver(rx);
        assert_eq!(f.get(), "whale".to_string());
    }

    #[test]
    fn test_from_fn() {
        let mut f = Future::from_fn(proc() "brail".to_string());
        assert_eq!(f.get(), "brail".to_string());
    }

    #[test]
    fn test_interface_get() {
        let mut f = Future::from_value("fail".to_string());
        assert_eq!(f.get(), "fail".to_string());
    }

    #[test]
    fn test_interface_unwrap() {
        let f = Future::from_value("fail".to_string());
        assert_eq!(f.unwrap(), "fail".to_string());
    }

    #[test]
    fn test_get_ref_method() {
        let mut f = Future::from_value(22i);
        assert_eq!(*f.get_ref(), 22);
    }

    #[test]
    fn test_spawn() {
        let mut f = Future::spawn(proc() "bale".to_string());
        assert_eq!(f.get(), "bale".to_string());
    }

    #[test]
    #[should_fail]
    fn test_futurefail() {
        let mut f = Future::spawn(proc() fail!());
        let _x: String = f.get();
    }

    #[test]
    fn test_sendable_future() {
        let expected = "schlorf";
        let (tx, rx) = channel();
        let f = Future::spawn(proc() { expected });
        task::spawn(proc() {
            let mut f = f;
            tx.send(f.get());
        });
        assert_eq!(rx.recv(), expected);
    }

    #[test]
    fn test_dropped_future_doesnt_fail() {
        struct Bomb(Sender<bool>);

        local_data_key!(LOCAL: Bomb)

        impl Drop for Bomb {
            fn drop(&mut self) {
                let Bomb(ref tx) = *self;
                tx.send(task::failing());
            }
        }

        // Spawn a future, but drop it immediately. When we receive the result
        // later on, we should never view the task as having failed.
        let (tx, rx) = channel();
        drop(Future::spawn(proc() {
            LOCAL.replace(Some(Bomb(tx)));
        }));

        // Make sure the future didn't fail the task.
        assert!(!rx.recv());
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::convert::From;
use std::fmt;
use ring::error;
use hyper::header::RetryAfter;

#[derive(PartialEq, Debug)]
pub enum WebPushError {
    Unspecified,
    Unauthorized,
    BadRequest,
    ServerError(Option<RetryAfter>),
    ContentTooLong,
    NotImplemented(&'static str),
    InvalidUri,
}

impl From<error::Unspecified> for WebPushError {
    fn from(_: error::Unspecified) -> WebPushError {
        WebPushError::Unspecified
    }
}

impl Error for WebPushError {
    fn description(&self) -> &str {
        match *self {
            WebPushError::Unspecified =>
                "An unknown error happened encrypting the message",
            WebPushError::Unauthorized =>
                "Please provide valid credentials to send the notification",
            WebPushError::BadRequest =>
                "Request was badly formed",
            WebPushError::ServerError(_) =>
                "Server was unable to process the request, please try again later",
            WebPushError::ContentTooLong =>
                "Maximum allowed payload size is 4078 bytes",
            WebPushError::InvalidUri =>
                "The provided URI is invalid",
            WebPushError::NotImplemented(msg) => msg,
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for WebPushError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}
<commit_msg>Fix an error message<commit_after>use std::error::Error;
use std::convert::From;
use std::fmt;
use ring::error;
use hyper::header::RetryAfter;

#[derive(PartialEq, Debug)]
pub enum WebPushError {
    Unspecified,
    Unauthorized,
    BadRequest,
    ServerError(Option<RetryAfter>),
    ContentTooLong,
    NotImplemented(&'static str),
    InvalidUri,
}

impl From<error::Unspecified> for WebPushError {
    fn from(_: error::Unspecified) -> WebPushError {
        WebPushError::Unspecified
    }
}

impl Error for WebPushError {
    fn description(&self) -> &str {
        match *self {
            WebPushError::Unspecified =>
                "An unknown error happened encrypting the message",
            WebPushError::Unauthorized =>
                "Please provide valid credentials to send the notification",
            WebPushError::BadRequest =>
                "Request was badly formed",
            WebPushError::ServerError(_) =>
                "Server was unable to process the request, please try again later",
            WebPushError::ContentTooLong =>
                "Maximum allowed payload size is 3800 characters",
            WebPushError::InvalidUri =>
                "The provided URI is invalid",
            WebPushError::NotImplemented(msg) => msg,
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for WebPushError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub struct CTError {
    pub kind: CTErrorKind,
    pub desc: String,
    pub pos: Option<(usize, usize)>,
}

#[derive(Debug, PartialEq)]
pub enum CTErrorKind {
    InputError,
    DatabaseError,
}

pub type CTResult<T> = Result<T, CTError>;

impl CTError {
    /// Pretty-prints the CTError struct to stdout
    pub fn print(&self, input: &str) {
        match self.kind {
            CTErrorKind::InputError => {
                println!("error: {}", self.desc);
                if let Some((pos, len)) = self.pos {
                    println!("error:     {}", input);
                    print!("error:     ");
                    for _ in 0..pos {
                        print!(" ");
                    }
                    print!("^");
                    for _ in 1..len {
                        print!("~");
                    }
                    println!("");
                }
            },
            CTErrorKind::DatabaseError => {
                println!("fatal error: {}", self.desc);
            }
        }
    }
}<commit_msg>Do not print 'error:' before every error message<commit_after>#[derive(Debug, PartialEq)]
pub struct CTError {
    pub kind: CTErrorKind,
    pub desc: String,
    pub pos: Option<(usize, usize)>,
}

#[derive(Debug, PartialEq)]
pub enum CTErrorKind {
    InputError,
    DatabaseError,
}

pub type CTResult<T> = Result<T, CTError>;

impl CTError {
    /// Pretty-prints the CTError struct to stdout
    pub fn print(&self, input: &str) {
        match self.kind {
            CTErrorKind::InputError => {
                println!("{}", self.desc);
                if let (Some((pos, len)), Some(input)) = (self.pos, extra_desc) {
                    println!("    {}", input);
                    print!("    ");
                    for _ in 0..pos {
                        print!(" ");
                    }
                    print!("^");
                    for _ in 1..len {
                        print!("~");
                    }
                    println!("");
                }
            },
            CTErrorKind::DatabaseError => {
                println!("{}", self.desc);
            }
        }
    }
}<|endoftext|>


<commit_before>use crate::path::Path;
use serde::{de, ser};
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::result;
use std::str;
use std::string;
use std::sync::Arc;
use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

/// An error that happened serializing or deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

/// Alias for a `Result` with the error type `serde_yaml::Error`.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum ErrorImpl {
    Message(String, Option<Pos>),

    Emit(emitter::EmitError),
    Scan(scanner::ScanError),
    Io(io::Error),
    Utf8(str::Utf8Error),
    FromUtf8(string::FromUtf8Error),

    EndOfStream,
    MoreThanOneDocument,
    RecursionLimitExceeded,

    Shared(Arc<ErrorImpl>),
}

#[derive(Debug)]
pub struct Pos {
    marker: Marker,
    path: String,
}

/// The input location that an error occured.
#[derive(Debug)]
pub struct Location {
    index: usize,
    line: usize,
    column: usize,
}

impl Location {
    /// The byte index of the error
    pub fn index(&self) -> usize {
        self.index
    }

    /// The line of the error
    pub fn line(&self) -> usize {
        self.line
    }

    /// The column of the error
    pub fn column(&self) -> usize {
        self.column
    }

    // This is to keep decoupled with the yaml crate
    #[doc(hidden)]
    fn from_marker(marker: &Marker) -> Self {
        Location {
            // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value
            column: marker.col() + 1,
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl Error {
    /// Returns the Location from the error if one exists.
    ///
    /// Not all types of errors have a location so this can return `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::{Value, Error};
    /// #
    /// // The `@` character as the first character makes this invalid yaml
    /// let invalid_yaml: Result<Value, Error> = serde_yaml::from_str("@invalid_yaml");
    ///
    /// let location = invalid_yaml.unwrap_err().location().unwrap();
    ///
    /// assert_eq!(location.line(), 1);
    /// assert_eq!(location.column(), 1);
    /// ```
    pub fn location(&self) -> Option<Location> {
        match self.0.as_ref() {
            ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)),
            ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())),
            _ => None,
        }
    }
}

pub(crate) fn end_of_stream() -> Error {
    Error(Box::new(ErrorImpl::EndOfStream))
}

pub(crate) fn more_than_one_document() -> Error {
    Error(Box::new(ErrorImpl::MoreThanOneDocument))
}

pub(crate) fn io(err: io::Error) -> Error {
    Error(Box::new(ErrorImpl::Io(err)))
}

pub(crate) fn emitter(err: emitter::EmitError) -> Error {
    Error(Box::new(ErrorImpl::Emit(err)))
}

pub(crate) fn scanner(err: scanner::ScanError) -> Error {
    Error(Box::new(ErrorImpl::Scan(err)))
}

pub(crate) fn str_utf8(err: str::Utf8Error) -> Error {
    Error(Box::new(ErrorImpl::Utf8(err)))
}

pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error {
    Error(Box::new(ErrorImpl::FromUtf8(err)))
}

pub(crate) fn recursion_limit_exceeded() -> Error {
    Error(Box::new(ErrorImpl::RecursionLimitExceeded))
}

pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error {
    if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() {
        *none = Some(Pos {
            marker,
            path: path.to_string(),
        });
    }
    error
}

impl error::Error for Error {
    // TODO: deprecated, remove in next major version.
    fn description(&self) -> &str {
        self.0.description()
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        self.0.source()
    }
}

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

// Remove two layers of verbosity from the debug representation. Humans often
// end up seeing this representation because it is what unwrap() shows.
impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.debug(f)
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl ErrorImpl {
    #[allow(deprecated)]
    fn description(&self) -> &str {
        match self {
            ErrorImpl::Message(msg, _) => msg,
            ErrorImpl::Emit(_) => "emit error",
            ErrorImpl::Scan(_) => "scan error",
            ErrorImpl::Io(err) => error::Error::description(err),
            ErrorImpl::Utf8(err) => error::Error::description(err),
            ErrorImpl::FromUtf8(err) => error::Error::description(err),
            ErrorImpl::EndOfStream => "EOF while parsing a value",
            ErrorImpl::MoreThanOneDocument => {
                "deserializing from YAML containing more than one document is not supported"
            }
            ErrorImpl::RecursionLimitExceeded => "recursion limit exceeded",
            ErrorImpl::Shared(err) => err.description(),
        }
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            ErrorImpl::Scan(err) => Some(err),
            ErrorImpl::Io(err) => Some(err),
            ErrorImpl::Utf8(err) => Some(err),
            ErrorImpl::FromUtf8(err) => Some(err),
            ErrorImpl::Shared(err) => err.source(),
            _ => None,
        }
    }

    fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(msg, Some(Pos { marker, path })) => {
                if path == "." {
                    write!(f, "{}", ScanError::new(*marker, msg))
                } else {
                    write!(f, "{}: {}", path, ScanError::new(*marker, msg))
                }
            }
            ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"),
            ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"),
            ErrorImpl::Scan(err) => Display::fmt(err, f),
            ErrorImpl::Io(err) => Display::fmt(err, f),
            ErrorImpl::Utf8(err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(err) => Display::fmt(err, f),
            ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"),
            ErrorImpl::MoreThanOneDocument => f.write_str(
                "deserializing from YAML containing more than one document is not supported",
            ),
            ErrorImpl::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
            ErrorImpl::Shared(err) => err.display(f),
        }
    }

    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(),
            ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(),
            ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(),
            ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(),
            ErrorImpl::Shared(err) => err.debug(f),
        }
    }
}
<commit_msg>Ignore unused Shared error until multi-doc deserialization<commit_after>use crate::path::Path;
use serde::{de, ser};
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::result;
use std::str;
use std::string;
use std::sync::Arc;
use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

/// An error that happened serializing or deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

/// Alias for a `Result` with the error type `serde_yaml::Error`.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum ErrorImpl {
    Message(String, Option<Pos>),

    Emit(emitter::EmitError),
    Scan(scanner::ScanError),
    Io(io::Error),
    Utf8(str::Utf8Error),
    FromUtf8(string::FromUtf8Error),

    EndOfStream,
    MoreThanOneDocument,
    RecursionLimitExceeded,

    #[allow(dead_code)] // to be used for multi-doc deserialization
    Shared(Arc<ErrorImpl>),
}

#[derive(Debug)]
pub struct Pos {
    marker: Marker,
    path: String,
}

/// The input location that an error occured.
#[derive(Debug)]
pub struct Location {
    index: usize,
    line: usize,
    column: usize,
}

impl Location {
    /// The byte index of the error
    pub fn index(&self) -> usize {
        self.index
    }

    /// The line of the error
    pub fn line(&self) -> usize {
        self.line
    }

    /// The column of the error
    pub fn column(&self) -> usize {
        self.column
    }

    // This is to keep decoupled with the yaml crate
    #[doc(hidden)]
    fn from_marker(marker: &Marker) -> Self {
        Location {
            // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value
            column: marker.col() + 1,
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl Error {
    /// Returns the Location from the error if one exists.
    ///
    /// Not all types of errors have a location so this can return `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::{Value, Error};
    /// #
    /// // The `@` character as the first character makes this invalid yaml
    /// let invalid_yaml: Result<Value, Error> = serde_yaml::from_str("@invalid_yaml");
    ///
    /// let location = invalid_yaml.unwrap_err().location().unwrap();
    ///
    /// assert_eq!(location.line(), 1);
    /// assert_eq!(location.column(), 1);
    /// ```
    pub fn location(&self) -> Option<Location> {
        match self.0.as_ref() {
            ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)),
            ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())),
            _ => None,
        }
    }
}

pub(crate) fn end_of_stream() -> Error {
    Error(Box::new(ErrorImpl::EndOfStream))
}

pub(crate) fn more_than_one_document() -> Error {
    Error(Box::new(ErrorImpl::MoreThanOneDocument))
}

pub(crate) fn io(err: io::Error) -> Error {
    Error(Box::new(ErrorImpl::Io(err)))
}

pub(crate) fn emitter(err: emitter::EmitError) -> Error {
    Error(Box::new(ErrorImpl::Emit(err)))
}

pub(crate) fn scanner(err: scanner::ScanError) -> Error {
    Error(Box::new(ErrorImpl::Scan(err)))
}

pub(crate) fn str_utf8(err: str::Utf8Error) -> Error {
    Error(Box::new(ErrorImpl::Utf8(err)))
}

pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error {
    Error(Box::new(ErrorImpl::FromUtf8(err)))
}

pub(crate) fn recursion_limit_exceeded() -> Error {
    Error(Box::new(ErrorImpl::RecursionLimitExceeded))
}

pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error {
    if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() {
        *none = Some(Pos {
            marker,
            path: path.to_string(),
        });
    }
    error
}

impl error::Error for Error {
    // TODO: deprecated, remove in next major version.
    fn description(&self) -> &str {
        self.0.description()
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        self.0.source()
    }
}

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

// Remove two layers of verbosity from the debug representation. Humans often
// end up seeing this representation because it is what unwrap() shows.
impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.debug(f)
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl ErrorImpl {
    #[allow(deprecated)]
    fn description(&self) -> &str {
        match self {
            ErrorImpl::Message(msg, _) => msg,
            ErrorImpl::Emit(_) => "emit error",
            ErrorImpl::Scan(_) => "scan error",
            ErrorImpl::Io(err) => error::Error::description(err),
            ErrorImpl::Utf8(err) => error::Error::description(err),
            ErrorImpl::FromUtf8(err) => error::Error::description(err),
            ErrorImpl::EndOfStream => "EOF while parsing a value",
            ErrorImpl::MoreThanOneDocument => {
                "deserializing from YAML containing more than one document is not supported"
            }
            ErrorImpl::RecursionLimitExceeded => "recursion limit exceeded",
            ErrorImpl::Shared(err) => err.description(),
        }
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            ErrorImpl::Scan(err) => Some(err),
            ErrorImpl::Io(err) => Some(err),
            ErrorImpl::Utf8(err) => Some(err),
            ErrorImpl::FromUtf8(err) => Some(err),
            ErrorImpl::Shared(err) => err.source(),
            _ => None,
        }
    }

    fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(msg, Some(Pos { marker, path })) => {
                if path == "." {
                    write!(f, "{}", ScanError::new(*marker, msg))
                } else {
                    write!(f, "{}: {}", path, ScanError::new(*marker, msg))
                }
            }
            ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"),
            ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"),
            ErrorImpl::Scan(err) => Display::fmt(err, f),
            ErrorImpl::Io(err) => Display::fmt(err, f),
            ErrorImpl::Utf8(err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(err) => Display::fmt(err, f),
            ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"),
            ErrorImpl::MoreThanOneDocument => f.write_str(
                "deserializing from YAML containing more than one document is not supported",
            ),
            ErrorImpl::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
            ErrorImpl::Shared(err) => err.display(f),
        }
    }

    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(),
            ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(),
            ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(),
            ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(),
            ErrorImpl::Shared(err) => err.debug(f),
        }
    }
}
<|endoftext|>


<commit_before>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::io::IoError;
use crate::node::Node;
use crate::url_resolver::Fragment;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

/// Errors returned when looking up a resource by URL reference.
#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    /// Error when parsing an [`Href`].
    ///
    /// [`Href`]: allowed_url/enum.Href.html
    HrefError(HrefError),

    /// Used when the public API tries to look up an external URL, which is not allowed.
    ///
    /// This catches the case where a public API wants to be misused to access an external
    /// resource.  For example, `SvgHandle.has_sub("https://evil.com/phone_home#element_id") will
    /// fail with this error.
    CannotLookupExternalReferences,

    /// For internal use only.
    ///
    // FIXME: this is returned internally from Handle.lookup_node(), and gets translated
    // to Ok(false).  Don't expose this internal code in the public API.
    NotFound,
}

impl fmt::Display for DefsLookupErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DefsLookupErrorKind::HrefError(_) => write!(f, "invalid URL"),
            DefsLookupErrorKind::CannotLookupExternalReferences => {
                write!(f, "cannot lookup references to elements in external files")
            }
            DefsLookupErrorKind::NotFound => write!(f, "not found"),
        }
    }
}

/// Errors that can happen while rendering or measuring an SVG document.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    /// An error from the rendering backend.
    Rendering(String),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Tried to reference an SVG element that does not exist.
    IdNotFound,

    /// Tried to reference an SVG element from a fragment identifier that is incorrect.
    InvalidId(String),

    /// Not enough memory was available for rendering.
    OutOfMemory(String),
}

impl From<DefsLookupErrorKind> for RenderingError {
    fn from(e: DefsLookupErrorKind) -> RenderingError {
        match e {
            DefsLookupErrorKind::NotFound => RenderingError::IdNotFound,
            _ => RenderingError::InvalidId(format!("{}", e)),
        }
    }
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::Rendering(ref s) => write!(f, "rendering error: {}", s),
            RenderingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            RenderingError::IdNotFound => write!(f, "element id not found"),
            RenderingError::InvalidId(ref s) => write!(f, "invalid id: {:?}", s),
            RenderingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Rendering(format!("{:?}", e))
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```
/// # use librsvg::doctest_only::AttributeResultExt;
/// # use librsvg::doctest_only::ValueErrorKind;
/// # use librsvg::doctest_only::ElementError;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName};
/// # type FooError = ValueErrorKind;
/// fn parse_foo(value: &str) -> Result<(), FooError>
/// # { Err(ValueErrorKind::value_error("test")) }
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
/// # let attr = QualName::new(
/// #     Some(Prefix::from("")),
/// #     Namespace::from(""),
/// #     LocalName::from(""),
/// # );
/// let result = parse_foo("value").attribute(attr);
/// assert!(result.is_err());
/// # Ok::<(), ElementError>(())
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// XML syntax error.
    XmlParseError(String),

    /// Not enough memory to load the document.
    OutOfMemory(String),

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// An invalid stylesheet was used.
    BadCss,

    /// There is no `<svg>` root element in the XML.
    NoSvgRoot,

    /// I/O error.
    Io(String),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Catch-all for loading errors.
    Other(String),
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::NoSvgRoot => write!(f, "XML does not have <svg> root"),
            LoadingError::Io(ref s) => write!(f, "I/O error: {}", s),
            LoadingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            LoadingError::Other(ref s) => write!(f, "{}", s),
        }
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        // FIXME: this is somewhat fishy; not all GError are I/O errors, but in librsvg
        // most GError do come from gio.  Some come from GdkPixbufLoader, though.
        LoadingError::Io(format!("{}", e))
    }
}

impl From<IoError> for LoadingError {
    fn from(e: IoError) -> LoadingError {
        match e {
            IoError::BadDataUrl => LoadingError::BadUrl,
            IoError::Glib(e) => LoadingError::Io(format!("{}", e)),
        }
    }
}
<commit_msg>RenderingError should not be PartialEq<commit_after>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::io::IoError;
use crate::node::Node;
use crate::url_resolver::Fragment;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

/// Errors returned when looking up a resource by URL reference.
#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    /// Error when parsing an [`Href`].
    ///
    /// [`Href`]: allowed_url/enum.Href.html
    HrefError(HrefError),

    /// Used when the public API tries to look up an external URL, which is not allowed.
    ///
    /// This catches the case where a public API wants to be misused to access an external
    /// resource.  For example, `SvgHandle.has_sub("https://evil.com/phone_home#element_id") will
    /// fail with this error.
    CannotLookupExternalReferences,

    /// For internal use only.
    ///
    // FIXME: this is returned internally from Handle.lookup_node(), and gets translated
    // to Ok(false).  Don't expose this internal code in the public API.
    NotFound,
}

impl fmt::Display for DefsLookupErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DefsLookupErrorKind::HrefError(_) => write!(f, "invalid URL"),
            DefsLookupErrorKind::CannotLookupExternalReferences => {
                write!(f, "cannot lookup references to elements in external files")
            }
            DefsLookupErrorKind::NotFound => write!(f, "not found"),
        }
    }
}

/// Errors that can happen while rendering or measuring an SVG document.
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum RenderingError {
    /// An error from the rendering backend.
    Rendering(String),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Tried to reference an SVG element that does not exist.
    IdNotFound,

    /// Tried to reference an SVG element from a fragment identifier that is incorrect.
    InvalidId(String),

    /// Not enough memory was available for rendering.
    OutOfMemory(String),
}

impl From<DefsLookupErrorKind> for RenderingError {
    fn from(e: DefsLookupErrorKind) -> RenderingError {
        match e {
            DefsLookupErrorKind::NotFound => RenderingError::IdNotFound,
            _ => RenderingError::InvalidId(format!("{}", e)),
        }
    }
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::Rendering(ref s) => write!(f, "rendering error: {}", s),
            RenderingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            RenderingError::IdNotFound => write!(f, "element id not found"),
            RenderingError::InvalidId(ref s) => write!(f, "invalid id: {:?}", s),
            RenderingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Rendering(format!("{:?}", e))
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```
/// # use librsvg::doctest_only::AttributeResultExt;
/// # use librsvg::doctest_only::ValueErrorKind;
/// # use librsvg::doctest_only::ElementError;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName};
/// # type FooError = ValueErrorKind;
/// fn parse_foo(value: &str) -> Result<(), FooError>
/// # { Err(ValueErrorKind::value_error("test")) }
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
/// # let attr = QualName::new(
/// #     Some(Prefix::from("")),
/// #     Namespace::from(""),
/// #     LocalName::from(""),
/// # );
/// let result = parse_foo("value").attribute(attr);
/// assert!(result.is_err());
/// # Ok::<(), ElementError>(())
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// XML syntax error.
    XmlParseError(String),

    /// Not enough memory to load the document.
    OutOfMemory(String),

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// An invalid stylesheet was used.
    BadCss,

    /// There is no `<svg>` root element in the XML.
    NoSvgRoot,

    /// I/O error.
    Io(String),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Catch-all for loading errors.
    Other(String),
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::NoSvgRoot => write!(f, "XML does not have <svg> root"),
            LoadingError::Io(ref s) => write!(f, "I/O error: {}", s),
            LoadingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            LoadingError::Other(ref s) => write!(f, "{}", s),
        }
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        // FIXME: this is somewhat fishy; not all GError are I/O errors, but in librsvg
        // most GError do come from gio.  Some come from GdkPixbufLoader, though.
        LoadingError::Io(format!("{}", e))
    }
}

impl From<IoError> for LoadingError {
    fn from(e: IoError) -> LoadingError {
        match e {
            IoError::BadDataUrl => LoadingError::BadUrl,
            IoError::Glib(e) => LoadingError::Io(format!("{}", e)),
        }
    }
}
<|endoftext|>