<commit_before>// Copyright 2012 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 version of the call operator that takes an immutable receiver.
///
/// # Examples
///
/// Closures automatically implement this trait, which allows them to be
/// invoked. Note, however, that `Fn` takes an immutable reference to any
/// captured variables. To take a mutable capture, implement [`FnMut`], and to
/// consume the capture, implement [`FnOnce`].
///
/// [`FnMut`]: trait.FnMut.html
/// [`FnOnce`]: trait.FnOnce.html
///
/// ```
/// let square = |x| x * x;
/// assert_eq!(square(5), 25);
/// ```
///
/// Closures can also be passed to higher-level functions through a `Fn`
/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of
/// `Fn`).
///
/// ```
/// fn call_with_one<F>(func: F) -> usize
///     where F: Fn(usize) -> usize {
///     func(1)
/// }
///
/// let double = |x| x * 2;
/// assert_eq!(call_with_one(double), 2);
/// ```
#[lang = "fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait Fn<Args> : FnMut<Args> {
    /// This is called when the call operator is used.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a mutable receiver.
///
/// # Examples
///
/// Closures that mutably capture variables automatically implement this trait,
/// which allows them to be invoked.
///
/// ```
/// let mut x = 5;
/// {
///     let mut square_x = || x *= x;
///     square_x();
/// }
/// assert_eq!(x, 25);
/// ```
///
/// Closures can also be passed to higher-level functions through a `FnMut`
/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`).
///
/// ```
/// fn do_twice<F>(mut func: F)
///     where F: FnMut()
/// {
///     func();
///     func();
/// }
///
/// let mut x: usize = 1;
/// {
///     let add_two_to_x = || x += 2;
///     do_twice(add_two_to_x);
/// }
///
/// assert_eq!(x, 5);
/// ```
#[lang = "fn_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait FnMut<Args> : FnOnce<Args> {
    /// This is called when the call operator is used.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a by-value receiver.
///
/// # Examples
///
/// By-value closures automatically implement this trait, which allows them to
/// be invoked.
///
/// ```
/// let x = 5;
/// let square_x = move || x * x;
/// assert_eq!(square_x(), 25);
/// ```
///
/// By-value Closures can also be passed to higher-level functions through a
/// `FnOnce` parameter.
///
/// ```
/// fn consume_with_relish<F>(func: F)
///     where F: FnOnce() -> String
/// {
///     // `func` consumes its captured variables, so it cannot be run more
///     // than once
///     println!("Consumed: {}", func());
///
///     println!("Delicious!");
///
///     // Attempting to invoke `func()` again will throw a `use of moved
///     // value` error for `func`
/// }
///
/// let x = String::from("x");
/// let consume_and_return_x = move || x;
/// consume_with_relish(consume_and_return_x);
///
/// // `consume_and_return_x` can no longer be invoked at this point
/// ```
#[lang = "fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait FnOnce<Args> {
    /// The returned type after the call operator is used.
    #[stable(feature = "fn_once_output", since = "1.12.0")]
    type Output;

    /// This is called when the call operator is used.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

mod impls {
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> Fn for &'a F
        where F : Fn
    {
        extern "rust-call" fn call(&self, args: A) -> F::Output {
            (**self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnMut for &'a F
        where F : Fn
    {
        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
            (**self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnOnce for &'a F
        where F : Fn
    {
        type Output = F::Output;

        extern "rust-call" fn call_once(self, args: A) -> F::Output {
            (*self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnMut for &'a mut F
        where F : FnMut
    {
        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
            (*self).call_mut(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnOnce for &'a mut F
        where F : FnMut
    {
        type Output = F::Output;
        extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
            (*self).call_mut(args)
        }
    }
}
<commit_msg>Revise `Fn`/`FnMut`/`FnOnce` documentation<commit_after>// Copyright 2012 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 version of the call operator that takes an immutable receiver.
///
/// Closures only taking immutable references to captured variables
/// automatically implement this trait, which allows them to be invoked.
/// For mutably referenced captures, see [`FnMut`], and for consuming the
/// capture, see [`FnOnce`].
///
/// You can use the [`Fn`] traits when you want to accept a closure as a
/// parameter. Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any
/// instance of `Fn` can be used where a [`FnMut`] or [`FnOnce`] is expected.
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// more information about closures in general.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in *The Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`FnMut`]: trait.FnMut.html
/// [`FnOnce`]: trait.FnOnce.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// ## Calling a closure
///
/// ```
/// let square = |x| x * x;
/// assert_eq!(square(5), 25);
/// ```
///
/// ## Using a `Fn` parameter
///
/// ```
/// fn call_with_one<F>(func: F) -> usize
///     where F: Fn(usize) -> usize {
///     func(1)
/// }
///
/// let double = |x| x * 2;
/// assert_eq!(call_with_one(double), 2);
/// ```
#[lang = "fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait Fn<Args> : FnMut<Args> {
    /// Performs the call operation.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a mutable receiver.
///
/// Closures that might mutably reference captured variables automatically
/// implement this trait, which allows them to be invoked. For immutably
/// referenced captures, see [`Fn`], and for consuming the captures, see
/// [`FnOnce`].
///
/// You can use the [`Fn`] traits when you want to accept a closure as a
/// parameter. Since [`FnOnce`] is a supertrait of `FnMut`, any instance of
/// `FnMut` can be used where a [`FnOnce`] is expected, and since [`Fn`] is a
/// subtrait of `FnMut`, any instance of [`Fn`] can be used where [`FnMut`] is
/// expected.
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// more information about closures in general.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in *The Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`Fn`]: trait.Fnhtml
/// [`FnOnce`]: trait.FnOnce.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// ## Calling a mutably capturing closure
///
/// ```
/// let mut x = 5;
/// {
///     let mut square_x = || x *= x;
///     square_x();
/// }
/// assert_eq!(x, 25);
/// ```
///
/// ## Using a `FnMut` parameter
///
/// ```
/// fn do_twice<F>(mut func: F)
///     where F: FnMut()
/// {
///     func();
///     func();
/// }
///
/// let mut x: usize = 1;
/// {
///     let add_two_to_x = || x += 2;
///     do_twice(add_two_to_x);
/// }
///
/// assert_eq!(x, 5);
/// ```
#[lang = "fn_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait FnMut<Args> : FnOnce<Args> {
    /// Performs the call operation.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a by-value receiver.
///
/// Closures that might take ownership of captured variables automatically
/// implement this trait, which allows them to be invoked. For immutably
/// referenced captures, see [`Fn`], and for mutably referenced captures,
/// see [`FnMut`].
///
/// You can use the [`Fn`] traits when you want to accept a closure as a
/// parameter. Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any
/// instance of [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected.
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// more information about closures in general.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in *The Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`Fn`]: trait.Fn.html
/// [`FnMut`]: trait.FnMut.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// ## Calling a by-value closure
///
/// ```
/// let x = 5;
/// let square_x = move || x * x;
/// assert_eq!(square_x(), 25);
/// ```
///
/// ## Using a `FnOnce` parameter
///
/// ```
/// fn consume_with_relish<F>(func: F)
///     where F: FnOnce() -> String
/// {
///     // `func` consumes its captured variables, so it cannot be run more
///     // than once.
///     println!("Consumed: {}", func());
///
///     println!("Delicious!");
///
///     // Attempting to invoke `func()` again will throw a `use of moved
///     // value` error for `func`.
/// }
///
/// let x = String::from("x");
/// let consume_and_return_x = move || x;
/// consume_with_relish(consume_and_return_x);
///
/// // `consume_and_return_x` can no longer be invoked at this point
/// ```
#[lang = "fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait FnOnce<Args> {
    /// The returned type after the call operator is used.
    #[stable(feature = "fn_once_output", since = "1.12.0")]
    type Output;

    /// Performs the call operation.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

mod impls {
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> Fn for &'a F
        where F : Fn
    {
        extern "rust-call" fn call(&self, args: A) -> F::Output {
            (**self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnMut for &'a F
        where F : Fn
    {
        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
            (**self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnOnce for &'a F
        where F : Fn
    {
        type Output = F::Output;

        extern "rust-call" fn call_once(self, args: A) -> F::Output {
            (*self).call(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnMut for &'a mut F
        where F : FnMut
    {
        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
            (*self).call_mut(args)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a,A,F:?Sized> FnOnce for &'a mut F
        where F : FnMut
    {
        type Output = F::Output;
        extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
            (*self).call_mut(args)
        }
    }
}
<|endoftext|>


<commit_before>#![crate_type = "dylib"]

extern crate intercom;
extern crate winapi;
use intercom::prelude::*;
use std::convert::TryInto;
use winapi::shared::{minwindef::DWORD, ntdef::ULARGE_INTEGER, windef::HBITMAP};
use winapi::um::{
    objidlbase::STATSTG,
    wingdi::{CreateBitmap, DeleteObject},
};

com_library! {
    on_load=on_load,
    class ThumbnailProvider
}

/// Called when the DLL is loaded.
///
/// Sets up logging to the Cargo.toml directory for debug purposes.
fn on_load()
{
    // Set up logging to the proejct directory.
    use log::LevelFilter;
    simple_logging::log_to_file(
        &format!("{}\\debug.log", env!("CARGO_MANIFEST_DIR")),
        LevelFilter::Trace,
    )
    .unwrap();
}

#[com_class(IInitializeWithStream, IThumbnailProvider)]
#[derive(Default)]
struct ThumbnailProvider
{
    bitmap: std::cell::Cell<Option<HBITMAP>>,
}

impl IInitializeWithStream for ThumbnailProvider
{
    fn initialize(&self, _stream: &ComItf<dyn IStream>, _mode: DWORD) -> ComResult<()>
    {
        // This sample always returns the same thumbnail so we don't need to read
        // the stream itself.
        Ok(())
    }
}

impl IThumbnailProvider for ThumbnailProvider
{
    fn get_thumbnail(&self, cx: u32) -> ComResult<(ComHBITMAP, WTS_ALPHATYPE)>
    {
        // Render a faded circle as an example thumbnail.
        let mut data = Vec::new();
        data.resize((cx * cx) as usize, 0);
        let midpoint = cx as f64 / 2.0;
        for x in 0..cx {
            for y in 0..cx {
                let x_coord = x as f64;
                let y_coord = y as f64;
                let dist_squared = (midpoint - x_coord).powf(2.0) + (midpoint - y_coord).powf(2.0);
                let mut value = (dist_squared.sqrt() / midpoint) * 255.0;
                if value > 255.0 {
                    value = 255.0
                }
                let value = value as u32;
                data[(x * cx + y) as usize] = value + (value << 8) + (value << 16) + (value << 24);
            }
        }

        // Create a bitmap from the data and return it.
        //
        // We'll store the bitmap handle in the struct so it can destroy the data when it's
        // not needed anymore.
        let icx: i32 = cx.try_into().map_err(|_| ComError::E_INVALIDARG)?;
        let bitmap = unsafe { CreateBitmap(icx, icx, 1, 32, data.as_ptr() as *const _) };
        self.bitmap.set(Some(bitmap));
        Ok((ComHBITMAP(bitmap), 0))
    }
}

impl Drop for ThumbnailProvider
{
    fn drop(&mut self)
    {
        // Delete the bitmap once it's not needed anymore.
        if let Some(bitmap) = self.bitmap.get() {
            unsafe { DeleteObject(bitmap as _) };
        }
    }
}

// New types for deriving Intercom traits.

#[derive(intercom::ForeignType, intercom::ExternOutput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComHBITMAP(HBITMAP);

#[derive(intercom::ForeignType, intercom::ExternOutput, intercom::ExternInput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComULARGE_INTEGER(ULARGE_INTEGER);

#[derive(intercom::ForeignType, intercom::ExternOutput, intercom::ExternInput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComSTATSTG(STATSTG);

#[allow(non_camel_case_types)]
type WTS_ALPHATYPE = u32;

// COM interface definitions.

#[com_interface(com_iid = "e357fccd-a995-4576-b01f-234630154e96")]
trait IThumbnailProvider
{
    fn get_thumbnail(&self, cx: u32) -> ComResult<(ComHBITMAP, WTS_ALPHATYPE)>;
}

// The IStream definition is untested since this provider doesn't initialize itself
// from the stream.
#[com_interface(com_iid = "0000000c-0000-0000-C000-000000000046")]
trait IStream
{
    fn clone(&self) -> ComResult<ComRc<dyn IStream>>;
    fn commit(&self, commit_flags: DWORD) -> ComResult<()>;
    fn copy_to(
        &self,
        target: &ComItf<dyn IStream>,
        count: ComULARGE_INTEGER,
    ) -> ComResult<(ComULARGE_INTEGER, ComULARGE_INTEGER)>;
    fn lock_region(
        &self,
        lock_offset: ComULARGE_INTEGER,
        count: ComULARGE_INTEGER,
        lock_type: DWORD,
    ) -> ComResult<()>;
    fn revert(&self) -> ComResult<()>;
    fn seek(&self, move_to: ComULARGE_INTEGER, origin: DWORD) -> ComResult<ComULARGE_INTEGER>;
    fn set_size(&self, new_size: ComULARGE_INTEGER) -> ComResult<()>;
    fn stat(&self, stat: *mut ComSTATSTG, stat_flag: DWORD) -> ComResult<()>;
    fn unlock_region(
        &self,
        lock_offset: ComULARGE_INTEGER,
        count: ComULARGE_INTEGER,
        lock_type: DWORD,
    ) -> ComResult<()>;
}

#[com_interface(com_iid = "b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
trait IInitializeWithStream
{
    fn initialize(&self, stream: &ComItf<dyn IStream>, mode: DWORD) -> ComResult<()>;
}
<commit_msg>Fix ThumbnailProvider after ExternType changes<commit_after>#![crate_type = "dylib"]

extern crate intercom;
extern crate winapi;
use intercom::prelude::*;
use std::convert::TryInto;
use winapi::shared::{minwindef::DWORD, ntdef::ULARGE_INTEGER, windef::HBITMAP};
use winapi::um::{
    objidlbase::STATSTG,
    wingdi::{CreateBitmap, DeleteObject},
};

com_library! {
    on_load=on_load,
    class ThumbnailProvider
}

/// Called when the DLL is loaded.
///
/// Sets up logging to the Cargo.toml directory for debug purposes.
fn on_load()
{
    // Set up logging to the proejct directory.
    use log::LevelFilter;
    simple_logging::log_to_file(
        &format!("{}\\debug.log", env!("CARGO_MANIFEST_DIR")),
        LevelFilter::Trace,
    )
    .unwrap();
}

#[com_class(IInitializeWithStream, IThumbnailProvider)]
#[derive(Default)]
struct ThumbnailProvider
{
    bitmap: std::cell::Cell<Option<HBITMAP>>,
}

impl IInitializeWithStream for ThumbnailProvider
{
    fn initialize(&self, _stream: &ComItf<dyn IStream>, _mode: DWORD) -> ComResult<()>
    {
        // This sample always returns the same thumbnail so we don't need to read
        // the stream itself.
        Ok(())
    }
}

impl IThumbnailProvider for ThumbnailProvider
{
    fn get_thumbnail(&self, cx: u32) -> ComResult<(ComHBITMAP, WTS_ALPHATYPE)>
    {
        // Render a faded circle as an example thumbnail.
        let mut data = Vec::new();
        data.resize((cx * cx) as usize, 0);
        let midpoint = cx as f64 / 2.0;
        for x in 0..cx {
            for y in 0..cx {
                let x_coord = x as f64;
                let y_coord = y as f64;
                let dist_squared = (midpoint - x_coord).powf(2.0) + (midpoint - y_coord).powf(2.0);
                let mut value = (dist_squared.sqrt() / midpoint) * 255.0;
                if value > 255.0 {
                    value = 255.0
                }
                let value = value as u32;
                data[(x * cx + y) as usize] = value + (value << 8) + (value << 16) + (value << 24);
            }
        }

        // Create a bitmap from the data and return it.
        //
        // We'll store the bitmap handle in the struct so it can destroy the data when it's
        // not needed anymore.
        let icx: i32 = cx.try_into().map_err(|_| ComError::E_INVALIDARG)?;
        let bitmap = unsafe { CreateBitmap(icx, icx, 1, 32, data.as_ptr() as *const _) };
        self.bitmap.set(Some(bitmap));
        Ok((ComHBITMAP(bitmap), 0))
    }
}

impl Drop for ThumbnailProvider
{
    fn drop(&mut self)
    {
        // Delete the bitmap once it's not needed anymore.
        if let Some(bitmap) = self.bitmap.get() {
            unsafe { DeleteObject(bitmap as _) };
        }
    }
}

// New types for deriving Intercom traits.

#[derive(intercom::ExternType, intercom::ForeignType, intercom::ExternOutput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComHBITMAP(HBITMAP);

#[derive(intercom::ExternType, intercom::ForeignType, intercom::ExternOutput, intercom::ExternInput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComULARGE_INTEGER(ULARGE_INTEGER);

#[derive(intercom::ExternType, intercom::ForeignType, intercom::ExternOutput, intercom::ExternInput)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
struct ComSTATSTG(STATSTG);

#[allow(non_camel_case_types)]
type WTS_ALPHATYPE = u32;

// COM interface definitions.

#[com_interface(com_iid = "e357fccd-a995-4576-b01f-234630154e96")]
trait IThumbnailProvider
{
    fn get_thumbnail(&self, cx: u32) -> ComResult<(ComHBITMAP, WTS_ALPHATYPE)>;
}

// The IStream definition is untested since this provider doesn't initialize itself
// from the stream.
#[com_interface(com_iid = "0000000c-0000-0000-C000-000000000046")]
trait IStream
{
    fn clone(&self) -> ComResult<ComRc<dyn IStream>>;
    fn commit(&self, commit_flags: DWORD) -> ComResult<()>;
    fn copy_to(
        &self,
        target: &ComItf<dyn IStream>,
        count: ComULARGE_INTEGER,
    ) -> ComResult<(ComULARGE_INTEGER, ComULARGE_INTEGER)>;
    fn lock_region(
        &self,
        lock_offset: ComULARGE_INTEGER,
        count: ComULARGE_INTEGER,
        lock_type: DWORD,
    ) -> ComResult<()>;
    fn revert(&self) -> ComResult<()>;
    fn seek(&self, move_to: ComULARGE_INTEGER, origin: DWORD) -> ComResult<ComULARGE_INTEGER>;
    fn set_size(&self, new_size: ComULARGE_INTEGER) -> ComResult<()>;
    fn stat(&self, stat: *mut ComSTATSTG, stat_flag: DWORD) -> ComResult<()>;
    fn unlock_region(
        &self,
        lock_offset: ComULARGE_INTEGER,
        count: ComULARGE_INTEGER,
        lock_type: DWORD,
    ) -> ComResult<()>;
}

#[com_interface(com_iid = "b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
trait IInitializeWithStream
{
    fn initialize(&self, stream: &ComItf<dyn IStream>, mode: DWORD) -> ComResult<()>;
}
<|endoftext|>


<commit_before>#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

type unw_context_t = ucontext::ucontext_t;

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    // fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_step(cp: *mut unw_cursor_t);
    // fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    // fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    // fn unw_resume(cp: *mut unw_cursor_t);

    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    // fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    // fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    // fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    // fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    // fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    // fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<commit_msg>Uncomment `fn unw_init_local` and add necessary definition of `unw_cursor_t`.<commit_after>#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_step(cp: *mut unw_cursor_t);
    // fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    // fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    // fn unw_resume(cp: *mut unw_cursor_t);

    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    // fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    // fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    // fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    // fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    // fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    // fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<|endoftext|>


<commit_before>extern crate quick_xml;

use std::io::{BufRead};

use quick_xml::{XmlReader, Event, AsStr, Element};
use quick_xml::error::ResultPos;
use std::fmt;

#[test]
fn sample_1_short() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_short.txt"),
        true
    );
}

#[test]
fn sample_1_full() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_full.txt"),
        false
    );
}

#[test]
fn sample_2_short() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_short.txt"),
        true
    );
}

#[test]
fn sample_2_full() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_full.txt"),
        false
    );
}

// #[test]
// fn sample_3_short() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_3_full() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_full.txt"),
//         false
//     );
// }

// #[test]
// fn sample_4_short() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_4_full() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_full.txt"),
//         false
//     );
//
// }
//

#[test]
fn eof_1() {
    test(
        br#"<?xml"#,
        br#"Malformed xml: Unescaped XmlDecl event"#,
        true
    );
}

#[test]
fn bad_1() {
    test(
        br#"<?xml&.,"#,
        br#"1:6 Malformed xml: Unescaped XmlDecl event"#,
        true
    );
}

#[test]
fn dashes_in_comments() {
    test(
        br#"<hello/>"#,
        br#"
            |1:14 Malformed xml: Unexpected token '--'
        "#,
        false
    );

    test(
        br#"<hello/>"#,
        br#"
            |1:14 Malformed xml: Unexpected token '--'
        "#,
        true
    );
}

#[test]
fn tabs_1() {
    test(
        b"\t\t",
        br#"
            StartElement(a)
            StartElement(b)
            EndElement(b)
            EndElement(a)
            EndDocument
        "#,
        true
    );
}
//
// #[test]
// fn issue_83_duplicate_attributes() {
//     test(
//         br#"<hello><some-tag a='10' a="20"></hello>"#,
//         br#"
//             |StartElement(hello)
//             |1:30 Attribute 'a' is redefined
//         "#,
//         true
//     );
// }

#[test]
fn issue_93_large_characters_in_entity_references() {
    test(
        r#"<hello>&𤶼;</hello>"#.as_bytes(),
        r#"
            |StartElement(hello)
            |1:10 Malformed xml: Unexpected entity: 𤶼
            |EndElement(hello)
        "#.as_bytes(),
        true
    )
}

#[test]
fn issue_98_cdata_ending_with_right_bracket() {
    test(
        br#"<hello><![CDATA[Foo [Bar]]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData("Foo [Bar]")
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false
    )
}

#[test]
fn issue_105_unexpected_double_dash() {
    test(
        br#"<hello>-- </hello>"#,
        br#"
            |StartElement(hello)
            |Characters("-- ")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello>--</hello>"#,
        br#"
            |StartElement(hello)
            |Characters("--")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello>--></hello>"#,
        br#"
            |StartElement(hello)
            |Characters("-->")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello><![CDATA[--]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData("--")
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );
}

// #[test]
// fn issue_attribues_have_no_default_namespace () {
//     test(
//         br#"<hello xmlns="urn:foo" x="y"/>"#,
//         br#"
//             |StartElement({urn:foo}hello [x="y"])
//             |EndElement({urn:foo}hello)
//             |EndDocument
//         "#,
//         true
//     );
// }

// clones a lot but that's fine
fn convert_to_quick_xml(s: &str) -> String {

    let mut s = match s.trim() {
        ts if ts.starts_with('|') => &ts[1..],
        s => s
    };

    if !s.is_empty() && s.as_bytes()[0] >= b'0' && s.as_bytes()[0] <= b'9' {
        let p = s.chars().position(|c| c == ' ').unwrap();
        s = &s[(p + 1) ..];
    }

    if s.starts_with("Whitespace") {
        format!("Characters{}", &s[10..])
    } else {
        s.to_owned()
    }
}

fn test(input: &[u8], output: &[u8], is_short: bool) {

    let mut reader = XmlReader::from_reader(input)
        .trim_text(is_short)
        .check_comments(true)
        .namespaced();

    let mut spec_lines = output.lines()
        .map(|line| line.unwrap())
        .enumerate()
        .map(|(i, line)| (i, convert_to_quick_xml(&line)))
        .filter(|&(_, ref line)| !line.trim().is_empty());

    if !is_short {
        reader.next();
    }

    loop {
        let e = reader.next();

        let line = format!("{}", OptEvent(e));

        if let Some((n, spec)) = spec_lines.next() {
            if spec == "EndDocument" {
                break;
            }
            if line != spec {
                const SPLITTER: &'static str = "-------------------";
                panic!("\n{}\nUnexpected event at line {}:\nExpected: {}\nFound:    {}\n{}\n",
                       SPLITTER, n + 1, spec, line, SPLITTER);
            }
        } else {
            if line == "EndDocument" {
                break;
            }
            panic!("Unexpected event: {}", line);
        }

        if !is_short && line.starts_with("StartDocument") {
            // advance next Characters(empty space) ...
            if let Some(Ok((_, Event::Text(ref e)))) = reader.next() {
                if e.content().iter().any(|b| match *b {
                    b' ' | b'\r' | b'\n' | b'\t' => false,
                    _ => true,
                }) {
                    panic!("XmlReader expects empty Text event after a StartDocument");
                }
            } else {
                panic!("XmlReader expects empty Text event after a StartDocument");
            }
        }
    }
}

fn namespace_name(n: &Option<Vec<u8>>, e: &Element) -> String {
    match n {
        &Some(ref n) =>
            format!("{{{}}}{}", n.as_str().unwrap(), e.name().as_str().unwrap()),
        &None => e.name().as_str().unwrap().to_owned(),
    }
}

struct OptEvent(Option<ResultPos<(Option<Vec<u8>>, Event)>>);

impl fmt::Display for OptEvent {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Some(Ok((ref n, Event::Start(ref e)))) => {
                let atts: String = e.attributes().unescaped().map(|a| a.unwrap())
                    .filter(|&(k, _)| k.len() < 5 || &k[..5] != b"xmlns")
                    .map(|(k, v)| format!("{}={:?}", k.as_str().unwrap(), v.as_str().unwrap()))
                    .collect::<Vec<_>>().join(", ");

                let name = namespace_name(n, e);

                if atts.is_empty() {
                    write!(f, "StartElement({})", &name)
                } else {
                    write!(f, "StartElement({} [{}])", &name, &atts)
                }
            },
            Some(Ok((ref n, Event::End(ref e)))) =>
                write!(f, "EndElement({})", namespace_name(n, e)),
            Some(Ok((_, Event::Comment(ref e)))) =>
                write!(f, "Comment({:?})", e.content().as_str().unwrap()),
            Some(Ok((_, Event::CData(ref e)))) =>
                write!(f, "CData({:?})", e.content().as_str().unwrap()),
            Some(Ok((_, Event::Text(ref e)))) => {
                match e.unescaped_content() {
                    Ok(c) => {
                        if c.is_empty() {
                            write!(f, "Characters()")
                        } else {
                            write!(f, "Characters({:?})", c.as_str().unwrap())
                        }
                    },
                    Err((ref e, _)) => write!(f, "{}", e),
                }
            },
            Some(Ok((_, Event::Decl(ref e)))) => {
                let version = e.version().unwrap().as_str().unwrap();
                let encoding = e.encoding().unwrap().unwrap().as_str().unwrap();
                write!(f, "StartDocument({}, {})", version, encoding)
            },
            None => write!(f, "EndDocument"),
            Some(Ok((_, Event::PI(ref e)))) =>
                write!(f, "ProcessingInstruction({}={:?})",
                    e.name().as_str().unwrap(), e.content().as_str().unwrap()),
            Some(Err((ref e, _))) => write!(f, "{}", e),
            Some(Ok((_, Event::DocType(ref e)))) =>
                write!(f, "DocType({})", e.content().as_str().unwrap()),
        }
    }
}
<commit_msg>make duplicate_attributes work<commit_after>extern crate quick_xml;

use std::io::{BufRead};

use quick_xml::{XmlReader, Event, AsStr, Element};
use quick_xml::error::ResultPos;
use std::fmt;

#[test]
fn sample_1_short() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_short.txt"),
        true
    );
}

#[test]
fn sample_1_full() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_full.txt"),
        false
    );
}

#[test]
fn sample_2_short() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_short.txt"),
        true
    );
}

#[test]
fn sample_2_full() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_full.txt"),
        false
    );
}

// #[test]
// fn sample_3_short() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_3_full() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_full.txt"),
//         false
//     );
// }

// #[test]
// fn sample_4_short() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_4_full() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_full.txt"),
//         false
//     );
//
// }
//

#[test]
fn eof_1() {
    test(
        br#"<?xml"#,
        br#"Malformed xml: Unescaped XmlDecl event"#,
        true
    );
}

#[test]
fn bad_1() {
    test(
        br#"<?xml&.,"#,
        br#"1:6 Malformed xml: Unescaped XmlDecl event"#,
        true
    );
}

#[test]
fn dashes_in_comments() {
    test(
        br#"<hello/>"#,
        br#"
            |1:14 Malformed xml: Unexpected token '--'
        "#,
        false
    );

    test(
        br#"<hello/>"#,
        br#"
            |1:14 Malformed xml: Unexpected token '--'
        "#,
        true
    );
}

#[test]
fn tabs_1() {
    test(
        b"\t\t",
        br#"
            StartElement(a)
            StartElement(b)
            EndElement(b)
            EndElement(a)
            EndDocument
        "#,
        true
    );
}

#[test]
fn issue_83_duplicate_attributes() {
    // Error when parsing attributes won't stop main event reader
    // as it is a lazy operation => add ending events
    test(
        br#"<hello><some-tag a='10' a="20"/></hello>"#,
        br#"
            |StartElement(hello)
            |1:30 Malformed xml: Duplicate attribute at position 9 and 16
            |EndElement(some-tag)
            |EndElement(hello)
        "#,
        true
    );
}

#[test]
fn issue_93_large_characters_in_entity_references() {
    test(
        r#"<hello>&𤶼;</hello>"#.as_bytes(),
        r#"
            |StartElement(hello)
            |1:10 Malformed xml: Unexpected entity: 𤶼
            |EndElement(hello)
        "#.as_bytes(),
        true
    )
}

#[test]
fn issue_98_cdata_ending_with_right_bracket() {
    test(
        br#"<hello><![CDATA[Foo [Bar]]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData("Foo [Bar]")
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false
    )
}

#[test]
fn issue_105_unexpected_double_dash() {
    test(
        br#"<hello>-- </hello>"#,
        br#"
            |StartElement(hello)
            |Characters("-- ")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello>--</hello>"#,
        br#"
            |StartElement(hello)
            |Characters("--")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello>--></hello>"#,
        br#"
            |StartElement(hello)
            |Characters("-->")
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );

    test(
        br#"<hello><![CDATA[--]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData("--")
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false
    );
}

// #[test]
// fn issue_attribues_have_no_default_namespace () {
//     test(
//         br#"<hello xmlns="urn:foo" x="y"/>"#,
//         br#"
//             |StartElement({urn:foo}hello [x="y"])
//             |EndElement({urn:foo}hello)
//             |EndDocument
//         "#,
//         true
//     );
// }

// clones a lot but that's fine
fn convert_to_quick_xml(s: &str) -> String {

    let mut s = match s.trim() {
        ts if ts.starts_with('|') => &ts[1..],
        s => s
    };

    if !s.is_empty() && s.as_bytes()[0] >= b'0' && s.as_bytes()[0] <= b'9' {
        let p = s.chars().position(|c| c == ' ').unwrap();
        s = &s[(p + 1) ..];
    }

    if s.starts_with("Whitespace") {
        format!("Characters{}", &s[10..])
    } else {
        s.to_owned()
    }
}

fn test(input: &[u8], output: &[u8], is_short: bool) {

    let mut reader = XmlReader::from_reader(input)
        .trim_text(is_short)
        .check_comments(true)
        .namespaced();

    let mut spec_lines = output.lines()
        .map(|line| line.unwrap())
        .enumerate()
        .map(|(i, line)| (i, convert_to_quick_xml(&line)))
        .filter(|&(_, ref line)| !line.trim().is_empty());

    if !is_short {
        reader.next();
    }

    loop {
        let e = reader.next();

        let line = format!("{}", OptEvent(e));

        if let Some((n, spec)) = spec_lines.next() {
            if spec == "EndDocument" {
                break;
            }
            if line != spec {
                const SPLITTER: &'static str = "-------------------";
                panic!("\n{}\nUnexpected event at line {}:\nExpected: {}\nFound:    {}\n{}\n",
                       SPLITTER, n + 1, spec, line, SPLITTER);
            }
        } else {
            if line == "EndDocument" {
                break;
            }
            panic!("Unexpected event: {}", line);
        }

        if !is_short && line.starts_with("StartDocument") {
            // advance next Characters(empty space) ...
            if let Some(Ok((_, Event::Text(ref e)))) = reader.next() {
                if e.content().iter().any(|b| match *b {
                    b' ' | b'\r' | b'\n' | b'\t' => false,
                    _ => true,
                }) {
                    panic!("XmlReader expects empty Text event after a StartDocument");
                }
            } else {
                panic!("XmlReader expects empty Text event after a StartDocument");
            }
        }
    }
}

fn namespace_name(n: &Option<Vec<u8>>, e: &Element) -> String {
    match n {
        &Some(ref n) =>
            format!("{{{}}}{}", n.as_str().unwrap(), e.name().as_str().unwrap()),
        &None => e.name().as_str().unwrap().to_owned(),
    }
}

struct OptEvent(Option<ResultPos<(Option<Vec<u8>>, Event)>>);

impl fmt::Display for OptEvent {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Some(Ok((ref n, Event::Start(ref e)))) => {
                let mut atts = Vec::new();
                for a in e.attributes().unescaped() {
                    match a {
                        Ok((k, v)) => if k.len() < 5 || &k[..5] != b"xmlns" {
                            atts.push(format!("{}={:?}", k.as_str().unwrap(), v.as_str().unwrap()));
                        },
                        Err((e, _)) => return write!(f, "{}", e),
                    }
                }
                let name = namespace_name(n, e);
                if atts.is_empty() {
                    write!(f, "StartElement({})", &name)
                } else {
                    write!(f, "StartElement({} [{}])", &name, &atts.join(", "))
                }
            },
            Some(Ok((ref n, Event::End(ref e)))) =>
                write!(f, "EndElement({})", namespace_name(n, e)),
            Some(Ok((_, Event::Comment(ref e)))) =>
                write!(f, "Comment({:?})", e.content().as_str().unwrap()),
            Some(Ok((_, Event::CData(ref e)))) =>
                write!(f, "CData({:?})", e.content().as_str().unwrap()),
            Some(Ok((_, Event::Text(ref e)))) => {
                match e.unescaped_content() {
                    Ok(c) => {
                        if c.is_empty() {
                            write!(f, "Characters()")
                        } else {
                            write!(f, "Characters({:?})", c.as_str().unwrap())
                        }
                    },
                    Err((ref e, _)) => write!(f, "{}", e),
                }
            },
            Some(Ok((_, Event::Decl(ref e)))) => {
                let version = e.version().unwrap().as_str().unwrap();
                let encoding = e.encoding().unwrap().unwrap().as_str().unwrap();
                write!(f, "StartDocument({}, {})", version, encoding)
            },
            None => write!(f, "EndDocument"),
            Some(Ok((_, Event::PI(ref e)))) =>
                write!(f, "ProcessingInstruction({}={:?})",
                    e.name().as_str().unwrap(), e.content().as_str().unwrap()),
            Some(Err((ref e, _))) => write!(f, "{}", e),
            Some(Ok((_, Event::DocType(ref e)))) =>
                write!(f, "DocType({})", e.content().as_str().unwrap()),
        }
    }
}
<|endoftext|>


<commit_before>use color_eyre::eyre::{bail, Result};
use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
    process::Command,
};

use crate::Config;

#[derive(Default, Debug)]
pub struct Dependencies {
    /// All paths that must be imported with `-L dependency=`. This is for
    /// finding proc macros run on the host and dependencies for the target.
    pub import_paths: Vec<PathBuf>,
    /// The name as chosen in the `Cargo.toml` and its corresponding rmeta file.
    pub dependencies: Vec<(String, PathBuf)>,
}

/// Compiles dependencies and returns the crate names and corresponding rmeta files.
pub fn build_dependencies(config: &Config) -> Result<Dependencies> {
    let manifest_path = match &config.dependencies_crate_manifest_path {
        Some(path) => path,
        None => return Ok(Default::default()),
    };
    let (program, args, envs): (&Path, &[_], &[_]) = match &config.dependency_builder {
        Some(db) => (&db.program, &db.args, &db.envs),
        None => (Path::new("cargo"), &[], &[]),
    };
    let mut build = Command::new(program);
    build.args(args);
    // HACK: we're using `cargo run` (or `cargo miri run`), because the latter does not
    // support `cargo miri build` yet.
    build.arg("run");

    if let Some(target) = &config.target {
        build.arg(format!("--target={target}"));
    }

    // Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
    let setup_command = |cmd: &mut Command| {
        cmd.envs(envs.iter().map(|(k, v)| (k, v)));
        cmd.arg("--manifest-path").arg(manifest_path);
    };

    setup_command(&mut build);
    build.arg("--message-format=json");

    let output = build.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to compile dependencies:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    // Collect all artifacts generated
    let output = output.stdout;
    let output = String::from_utf8(output)?;
    let mut import_paths: HashSet<PathBuf> = HashSet::new();
    let mut artifacts: HashMap<_, _> = output
        .lines()
        .filter_map(|line| {
            let message = serde_json::from_str::<cargo_metadata::Message>(line).ok()?;
            if let cargo_metadata::Message::CompilerArtifact(artifact) = message {
                for filename in &artifact.filenames {
                    import_paths.insert(filename.parent().unwrap().into());
                }
                let filename = artifact
                    .filenames
                    .into_iter()
                    .find(|filename| filename.extension() == Some("rmeta"))?;
                Some((artifact.package_id, filename.into_std_path_buf()))
            } else {
                None
            }
        })
        .collect();

    // Check which crates are mentioned in the crate itself
    let mut metadata = cargo_metadata::MetadataCommand::new().cargo_command();
    setup_command(&mut metadata);
    let output = metadata.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to run cargo-metadata:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    let output = output.stdout;
    let output = String::from_utf8(output)?;

    for line in output.lines() {
        if !line.starts_with('{') {
            continue;
        }
        let metadata: cargo_metadata::Metadata = serde_json::from_str(line)?;
        // Only take artifacts that are defined in the Cargo.toml

        // First, find the root artifact
        let root = metadata
            .packages
            .iter()
            .find(|package| {
                package.manifest_path.as_std_path().canonicalize().unwrap()
                    == manifest_path.canonicalize().unwrap()
            })
            .unwrap();

        // Then go over all of its dependencies
        let dependencies = root
            .dependencies
            .iter()
            .map(|package| {
                // Get the id for the package matching the version requirement of the dep
                let id = &metadata
                    .packages
                    .iter()
                    .find(|&dep| dep.name == package.name && package.req.matches(&dep.version))
                    .expect("dependency does not exist")
                    .id;
                // Return the name chosen in `Cargo.toml` and the path to the corresponding artifact
                (
                    package.rename.clone().unwrap_or_else(|| package.name.clone()),
                    artifacts.remove(id).expect("package without artifact"),
                )
            })
            .collect();
        let import_paths = import_paths.into_iter().collect();
        return Ok(Dependencies { dependencies, import_paths });
    }

    bail!("no json found in cargo-metadata output")
}
<commit_msg>ui_test: build dependencies in locked mode unless bless is enabled<commit_after>use color_eyre::eyre::{bail, Result};
use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
    process::Command,
};

use crate::{Config, OutputConflictHandling};

#[derive(Default, Debug)]
pub struct Dependencies {
    /// All paths that must be imported with `-L dependency=`. This is for
    /// finding proc macros run on the host and dependencies for the target.
    pub import_paths: Vec<PathBuf>,
    /// The name as chosen in the `Cargo.toml` and its corresponding rmeta file.
    pub dependencies: Vec<(String, PathBuf)>,
}

/// Compiles dependencies and returns the crate names and corresponding rmeta files.
pub fn build_dependencies(config: &Config) -> Result<Dependencies> {
    let manifest_path = match &config.dependencies_crate_manifest_path {
        Some(path) => path,
        None => return Ok(Default::default()),
    };
    let (program, args, envs): (&Path, &[_], &[_]) = match &config.dependency_builder {
        Some(db) => (&db.program, &db.args, &db.envs),
        None => (Path::new("cargo"), &[], &[]),
    };
    let mut build = Command::new(program);
    build.args(args);
    // HACK: we're using `cargo run` (or `cargo miri run`), because the latter does not
    // support `cargo miri build` yet.
    build.arg("run");

    if let Some(target) = &config.target {
        build.arg(format!("--target={target}"));
    }

    // Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
    let setup_command = |cmd: &mut Command| {
        cmd.envs(envs.iter().map(|(k, v)| (k, v)));
        cmd.arg("--manifest-path").arg(manifest_path);
        if matches!(config.output_conflict_handling, OutputConflictHandling::Error) {
            cmd.arg("--locked");
        }
    };

    setup_command(&mut build);
    build.arg("--message-format=json");

    let output = build.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to compile dependencies:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    // Collect all artifacts generated
    let output = output.stdout;
    let output = String::from_utf8(output)?;
    let mut import_paths: HashSet<PathBuf> = HashSet::new();
    let mut artifacts: HashMap<_, _> = output
        .lines()
        .filter_map(|line| {
            let message = serde_json::from_str::<cargo_metadata::Message>(line).ok()?;
            if let cargo_metadata::Message::CompilerArtifact(artifact) = message {
                for filename in &artifact.filenames {
                    import_paths.insert(filename.parent().unwrap().into());
                }
                let filename = artifact
                    .filenames
                    .into_iter()
                    .find(|filename| filename.extension() == Some("rmeta"))?;
                Some((artifact.package_id, filename.into_std_path_buf()))
            } else {
                None
            }
        })
        .collect();

    // Check which crates are mentioned in the crate itself
    let mut metadata = cargo_metadata::MetadataCommand::new().cargo_command();
    setup_command(&mut metadata);
    let output = metadata.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to run cargo-metadata:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    let output = output.stdout;
    let output = String::from_utf8(output)?;

    for line in output.lines() {
        if !line.starts_with('{') {
            continue;
        }
        let metadata: cargo_metadata::Metadata = serde_json::from_str(line)?;
        // Only take artifacts that are defined in the Cargo.toml

        // First, find the root artifact
        let root = metadata
            .packages
            .iter()
            .find(|package| {
                package.manifest_path.as_std_path().canonicalize().unwrap()
                    == manifest_path.canonicalize().unwrap()
            })
            .unwrap();

        // Then go over all of its dependencies
        let dependencies = root
            .dependencies
            .iter()
            .map(|package| {
                // Get the id for the package matching the version requirement of the dep
                let id = &metadata
                    .packages
                    .iter()
                    .find(|&dep| dep.name == package.name && package.req.matches(&dep.version))
                    .expect("dependency does not exist")
                    .id;
                // Return the name chosen in `Cargo.toml` and the path to the corresponding artifact
                (
                    package.rename.clone().unwrap_or_else(|| package.name.clone()),
                    artifacts.remove(id).expect("package without artifact"),
                )
            })
            .collect();
        let import_paths = import_paths.into_iter().collect();
        return Ok(Dependencies { dependencies, import_paths });
    }

    bail!("no json found in cargo-metadata output")
}
<|endoftext|>


<commit_before>use std::{
    fmt::Write,
    path::{Path, PathBuf},
};

use regex::Regex;

#[derive(serde::Deserialize, Debug)]
struct RustcMessage {
    rendered: Option<String>,
    spans: Vec<Span>,
    level: String,
    message: String,
    children: Vec<RustcMessage>,
}

#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub(crate) enum Level {
    Error = 4,
    Warn = 3,
    Help = 2,
    Note = 1,
    /// Only used for "For more information about this error, try `rustc --explain EXXXX`".
    FailureNote = 0,
}

#[derive(Debug)]
pub(crate) struct Message {
    pub(crate) level: Level,
    pub(crate) message: String,
}

/// Information about macro expansion.
#[derive(serde::Deserialize, Debug)]
struct Expansion {
    span: Span,
}

#[derive(serde::Deserialize, Debug)]
struct Span {
    line_start: usize,
    file_name: PathBuf,
    expansion: Option<Box<Expansion>>,
}

impl std::str::FromStr for Level {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "ERROR" | "error" => Ok(Self::Error),
            "WARN" | "warning" => Ok(Self::Warn),
            "HELP" | "help" => Ok(Self::Help),
            "NOTE" | "note" => Ok(Self::Note),
            "failure-note" => Ok(Self::FailureNote),
            _ => Err(format!("unknown level `{s}`")),
        }
    }
}

#[derive(Debug)]
pub(crate) struct Diagnostics {
    /// Rendered and concatenated version of all diagnostics.
    /// This is equivalent to non-json diagnostics.
    pub rendered: String,
    /// Per line, a list of messages for that line.
    pub messages: Vec<Vec<Message>>,
    /// Messages not on any line (usually because they are from libstd)
    pub messages_from_unknown_file_or_line: Vec<Message>,
}

impl RustcMessage {
    fn line(&self, file: &Path) -> Option<usize> {
        self.spans.iter().find_map(|span| span.line(file))
    }

    /// Put the message and its children into the line-indexed list.
    fn insert_recursive(
        self,
        file: &Path,
        messages: &mut Vec<Vec<Message>>,
        messages_from_unknown_file_or_line: &mut Vec<Message>,
        line: Option<usize>,
    ) {
        let line = self.line(file).or(line);
        let msg = Message { level: self.level.parse().unwrap(), message: self.message };
        if let Some(line) = line {
            if messages.len() <= line {
                messages.resize_with(line + 1, Vec::new);
            }
            messages[line].push(msg);
        // All other messages go into the general bin, unless they are specifically of the
        // "aborting due to X previous errors" variety, as we never want to match those. They
        // only count the number of errors and provide no useful information about the tests.
        } else if !(msg.message.starts_with("aborting due to")
            && msg.message.contains("previous error"))
        {
            messages_from_unknown_file_or_line.push(msg);
        }
        for child in self.children {
            child.insert_recursive(file, messages, messages_from_unknown_file_or_line, line)
        }
    }
}

impl Span {
    /// Returns a line number *in the given file*, if possible.
    fn line(&self, file: &Path) -> Option<usize> {
        if self.file_name == file {
            Some(self.line_start)
        } else {
            self.expansion.as_ref()?.span.line(file)
        }
    }
}

pub(crate) fn filter_annotations_from_rendered(rendered: &str) -> std::borrow::Cow<'_, str> {
    let annotations = Regex::new(r"\s*//~.*").unwrap();
    annotations.replace_all(&rendered, "")
}

pub(crate) fn process(file: &Path, stderr: &[u8]) -> Diagnostics {
    let stderr = std::str::from_utf8(&stderr).unwrap();
    let mut rendered = String::new();
    let mut messages = vec![];
    let mut messages_from_unknown_file_or_line = vec![];
    for line in stderr.lines() {
        if line.starts_with("{") {
            match serde_json::from_str::<RustcMessage>(line) {
                Ok(msg) => {
                    write!(
                        rendered,
                        "{}",
                        filter_annotations_from_rendered(msg.rendered.as_ref().unwrap())
                    )
                    .unwrap();
                    msg.insert_recursive(
                        file,
                        &mut messages,
                        &mut messages_from_unknown_file_or_line,
                        None,
                    );
                }
                Err(err) =>
                    panic!("failed to parse rustc JSON output at line: {}\nerr:{}", line, err),
            }
        } else {
            // FIXME: do we want to throw interpreter stderr into a separate file?
            writeln!(rendered, "{}", line).unwrap();
        }
    }
    Diagnostics { rendered, messages, messages_from_unknown_file_or_line }
}
<commit_msg>Auto merge of #2237 - RalfJung:ice, r=oli-obk<commit_after>use std::{
    fmt::Write,
    path::{Path, PathBuf},
};

use regex::Regex;

#[derive(serde::Deserialize, Debug)]
struct RustcMessage {
    rendered: Option<String>,
    spans: Vec<Span>,
    level: String,
    message: String,
    children: Vec<RustcMessage>,
}

#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub(crate) enum Level {
    Ice = 5,
    Error = 4,
    Warn = 3,
    Help = 2,
    Note = 1,
    /// Only used for "For more information about this error, try `rustc --explain EXXXX`".
    FailureNote = 0,
}

#[derive(Debug)]
pub(crate) struct Message {
    pub(crate) level: Level,
    pub(crate) message: String,
}

/// Information about macro expansion.
#[derive(serde::Deserialize, Debug)]
struct Expansion {
    span: Span,
}

#[derive(serde::Deserialize, Debug)]
struct Span {
    line_start: usize,
    file_name: PathBuf,
    expansion: Option<Box<Expansion>>,
}

impl std::str::FromStr for Level {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "ERROR" | "error" => Ok(Self::Error),
            "WARN" | "warning" => Ok(Self::Warn),
            "HELP" | "help" => Ok(Self::Help),
            "NOTE" | "note" => Ok(Self::Note),
            "failure-note" => Ok(Self::FailureNote),
            "error: internal compiler error" => Ok(Self::Ice),
            _ => Err(format!("unknown level `{s}`")),
        }
    }
}

#[derive(Debug)]
pub(crate) struct Diagnostics {
    /// Rendered and concatenated version of all diagnostics.
    /// This is equivalent to non-json diagnostics.
    pub rendered: String,
    /// Per line, a list of messages for that line.
    pub messages: Vec<Vec<Message>>,
    /// Messages not on any line (usually because they are from libstd)
    pub messages_from_unknown_file_or_line: Vec<Message>,
}

impl RustcMessage {
    fn line(&self, file: &Path) -> Option<usize> {
        self.spans.iter().find_map(|span| span.line(file))
    }

    /// Put the message and its children into the line-indexed list.
    fn insert_recursive(
        self,
        file: &Path,
        messages: &mut Vec<Vec<Message>>,
        messages_from_unknown_file_or_line: &mut Vec<Message>,
        line: Option<usize>,
    ) {
        let line = self.line(file).or(line);
        let msg = Message { level: self.level.parse().unwrap(), message: self.message };
        if let Some(line) = line {
            if messages.len() <= line {
                messages.resize_with(line + 1, Vec::new);
            }
            messages[line].push(msg);
        // All other messages go into the general bin, unless they are specifically of the
        // "aborting due to X previous errors" variety, as we never want to match those. They
        // only count the number of errors and provide no useful information about the tests.
        } else if !(msg.message.starts_with("aborting due to")
            && msg.message.contains("previous error"))
        {
            messages_from_unknown_file_or_line.push(msg);
        }
        for child in self.children {
            child.insert_recursive(file, messages, messages_from_unknown_file_or_line, line)
        }
    }
}

impl Span {
    /// Returns a line number *in the given file*, if possible.
    fn line(&self, file: &Path) -> Option<usize> {
        if self.file_name == file {
            Some(self.line_start)
        } else {
            self.expansion.as_ref()?.span.line(file)
        }
    }
}

pub(crate) fn filter_annotations_from_rendered(rendered: &str) -> std::borrow::Cow<'_, str> {
    let annotations = Regex::new(r"\s*//~.*").unwrap();
    annotations.replace_all(&rendered, "")
}

pub(crate) fn process(file: &Path, stderr: &[u8]) -> Diagnostics {
    let stderr = std::str::from_utf8(&stderr).unwrap();
    let mut rendered = String::new();
    let mut messages = vec![];
    let mut messages_from_unknown_file_or_line = vec![];
    for line in stderr.lines() {
        if line.starts_with("{") {
            match serde_json::from_str::<RustcMessage>(line) {
                Ok(msg) => {
                    write!(
                        rendered,
                        "{}",
                        filter_annotations_from_rendered(msg.rendered.as_ref().unwrap())
                    )
                    .unwrap();
                    msg.insert_recursive(
                        file,
                        &mut messages,
                        &mut messages_from_unknown_file_or_line,
                        None,
                    );
                }
                Err(err) =>
                    panic!("failed to parse rustc JSON output at line: {}\nerr:{}", line, err),
            }
        } else {
            // FIXME: do we want to throw interpreter stderr into a separate file?
            writeln!(rendered, "{}", line).unwrap();
        }
    }
    Diagnostics { rendered, messages, messages_from_unknown_file_or_line }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use light_arena::Allocator;

use clamp;
use bsdf::{BxDFHolder, LambertianReflection, OrenNayar, BSDF};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use paramset::TextureParams;
use spectrum::Spectrum;
use texture::{TextureFloat, TextureSpectrum};

#[derive(Debug)]
pub struct MatteMaterial {
    kd: Arc<TextureSpectrum>,
    sigma: Arc<TextureFloat>,
    bump_map: Option<Arc<TextureFloat>>,
}

impl MatteMaterial {
    pub fn create(mp: &TextureParams) -> Arc<Material> {
        info!("Creating Matte material");
        let kd = mp.get_spectrum_texture("Kd", &Spectrum::grey(0.5));
        let sigma = mp.get_float_texture("sigma", 0.0);
        let bump_map = mp.get_float_texture_or_none("bumpmap");

        Arc::new(MatteMaterial {
            kd,
            sigma,
            bump_map,
        })
    }
}

impl Material for MatteMaterial {
    fn compute_scattering_functions<'a, 'b>(
        &self,
        si: &mut SurfaceInteraction<'a, 'b>,
        _mode: TransportMode,
        _allow_multiple_lobes: bool,
        arena: &'b Allocator,
    ) {
        let mut bxdfs = BxDFHolder::new(arena);

        if let Some(ref bump_map) = self.bump_map {
            super::bump(bump_map, si);
        }

        let r = self.kd.evaluate(si).clamp();
        let sigma = clamp(self.sigma.evaluate(si), 0.0, 1.0);
        if sigma == 0.0 {
            bxdfs.add(arena <- LambertianReflection::new(r));
        } else {
            bxdfs.add(arena <- OrenNayar::new(r, sigma));
        }

        let bsdf = BSDF::new(si, 1.0, bxdfs.into_slice());
        si.bsdf = Some(Arc::new(bsdf));
    }
}
<commit_msg>Fix bug in matte material<commit_after>use std::sync::Arc;

use light_arena::Allocator;

use clamp;
use bsdf::{BxDFHolder, LambertianReflection, OrenNayar, BSDF};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use paramset::TextureParams;
use spectrum::Spectrum;
use texture::{TextureFloat, TextureSpectrum};

#[derive(Debug)]
pub struct MatteMaterial {
    kd: Arc<TextureSpectrum>,
    sigma: Arc<TextureFloat>,
    bump_map: Option<Arc<TextureFloat>>,
}

impl MatteMaterial {
    pub fn create(mp: &TextureParams) -> Arc<Material> {
        info!("Creating Matte material");
        let kd = mp.get_spectrum_texture("Kd", &Spectrum::grey(0.5));
        let sigma = mp.get_float_texture("sigma", 0.0);
        let bump_map = mp.get_float_texture_or_none("bumpmap");

        Arc::new(MatteMaterial {
            kd,
            sigma,
            bump_map,
        })
    }
}

impl Material for MatteMaterial {
    fn compute_scattering_functions<'a, 'b>(
        &self,
        si: &mut SurfaceInteraction<'a, 'b>,
        _mode: TransportMode,
        _allow_multiple_lobes: bool,
        arena: &'b Allocator,
    ) {
        let mut bxdfs = BxDFHolder::new(arena);

        if let Some(ref bump_map) = self.bump_map {
            super::bump(bump_map, si);
        }

        let r = self.kd.evaluate(si).clamp();
        let sigma = clamp(self.sigma.evaluate(si), 0.0, 1.0);
        if !r.is_black() {
            if sigma == 0.0 {
                bxdfs.add(arena <- LambertianReflection::new(r));
            } else {
                bxdfs.add(arena <- OrenNayar::new(r, sigma));
            }
        }

        let bsdf = BSDF::new(si, 1.0, bxdfs.into_slice());
        si.bsdf = Some(Arc::new(bsdf));
    }
}
<|endoftext|>


<commit_before>use std::ops::{Mul,Add,Sub};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }

    pub fn dot(self, rhs: Vec3<T>) -> T {
         self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }

    pub fn cross(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.y * rhs.z - self.z * rhs.y,
            self.z * rhs.x - self.x * rhs.z,
            self.x * rhs.y - self.y * rhs.x,
            )
    }
}

impl <T> Add<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn add(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.x + rhs.x,
            self.y + rhs.y,
            self.z + rhs.z,
            )
    }
}

impl <T> Sub<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn sub(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.x - rhs.x,
            self.y - rhs.y,
            self.z - rhs.z,
            )
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    pub fn length(& self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u.dot(v);

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_cross_product() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let product = v.cross(w);

        assert_eq!(product, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }

    #[test]
    fn should_form_vector_sum() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v + w;

        assert_eq!(sum, Vec3 { x: 1.0, y: 1.0, z: 0.0 });
    }

    #[test]
    fn should_form_vector_difference() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v - w;

        assert_eq!(sum, Vec3 { x: 1.0, y: -1.0, z: 0.0 });
    }
}
<commit_msg>Implement scalar product<commit_after>use std::ops::{Mul,Add,Sub};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }

    pub fn dot(self, rhs: Vec3<T>) -> T {
         self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }

    pub fn cross(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.y * rhs.z - self.z * rhs.y,
            self.z * rhs.x - self.x * rhs.z,
            self.x * rhs.y - self.y * rhs.x,
            )
    }
}

impl <T> Add<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn add(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.x + rhs.x,
            self.y + rhs.y,
            self.z + rhs.z,
            )
    }
}

impl <T> Sub<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn sub(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.x - rhs.x,
            self.y - rhs.y,
            self.z - rhs.z,
            )
    }
}

impl <T> Mul<T> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn mul(self, rhs: T) -> Vec3<T> {
        Vec3::new(
            self.x * rhs,
            self.y * rhs,
            self.z * rhs,
            )
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    pub fn length(& self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u.dot(v);

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_cross_product() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let product = v.cross(w);

        assert_eq!(product, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }

    #[test]
    fn should_form_vector_sum() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v + w;

        assert_eq!(sum, Vec3 { x: 1.0, y: 1.0, z: 0.0 });
    }

    #[test]
    fn should_form_vector_difference() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v - w;

        assert_eq!(sum, Vec3 { x: 1.0, y: -1.0, z: 0.0 });
    }

    #[test]
    fn should_form_scalar_multiplication() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let c: f64 = 2.0;

        let scalar = v * c;

        assert_eq!(scalar, Vec3 { x: 2.0, y: 0.0, z: 0.0 });
    }
}
<|endoftext|>


<commit_before>use super::super::error;
use super::super::error::Result;
use lazy_static::lazy_static;
use regex::Regex;
use std::collections::hash_map::HashMap;
use std::fs;
use tree_sitter::Point;

// TODO: It would be cooler to do this with a comments query rather than with a regex
// directly.
lazy_static! {
    static ref METADATA_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+), (\d+), (\d+)"#).unwrap();
}

#[derive(Debug, Eq, PartialEq)]
pub struct CaptureInfo {
    pub name: String,
    pub position: Point,
}

#[derive(Debug, Eq, PartialEq)]
struct Assertion {
    position: Point,
    capture_class: String,
    capture_type: String,
}

impl From<regex::Captures<'_>> for Assertion {
    fn from(re: regex::Captures) -> Assertion {
        Assertion {
            capture_class: re.get(1).unwrap().as_str().to_string(),
            capture_type: re.get(2).unwrap().as_str().to_string(),
            position: Point {
                row: re
                    .get(3)
                    .iter()
                    .flat_map(|m| m.as_str().parse::<usize>())
                    .next()
                    .unwrap(),
                column: re
                    .get(4)
                    .iter()
                    .flat_map(|m| m.as_str().parse::<usize>())
                    .next()
                    .unwrap(),
            },
        }
    }
}

pub fn assert_expected_captures(captures: Vec<CaptureInfo>, path: String) -> Result<()> {
    let contents = fs::read_to_string(path)?;

    let assertions: Vec<Assertion> = METADATA_REGEX
        .captures_iter(&contents)
        .map(|c| Assertion::from(c))
        .collect();

    let per_position_index: HashMap<Point, &Assertion> =
        assertions.iter().map(|a| (a.position, a)).collect();

    for capture in &captures {
        let oFound = per_position_index.get(&capture.position);
        if oFound.is_none() {
            continue;
        }
        let found = oFound.unwrap();
        let joined = format!("{}.{}", found.capture_class, found.capture_type);
        if joined != capture.name && capture.name != "name" {
            Err(error::Error::new(format!(
                "Assertion failed: at {}, found {}, expected {}",
                capture.position, capture.name, joined
            )))?
        }
    }
    Ok(())
}
<commit_msg>this is nicer, though<commit_after>use crate::error;
use crate::error::Result;
use lazy_static::lazy_static;
use regex::Regex;
use std::collections::hash_map::HashMap;
use std::fs;
use tree_sitter::Point;

// TODO: It would be cooler to do this with a comments query rather than with a regex
// directly.
lazy_static! {
    static ref METADATA_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+), (\d+), (\d+)"#).unwrap();
}

#[derive(Debug, Eq, PartialEq)]
pub struct CaptureInfo {
    pub name: String,
    pub position: Point,
}

#[derive(Debug, Eq, PartialEq)]
struct Assertion {
    position: Point,
    capture_class: String,
    capture_type: String,
}

impl From<regex::Captures<'_>> for Assertion {
    fn from(re: regex::Captures) -> Assertion {
        Assertion {
            capture_class: re.get(1).unwrap().as_str().to_string(),
            capture_type: re.get(2).unwrap().as_str().to_string(),
            position: Point {
                row: re
                    .get(3)
                    .iter()
                    .flat_map(|m| m.as_str().parse::<usize>())
                    .next()
                    .unwrap(),
                column: re
                    .get(4)
                    .iter()
                    .flat_map(|m| m.as_str().parse::<usize>())
                    .next()
                    .unwrap(),
            },
        }
    }
}

pub fn assert_expected_captures(infos: Vec<CaptureInfo>, path: String) -> Result<()> {
    let contents = fs::read_to_string(path)?;

    let assertions: Vec<Assertion> = METADATA_REGEX
        .captures_iter(&contents)
        .map(|c| Assertion::from(c))
        .collect();

    let per_position_index: HashMap<Point, &Assertion> =
        assertions.iter().map(|a| (a.position, a)).collect();

    for info in &infos {
        if !per_position_index.contains_key(&info.position) {
            continue;
        }
        let found = per_position_index.get(&info.position).unwrap();
        let joined = format!("{}.{}", found.capture_class, found.capture_type);
        if joined != info.name && info.name != "name" {
            Err(error::Error::new(format!(
                "Assertion failed: at {}, found {}, expected {}",
                info.position, info.name, joined
            )))?
        }
    }
    Ok(())
}
<|endoftext|>


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

use rand::{thread_rng, Rng};

use secp;
use secp::{Message, Secp256k1, Signature};
use secp::key::SecretKey;
use secp::pedersen::{Commitment, RangeProof};
use blake2;

use blind::{BlindingFactor, BlindSum};
use extkey::{self, Fingerprint, Identifier};

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Error {
	ExtendedKey(extkey::Error),
	Secp(secp::Error),
	KeyDerivation(String),
}

impl From<secp::Error> for Error {
	fn from(e: secp::Error) -> Error {
		Error::Secp(e)
	}
}

impl From<extkey::Error> for Error {
	fn from(e: extkey::Error) -> Error {
		Error::ExtendedKey(e)
	}
}

#[derive(Clone, Debug)]
pub struct Keychain {
	secp: Secp256k1,
	extkey: extkey::ExtendedKey,
}

impl Keychain {
	pub fn fingerprint(self) -> Fingerprint {
		self.extkey.fingerprint.clone()
	}

	pub fn from_seed(seed: &[u8]) -> Result<Keychain, Error> {
		let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
		let extkey = extkey::ExtendedKey::from_seed(&secp, seed)?;
		let keychain = Keychain {
			secp: secp,
			extkey: extkey,
		};
		Ok(keychain)
	}

	/// For testing - probably not a good idea to use outside of tests.
	pub fn from_random_seed() -> Result<Keychain, Error> {
		let seed: String = thread_rng().gen_ascii_chars().take(16).collect();
		let seed = blake2::blake2b::blake2b(32, &[], seed.as_bytes());
		Keychain::from_seed(seed.as_bytes())
	}

	pub fn derive_pubkey(&self, derivation: u32) -> Result<Identifier, Error> {
		let extkey = self.extkey.derive(&self.secp, derivation)?;
		Ok(extkey.identifier())
	}

	// TODO - this is a work in progress
	// TODO - smarter lookups - can we cache key_id/fingerprint -> derivation
	// number somehow?
	fn derived_key(&self, pubkey: &Identifier) -> Result<SecretKey, Error> {
		for i in 1..10000 {
			let extkey = self.extkey.derive(&self.secp, i)?;
			if extkey.identifier() == *pubkey {
				return Ok(extkey.key);
			}
		}
		Err(Error::KeyDerivation("cannot find one...".to_string()))
	}

	pub fn commit(&self, amount: u64, pubkey: &Identifier) -> Result<Commitment, Error> {
		let skey = self.derived_key(pubkey)?;
		let commit = self.secp.commit(amount, skey)?;
		Ok(commit)
	}

	pub fn switch_commit(&self, pubkey: &Identifier) -> Result<Commitment, Error> {
		let skey = self.derived_key(pubkey)?;
		let commit = self.secp.switch_commit(skey)?;
		Ok(commit)
	}

	pub fn range_proof(
		&self,
		amount: u64,
		pubkey: &Identifier,
		commit: Commitment,
	) -> Result<RangeProof, Error> {
		let skey = self.derived_key(pubkey)?;
		let nonce = self.secp.nonce();
		let range_proof = self.secp.range_proof(0, amount, skey, commit, nonce);
		Ok(range_proof)
	}

	pub fn blind_sum(&self, blind_sum: &BlindSum) -> Result<BlindingFactor, Error> {
		let mut pos_keys: Vec<SecretKey> = blind_sum
			.positive_pubkeys
			.iter()
			.filter_map(|k| self.derived_key(&k).ok())
			.collect();
		println!("pos_keys - {}", pos_keys.len());

		let mut neg_keys: Vec<SecretKey> = blind_sum
			.negative_pubkeys
			.iter()
			.filter_map(|k| self.derived_key(&k).ok())
			.collect();
		println!("neg_keys - {}", neg_keys.len());

		pos_keys.extend(&blind_sum
			.positive_blinding_factors
			.iter()
			.map(|b| b.secret_key())
			.collect::<Vec<SecretKey>>());

		neg_keys.extend(&blind_sum
			.negative_blinding_factors
			.iter()
			.map(|b| b.secret_key())
			.collect::<Vec<SecretKey>>());

		println!("pos_keys all - {}", pos_keys.len());
		println!("neg_keys all - {}", neg_keys.len());

		let blinding = self.secp.blind_sum(pos_keys, neg_keys)?;
		Ok(BlindingFactor::new(blinding))
	}

	pub fn sign(&self, msg: &Message, pubkey: &Identifier) -> Result<Signature, Error> {
		let skey = self.derived_key(pubkey)?;
		let sig = self.secp.sign(msg, &skey)?;
		Ok(sig)
	}

	pub fn sign_with_blinding(
		&self,
		msg: &Message,
		blinding: &BlindingFactor,
	) -> Result<Signature, Error> {
		let sig = self.secp.sign(msg, &blinding.secret_key())?;
		Ok(sig)
	}

	pub fn secp(&self) -> &Secp256k1 {
		&self.secp
	}
}

#[cfg(test)]
mod test {
	use keychain::Keychain;
	use secp;

	#[test]
	fn test_key_derivation() {
		let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);

		let keychain = Keychain::from_random_seed().unwrap();

		// use the keychain to derive a "pubkey" based on the underlying seed
		let pubkey = keychain.derive_pubkey(1).unwrap();

		let msg_bytes = [0; 32];
		let msg = secp::Message::from_slice(&msg_bytes[..]).unwrap();

		// now create a zero commitment using the key on the keychain associated with
		// the pubkey
		let commit = keychain.commit(0, &pubkey).unwrap();

		// now check we can use our key to verify a signature from this zero commitment
		let sig = keychain.sign(&msg, &pubkey).unwrap();
		secp.verify_from_commit(&msg, &sig, &commit).unwrap();
	}
}
<commit_msg>cleanup some println! (#153)<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rand::{thread_rng, Rng};

use secp;
use secp::{Message, Secp256k1, Signature};
use secp::key::SecretKey;
use secp::pedersen::{Commitment, RangeProof};
use blake2;

use blind::{BlindingFactor, BlindSum};
use extkey::{self, Fingerprint, Identifier};

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Error {
	ExtendedKey(extkey::Error),
	Secp(secp::Error),
	KeyDerivation(String),
}

impl From<secp::Error> for Error {
	fn from(e: secp::Error) -> Error {
		Error::Secp(e)
	}
}

impl From<extkey::Error> for Error {
	fn from(e: extkey::Error) -> Error {
		Error::ExtendedKey(e)
	}
}

#[derive(Clone, Debug)]
pub struct Keychain {
	secp: Secp256k1,
	extkey: extkey::ExtendedKey,
}

impl Keychain {
	pub fn fingerprint(self) -> Fingerprint {
		self.extkey.fingerprint.clone()
	}

	pub fn from_seed(seed: &[u8]) -> Result<Keychain, Error> {
		let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
		let extkey = extkey::ExtendedKey::from_seed(&secp, seed)?;
		let keychain = Keychain {
			secp: secp,
			extkey: extkey,
		};
		Ok(keychain)
	}

	/// For testing - probably not a good idea to use outside of tests.
	pub fn from_random_seed() -> Result<Keychain, Error> {
		let seed: String = thread_rng().gen_ascii_chars().take(16).collect();
		let seed = blake2::blake2b::blake2b(32, &[], seed.as_bytes());
		Keychain::from_seed(seed.as_bytes())
	}

	pub fn derive_pubkey(&self, derivation: u32) -> Result<Identifier, Error> {
		let extkey = self.extkey.derive(&self.secp, derivation)?;
		Ok(extkey.identifier())
	}

	// TODO - this is a work in progress
	// TODO - smarter lookups - can we cache key_id/fingerprint -> derivation
	// number somehow?
	fn derived_key(&self, pubkey: &Identifier) -> Result<SecretKey, Error> {
		for i in 1..10000 {
			let extkey = self.extkey.derive(&self.secp, i)?;
			if extkey.identifier() == *pubkey {
				return Ok(extkey.key);
			}
		}
		Err(Error::KeyDerivation("cannot find one...".to_string()))
	}

	pub fn commit(&self, amount: u64, pubkey: &Identifier) -> Result<Commitment, Error> {
		let skey = self.derived_key(pubkey)?;
		let commit = self.secp.commit(amount, skey)?;
		Ok(commit)
	}

	pub fn switch_commit(&self, pubkey: &Identifier) -> Result<Commitment, Error> {
		let skey = self.derived_key(pubkey)?;
		let commit = self.secp.switch_commit(skey)?;
		Ok(commit)
	}

	pub fn range_proof(
		&self,
		amount: u64,
		pubkey: &Identifier,
		commit: Commitment,
	) -> Result<RangeProof, Error> {
		let skey = self.derived_key(pubkey)?;
		let nonce = self.secp.nonce();
		let range_proof = self.secp.range_proof(0, amount, skey, commit, nonce);
		Ok(range_proof)
	}

	pub fn blind_sum(&self, blind_sum: &BlindSum) -> Result<BlindingFactor, Error> {
		let mut pos_keys: Vec<SecretKey> = blind_sum
			.positive_pubkeys
			.iter()
			.filter_map(|k| self.derived_key(&k).ok())
			.collect();

		let mut neg_keys: Vec<SecretKey> = blind_sum
			.negative_pubkeys
			.iter()
			.filter_map(|k| self.derived_key(&k).ok())
			.collect();

		pos_keys.extend(&blind_sum
			.positive_blinding_factors
			.iter()
			.map(|b| b.secret_key())
			.collect::<Vec<SecretKey>>());

		neg_keys.extend(&blind_sum
			.negative_blinding_factors
			.iter()
			.map(|b| b.secret_key())
			.collect::<Vec<SecretKey>>());

		let blinding = self.secp.blind_sum(pos_keys, neg_keys)?;
		Ok(BlindingFactor::new(blinding))
	}

	pub fn sign(&self, msg: &Message, pubkey: &Identifier) -> Result<Signature, Error> {
		let skey = self.derived_key(pubkey)?;
		let sig = self.secp.sign(msg, &skey)?;
		Ok(sig)
	}

	pub fn sign_with_blinding(
		&self,
		msg: &Message,
		blinding: &BlindingFactor,
	) -> Result<Signature, Error> {
		let sig = self.secp.sign(msg, &blinding.secret_key())?;
		Ok(sig)
	}

	pub fn secp(&self) -> &Secp256k1 {
		&self.secp
	}
}

#[cfg(test)]
mod test {
	use keychain::Keychain;
	use secp;

	#[test]
	fn test_key_derivation() {
		let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);

		let keychain = Keychain::from_random_seed().unwrap();

		// use the keychain to derive a "pubkey" based on the underlying seed
		let pubkey = keychain.derive_pubkey(1).unwrap();

		let msg_bytes = [0; 32];
		let msg = secp::Message::from_slice(&msg_bytes[..]).unwrap();

		// now create a zero commitment using the key on the keychain associated with
		// the pubkey
		let commit = keychain.commit(0, &pubkey).unwrap();

		// now check we can use our key to verify a signature from this zero commitment
		let sig = keychain.sign(&msg, &pubkey).unwrap();
		secp.verify_from_commit(&msg, &sig, &commit).unwrap();
	}
}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Response<T> {
    Success {
        result: T,
    },
    Error {
        description: String,
        parameters: Option<ResponseParameters>,
    },
}

impl<T: Deserialize> Deserialize for Response<T> {
    fn deserialize<D>(deserializer: D) -> Result<Response<T>, D::Error> where D: Deserializer {
        let raw: RawResponse<T> = Deserialize::deserialize(deserializer)?;
        match (raw.ok, raw.description, raw.result) {
            (false, Some(description), None) => {
                Ok(Response::Error {
                    description: description,
                    parameters: raw.parameters,
                })
            },
            (true, None, Some(result)) => {
                Ok(Response::Success {
                    result: result,
                })
            }
            _ => Err(D::Error::custom("ambiguous response")),
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawResponse<T> {
    ok: bool,
    description: Option<String>,
    result: Option<T>,
    parameters: Option<ResponseParameters>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct ResponseParameters {
    pub migrate_to_chat_id: Option<Integer>,
    pub retry_after: Option<Integer>,
}
<commit_msg>docs: document response types<commit_after>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

/// All API responses are from this type. Mostly used internal.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Response<T> {
    /// Request was successful.
    Success {
        /// Response result.
        result: T,
    },
    /// Request was unsuccessful.
    Error {
        /// Human-readable description of the result.
        description: String,
        /// Contains information about why a request was unsuccessful.
        parameters: Option<ResponseParameters>,
    },
}

impl<T: Deserialize> Deserialize for Response<T> {
    fn deserialize<D>(deserializer: D) -> Result<Response<T>, D::Error> where D: Deserializer {
        let raw: RawResponse<T> = Deserialize::deserialize(deserializer)?;
        match (raw.ok, raw.description, raw.result) {
            (false, Some(description), None) => {
                Ok(Response::Error {
                    description: description,
                    parameters: raw.parameters,
                })
            },
            (true, None, Some(result)) => {
                Ok(Response::Success {
                    result: result,
                })
            }
            _ => Err(D::Error::custom("ambiguous response")),
        }
    }
}

/// Directly mapped telegram API response.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawResponse<T> {
    /// If ‘ok’ equals true, the request was successful.
    ok: bool,
    /// Human-readable description of the result.
    description: Option<String>,
    /// Result of the query.
    result: Option<T>,
    /// Information about why a request was unsuccessful.
    parameters: Option<ResponseParameters>,
}

/// Contains information about why a request was unsuccessful.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct ResponseParameters {
    /// The group has been migrated to a supergroup with the specified identifier.
    pub migrate_to_chat_id: Option<Integer>,
    /// In case of exceeding flood control, the number of seconds left to wait
    /// before the request can be repeated.
    pub retry_after: Option<Integer>,
}
<|endoftext|>