<commit_before>
use {
    AddRound,
    BackEnd,
    Borrowed,
    Clear,
    Color,
    Field,
    Fill,
    Matrix2d,
    Rectangle,
    RoundRectangleColorContext,
    Value,
    View
};
use vecmath::{
    identity,
};
use triangulation::{
    rect_tri_list_xy_f32,
    rect_tri_list_rgba_f32,
};
use internal::{
    CanColor,
    CanRectangle,
    CanTransform,
    HasColor,
    HasRectangle,
    HasTransform,
};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> HasTransform<'a, Matrix2d> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, RectangleColorContext<'a>, Matrix2d> for RectangleColorContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> HasColor<'a, Color> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_color(&'a self) -> &'a Color {
        self.color.get()
    }
}

impl<'a> CanColor<'a, RectangleColorContext<'a>, Color> for RectangleColorContext<'a> {
    #[inline(always)]
    fn color(&'a self, value: Color) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value(value),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> HasRectangle<'a, Rectangle> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_rectangle(&'a self) -> &'a Rectangle {
        self.rect.get()
    }
}

impl<'a> CanRectangle<'a, RectangleColorContext<'a>, Rectangle> for RectangleColorContext<'a> {
    #[inline(always)]
    fn rectangle(&'a self, rect: Rectangle) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(rect),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let rect = self.rect.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            back_end.tri_list_xy_f32_rgba_f32(
                rect_tri_list_xy_f32(self.transform.get(), rect),
                rect_tri_list_rgba_f32(color)
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}

impl<'a> AddRound<'a, RoundRectangleColorContext<'a>> for RectangleColorContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            rect: Borrowed(self.rect.get()),
            round_radius: Value(radius),
        }
    }
}

impl<'a> View<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}
<commit_msg>Implemented `AddImage` for `RectangleColorContext`<commit_after>
use {
    AddImage,
    AddRound,
    BackEnd,
    Borrowed,
    Clear,
    Color,
    Field,
    Fill,
    Image,
    ImageRectangleColorContext,
    Matrix2d,
    Rectangle,
    RoundRectangleColorContext,
    Value,
    View
};
use vecmath::{
    identity,
};
use triangulation::{
    rect_tri_list_xy_f32,
    rect_tri_list_rgba_f32,
};
use internal::{
    CanColor,
    CanRectangle,
    CanTransform,
    HasColor,
    HasRectangle,
    HasTransform,
};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> HasTransform<'a, Matrix2d> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, RectangleColorContext<'a>, Matrix2d> for RectangleColorContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> HasColor<'a, Color> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_color(&'a self) -> &'a Color {
        self.color.get()
    }
}

impl<'a> CanColor<'a, RectangleColorContext<'a>, Color> for RectangleColorContext<'a> {
    #[inline(always)]
    fn color(&'a self, value: Color) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value(value),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> HasRectangle<'a, Rectangle> for RectangleColorContext<'a> {
    #[inline(always)]
    fn get_rectangle(&'a self) -> &'a Rectangle {
        self.rect.get()
    }
}

impl<'a> CanRectangle<'a, RectangleColorContext<'a>, Rectangle> for RectangleColorContext<'a> {
    #[inline(always)]
    fn rectangle(&'a self, rect: Rectangle) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(rect),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let rect = self.rect.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            back_end.tri_list_xy_f32_rgba_f32(
                rect_tri_list_xy_f32(self.transform.get(), rect),
                rect_tri_list_rgba_f32(color)
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}

impl<'a> AddRound<'a, RoundRectangleColorContext<'a>> for RectangleColorContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            rect: Borrowed(self.rect.get()),
            round_radius: Value(radius),
        }
    }
}

impl<'a> View<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> AddImage<'a, ImageRectangleColorContext<'a>> for RectangleColorContext<'a> {
    fn image(&'a self, image: Image) -> ImageRectangleColorContext<'a> {
        ImageRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Value(image),
            color: Borrowed(self.color.get()),
        }
    }
}

<|endoftext|>


<commit_before>use configuration::Configuration;
use search::Search;

#[derive(PartialEq, Show)]
pub enum Text {
    Normal(String),
    Highlight(String),
    Blank,
}

pub struct Renderer {
    search: Search,
}

impl Renderer {
    pub fn new(search: Search) -> Renderer {
        Renderer { search: search }
    }

    pub fn render(&self) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(self.create_header());

        let selection = self.search.selection.clone().unwrap_or("".to_string());

        for position in 0..(self.search.config.visible_limit -1) {
            if position >= self.search.result.len() {
                result.push(Text::Blank);
                continue;
            }

            let choice = self.search.result[position].clone();

            if choice == selection {
                result.push(Text::Highlight(choice));
            } else {
                result.push(Text::Normal(choice))
            }
        }
        result
    }

    fn create_header(&self) -> Text {
        let mut line = String::from_str("> ");
        line.push_str(self.search.query.as_slice());
        Text::Normal(line)
    }
}

#[cfg(test)]

#[test]
fn it_renderes_selected_matches_with_a_highlight() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));
    let search = Search::blank(config).down();
    let renderer = Renderer::new(search);

    let output = renderer.render();

    assert_eq!(vec![Text::Normal("> ".to_string()),
                    Text::Normal("one".to_string()),
                    Text::Highlight("two".to_string())], output);
}

#[test]
fn it_renders_a_missmatch() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));

    let search = Search::blank(config).append_to_search("z");
    let renderer = Renderer::new(search);

    let output = renderer.render();

    assert_eq!(vec![Text::Normal("> z".to_string()),
                    Text::Blank,
                    Text::Blank], output);
}
<commit_msg>Replace the field in Renderer with a parameter in render<commit_after>use configuration::Configuration;
use search::Search;

#[derive(PartialEq, Show)]
pub enum Text {
    Normal(String),
    Highlight(String),
    Blank,
}

pub struct Renderer;

impl Renderer {
    pub fn render(&self, search: &Search) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(self.create_header(search));

        let selection = search.selection.clone().unwrap_or("".to_string());

        for position in 0..(search.config.visible_limit -1) {
            if position >= search.result.len() {
                result.push(Text::Blank);
                continue;
            }

            let choice = search.result[position].clone();

            if choice == selection {
                result.push(Text::Highlight(choice));
            } else {
                result.push(Text::Normal(choice))
            }
        }
        result
    }

    fn create_header(&self, search: &Search) -> Text {
        let mut line = String::from_str("> ");
        line.push_str(search.query.as_slice());
        Text::Normal(line)
    }
}

#[cfg(test)]

#[test]
fn it_renderes_selected_matches_with_a_highlight() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));
    let search = Search::blank(config).down();
    let renderer = Renderer;

    let output = renderer.render(&search);

    assert_eq!(vec![Text::Normal("> ".to_string()),
                    Text::Normal("one".to_string()),
                    Text::Highlight("two".to_string())], output);
}

#[test]
fn it_renders_a_missmatch() {
    let config = Configuration::from_inputs(vec!["one".to_string(),
                                                 "two".to_string(),
                                                 "three".to_string()], None, Some(3));

    let search = Search::blank(config).append_to_search("z");
    let renderer = Renderer;

    let output = renderer.render(&search);

    assert_eq!(vec![Text::Normal("> z".to_string()),
                    Text::Blank,
                    Text::Blank], output);
}
<|endoftext|>


<commit_before>//! Functionality for sending requests to Slack.

use std::error;

/// Functionality for sending authenticated and unauthenticated requests to Slack via HTTP.
///
/// If you do not have a custom client to integrate with and just want to send requests, use
/// the [`default_client()`] function to get a simple request sender.
pub trait SlackWebRequestSender {
    type Error: error::Error;

    /// Make an API call to Slack. Takes a map of parameters that get appended to the request as query
    /// params.
    fn send(&self, method: &str, params: &[(&str, &str)]) -> Result<String, Self::Error>;
}

#[cfg(feature = "reqwest")]
mod reqwest_support {
    extern crate reqwest;
    pub use self::reqwest::Client;
    pub use self::reqwest::Error;

    use std::io::Read;

    use super::SlackWebRequestSender;

    impl SlackWebRequestSender for reqwest::Client {
        type Error = reqwest::Error;

        fn send(&self, method_url: &str, params: &[(&str, &str)]) -> Result<String, Self::Error> {
            let mut url = reqwest::Url::parse(&method_url).expect("Unable to parse url");

            url.query_pairs_mut().extend_pairs(params);

            let mut response = self.get(url).send()?;
            let mut res_str = String::new();
            response.read_to_string(&mut res_str).map_err(reqwest::HyperError::from)?;

            Ok(res_str)
        }
    }

    /// Provides a default `reqwest` client to give to the API functions to send requests.
    ///
    /// # Examples
    ///
    /// ```
    /// # let token = "some_token";
    /// let client = slack_api::requests::default_client().unwrap();
    /// let response = slack_api::channels::list(&client, &token, &Default::default());
    /// ```
    pub fn default_client() -> Result<reqwest::Client, reqwest::Error> {
        reqwest::Client::new()
    }
}

#[cfg(feature = "reqwest")]
pub use self::reqwest_support::*;
<commit_msg>fix double ref warning<commit_after>//! Functionality for sending requests to Slack.

use std::error;

/// Functionality for sending authenticated and unauthenticated requests to Slack via HTTP.
///
/// If you do not have a custom client to integrate with and just want to send requests, use
/// the [`default_client()`] function to get a simple request sender.
pub trait SlackWebRequestSender {
    type Error: error::Error;

    /// Make an API call to Slack. Takes a map of parameters that get appended to the request as query
    /// params.
    fn send(&self, method: &str, params: &[(&str, &str)]) -> Result<String, Self::Error>;
}

#[cfg(feature = "reqwest")]
mod reqwest_support {
    extern crate reqwest;
    pub use self::reqwest::Client;
    pub use self::reqwest::Error;

    use std::io::Read;

    use super::SlackWebRequestSender;

    impl SlackWebRequestSender for reqwest::Client {
        type Error = reqwest::Error;

        fn send(&self, method_url: &str, params: &[(&str, &str)]) -> Result<String, Self::Error> {
            let mut url = reqwest::Url::parse(method_url).expect("Unable to parse url");

            url.query_pairs_mut().extend_pairs(params);

            let mut response = self.get(url).send()?;
            let mut res_str = String::new();
            response.read_to_string(&mut res_str).map_err(reqwest::HyperError::from)?;

            Ok(res_str)
        }
    }

    /// Provides a default `reqwest` client to give to the API functions to send requests.
    ///
    /// # Examples
    ///
    /// ```
    /// # let token = "some_token";
    /// let client = slack_api::requests::default_client().unwrap();
    /// let response = slack_api::channels::list(&client, &token, &Default::default());
    /// ```
    pub fn default_client() -> Result<reqwest::Client, reqwest::Error> {
        reqwest::Client::new()
    }
}

#[cfg(feature = "reqwest")]
pub use self::reqwest_support::*;
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use ffi::cairo_user_data_key_t;

/// A key for indexing user data in various cairo types.
///
/// Some types like [`Surface`] have `get_user_data`, `set_user_data`, and `remove_user_data`
/// methods that take `&'static UserDataKey`, where the address of that reference is significant.
///
/// To reliably have a stable address, the expected usage is to define a `static` item:
///
/// ```
/// use cairo::UserDataKey;
/// static FOO: UserDataKey<String> = UserDataKey::new();
///
/// # fn foo(surface: &cairo::Surface) {
/// surface.get_user_data(&FOO)
/// # ; }
pub struct UserDataKey<T> {
    pub(crate) ffi: cairo_user_data_key_t,
    marker: PhantomData<*const T>,
}

unsafe impl<T> Sync for UserDataKey<T> {}

impl<T> UserDataKey<T> {
    pub const fn new() -> Self {
        UserDataKey {
            ffi: cairo_user_data_key_t { unused: 0 },
            marker: PhantomData,
        }
    }
}

// In a safe API for user data we can’t make `get_user_data`
// transfer full ownership of the value to the caller (e.g. by returning `Box<T>`)
// because `self` still has a pointer to that value
// and `get_user_data` could be called again with the same key.
//
// We also can’t return a `&T` reference that borrows from `self`
// because the value could be removed with `remove_user_data` or replaced with `set_user_data`
// while the borrow still needs to be valid.
// (Borrowing with `&mut self` would not help as `Self` can be itself reference-counted.)
//
// Therefore the value must be reference-counted.
//
// We use `Rc` over `Arc` because the types implementing these methods are `!Send` and `!Sync`.
// See <https://github.com/gtk-rs/cairo/issues/256>

macro_rules! user_data_methods {
    ($ffi_get_user_data: path, $ffi_set_user_data: path,) => {
        /// Attach user data to `self` for the given `key`.
        pub fn set_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>,
                                         value: std::rc::Rc<T>)
        {
            unsafe extern "C" fn destructor<T>(ptr: *mut libc::c_void) {
                let ptr: *const T = ptr as _;
                drop(std::rc::Rc::from_raw(ptr))
            }
            // Safety:
            //
            // The destructor’s cast and `from_raw` are symetric
            // with the `into_raw` and cast below.
            // They both transfer ownership of one strong reference:
            // neither of them touches the reference count.
            let ptr: *const T = std::rc::Rc::into_raw(value);
            let ptr = ptr as *mut T as *mut libc::c_void;
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, ptr, Some(destructor::<T>))
            };
            Status::from(result).ensure_valid()
        }

        /// Return the user data previously attached to `self` with the given `key`, if any.
        pub fn get_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                         -> Option<std::rc::Rc<T>>
        {
            let ptr = self.get_user_data_ptr(key)?.as_ptr();

            // Safety:
            //
            // `Rc::from_raw` would normally take ownership of a strong reference for this pointer.
            // But `self` still has a copy of that pointer and `get_user_data` can be called again
            // with the same key.
            // We use `ManuallyDrop` to avoid running the destructor of that first `Rc`,
            // and return a cloned one (which increments the reference count).
            unsafe {
                let rc = std::mem::ManuallyDrop::new(std::rc::Rc::from_raw(ptr));
                Some(std::rc::Rc::clone(&rc))
            }
        }

        /// Return the user data previously attached to `self` with the given `key`, if any,
        /// without incrementing the reference count.
        ///
        /// The pointer is valid when it is returned from this method,
        /// until the cairo object that `self` represents is destroyed
        /// or `remove_user_data` or `set_user_data` is called with the same key.
        pub fn get_user_data_ptr<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                             -> Option<std::ptr::NonNull<T>>
        {
            // Safety:
            //
            // If `ffi_get_user_data` returns a non-null pointer,
            // there was a previous call to `ffi_set_user_data` with a key with the same address.
            // Either:
            //
            // * This was a call to a Rust `Self::set_user_data` method.
            //   Because that method takes a `&'static` reference,
            //   the key used then must live at that address until the end of the process.
            //   Because `UserDataKey<T>` has a non-zero size regardless of `T`,
            //   no other `UserDataKey<U>` value can have the same address.
            //   Therefore the `T` type was the same then at it is now and `cast` is type-safe.
            //
            // * Or, it is technically possible that the `set` call was to the C function directly,
            //   with a `cairo_user_data_key_t` in heap-allocated memory that was then freed,
            //   then `Box::new(UserDataKey::new()).leak()` was used to create a `&'static`
            //   that happens to have the same address because the allocator for `Box`
            //   reused that memory region.
            //   Since this involves a C (or FFI) call *and* is so far out of “typical” use
            //   of the user data functionality, we consider this a misuse of an unsafe API.
            unsafe {
                let ptr = $ffi_get_user_data(self.to_raw_none(), &key.ffi);
                Some(std::ptr::NonNull::new(ptr)?.cast())
            }
        }

        /// Unattach from `self` the user data associated with `key`, if any.
        /// If there is no other `Rc` strong reference, the data is destroyed.
        pub fn remove_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>) {
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, std::ptr::null_mut(), None)
            };
            Status::from(result).ensure_valid()
        }
    };
}
<commit_msg>move doc into lgpl-docs repository<commit_after>use std::marker::PhantomData;

use ffi::cairo_user_data_key_t;

pub struct UserDataKey<T> {
    pub(crate) ffi: cairo_user_data_key_t,
    marker: PhantomData<*const T>,
}

unsafe impl<T> Sync for UserDataKey<T> {}

impl<T> UserDataKey<T> {
    pub const fn new() -> Self {
        UserDataKey {
            ffi: cairo_user_data_key_t { unused: 0 },
            marker: PhantomData,
        }
    }
}

// In a safe API for user data we can’t make `get_user_data`
// transfer full ownership of the value to the caller (e.g. by returning `Box<T>`)
// because `self` still has a pointer to that value
// and `get_user_data` could be called again with the same key.
//
// We also can’t return a `&T` reference that borrows from `self`
// because the value could be removed with `remove_user_data` or replaced with `set_user_data`
// while the borrow still needs to be valid.
// (Borrowing with `&mut self` would not help as `Self` can be itself reference-counted.)
//
// Therefore the value must be reference-counted.
//
// We use `Rc` over `Arc` because the types implementing these methods are `!Send` and `!Sync`.
// See <https://github.com/gtk-rs/cairo/issues/256>

macro_rules! user_data_methods {
    ($ffi_get_user_data: path, $ffi_set_user_data: path,) => {
        /// Attach user data to `self` for the given `key`.
        pub fn set_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>,
                                         value: std::rc::Rc<T>)
        {
            unsafe extern "C" fn destructor<T>(ptr: *mut libc::c_void) {
                let ptr: *const T = ptr as _;
                drop(std::rc::Rc::from_raw(ptr))
            }
            // Safety:
            //
            // The destructor’s cast and `from_raw` are symetric
            // with the `into_raw` and cast below.
            // They both transfer ownership of one strong reference:
            // neither of them touches the reference count.
            let ptr: *const T = std::rc::Rc::into_raw(value);
            let ptr = ptr as *mut T as *mut libc::c_void;
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, ptr, Some(destructor::<T>))
            };
            Status::from(result).ensure_valid()
        }

        /// Return the user data previously attached to `self` with the given `key`, if any.
        pub fn get_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                         -> Option<std::rc::Rc<T>>
        {
            let ptr = self.get_user_data_ptr(key)?.as_ptr();

            // Safety:
            //
            // `Rc::from_raw` would normally take ownership of a strong reference for this pointer.
            // But `self` still has a copy of that pointer and `get_user_data` can be called again
            // with the same key.
            // We use `ManuallyDrop` to avoid running the destructor of that first `Rc`,
            // and return a cloned one (which increments the reference count).
            unsafe {
                let rc = std::mem::ManuallyDrop::new(std::rc::Rc::from_raw(ptr));
                Some(std::rc::Rc::clone(&rc))
            }
        }

        /// Return the user data previously attached to `self` with the given `key`, if any,
        /// without incrementing the reference count.
        ///
        /// The pointer is valid when it is returned from this method,
        /// until the cairo object that `self` represents is destroyed
        /// or `remove_user_data` or `set_user_data` is called with the same key.
        pub fn get_user_data_ptr<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                             -> Option<std::ptr::NonNull<T>>
        {
            // Safety:
            //
            // If `ffi_get_user_data` returns a non-null pointer,
            // there was a previous call to `ffi_set_user_data` with a key with the same address.
            // Either:
            //
            // * This was a call to a Rust `Self::set_user_data` method.
            //   Because that method takes a `&'static` reference,
            //   the key used then must live at that address until the end of the process.
            //   Because `UserDataKey<T>` has a non-zero size regardless of `T`,
            //   no other `UserDataKey<U>` value can have the same address.
            //   Therefore the `T` type was the same then at it is now and `cast` is type-safe.
            //
            // * Or, it is technically possible that the `set` call was to the C function directly,
            //   with a `cairo_user_data_key_t` in heap-allocated memory that was then freed,
            //   then `Box::new(UserDataKey::new()).leak()` was used to create a `&'static`
            //   that happens to have the same address because the allocator for `Box`
            //   reused that memory region.
            //   Since this involves a C (or FFI) call *and* is so far out of “typical” use
            //   of the user data functionality, we consider this a misuse of an unsafe API.
            unsafe {
                let ptr = $ffi_get_user_data(self.to_raw_none(), &key.ffi);
                Some(std::ptr::NonNull::new(ptr)?.cast())
            }
        }

        /// Unattach from `self` the user data associated with `key`, if any.
        /// If there is no other `Rc` strong reference, the data is destroyed.
        pub fn remove_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>) {
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, std::ptr::null_mut(), None)
            };
            Status::from(result).ensure_valid()
        }
    };
}
<|endoftext|>


<commit_before>use std::fmt;

use self::Rope::*;

fn max<T: PartialOrd + Copy>(x: T, y: T) -> T {
    if x >= y {
        x
    } else {
        y
    }
}

#[derive(Clone)]
pub enum Rope {
    FlatCharVec { seq: Vec<char> },
    Concatenation { left: Box<Rope>, right: Box<Rope>, depth: usize, length: usize },
    Reverse { rope: Box<Rope> },
    SubString { rope: Box<Rope>, offset: usize, length: usize },
}

fn write_rope_to_string(rope: &Rope, s: &mut String) {
    match *rope {
        FlatCharVec { ref seq }                   => {
            s.push_str(&seq.iter().map(Clone::clone).collect::<String>());
        }
        Concatenation { ref left, ref right, .. } => {
            write_rope_to_string(left, s);
            write_rope_to_string(right, s);
        },
        Reverse { ref rope }                      => {
            let inner = rope.to_string();
            s.push_str(&inner.chars().rev().collect::<String>());
        }
        SubString { ref rope, offset, length }    => {
            let inner = rope.to_string();
            s.push_str(&inner[offset..offset+length]);
        }
    }
}

fn concatenate(left: Rope, right: Rope) -> Rope {
    if left.len() == 0 {
        return right;
    }
    if right.len() == 0 {
        return left;
    }

    const COMBINE_LENGTH: usize = 17;
    let length = left.len() + right.len();
    if length < COMBINE_LENGTH {
        let mut lchs = left.into_chars();
        lchs.extend(right.into_chars());
        return FlatCharVec { seq: lchs };
    }
    let depth = max(left.depth(), right.depth()) + 1;
    Concatenation { left: Box::new(left), right: Box::new(right), depth: depth, length: length }
}

impl Rope {
    pub fn from_str(s: &str) -> Rope {
        Rope::from_vec(s.chars().collect())
    }

    pub fn from_vec(seq: Vec<char>) -> Rope {
        Rope::FlatCharVec { seq: seq }
    }

    pub fn len(&self) -> usize {
        match *self {
            FlatCharVec { ref seq }      => seq.len(),
            Concatenation { length, .. } => length,
            Reverse { ref rope }         => rope.len(),
            SubString { length, .. }     => length
        }
    }

    pub fn depth(&self) -> usize {
        match *self {
            FlatCharVec { .. }          => 0,
            Concatenation { depth, .. } => depth,
            Reverse { ref rope }        => rope.depth(),
            SubString { ref rope, .. }  => rope.depth()
        }
    }

    pub fn append<RHS: IntoRope>(self, rhs: RHS) -> Self {
        concatenate(self, rhs.into_rope())
    }

    pub fn to_string(&self) -> String {
        let mut s = String::new();
        write_rope_to_string(self, &mut s);
        s
    }

    pub fn reverse(self) -> Self {
        match self {
            Reverse { rope } => *rope,
            Concatenation { left, right, .. } => {
                concatenate(right.reverse(), left.reverse())
            },
            this => Reverse { rope: Box::new(this) }
        }
    }

    // FIXME: clone?
    pub fn delete(self, start: usize, end: usize) -> Self {
        let tail = self.clone().slice_from(end);
        self.slice_to(start).append(tail)
    }

    pub fn slice_from(self, start: usize) -> Self {
        let len = self.len();
        self.slice(start, len)
    }

    pub fn slice_to(self, end: usize) -> Self {
        self.slice(0, end)
    }

    pub fn slice(self, start: usize, end: usize) -> Self {
        assert!(end <= self.len(), "illegal slice()");
        let slen = self.len();
        if start == 0 && end == slen {
            self
        } else {
            match self {
                Concatenation { left, right, .. } => {
                    let llen = left.len();
                    if end <= llen {
                        left.slice(start, end)
                    } else if start >= llen {
                        right.slice(start-llen, end-llen)
                    } else  {
                        concatenate(left.slice(start, llen), right.slice(0, end-llen))
                    }
                },
                this@FlatCharVec { .. } => {
                    if end - start < 16 {
                        if let FlatCharVec { seq } = this {
                            FlatCharVec { seq: seq[start..end].to_vec() }
                        } else {
                            unreachable!()
                        }
                    } else {
                        SubString { rope: Box::new(this), offset: start, length: end-start }
                    }
                },
                SubString { rope, offset, length }  => {
                    assert!(end - start <= length);
                    SubString { rope: rope, offset: offset + start, length: end - start }
                },
                Reverse { rope } => {
                    rope.slice(slen-end, slen-start).reverse()
                }
            }
        }
    }

    pub fn insert<T: IntoRope>(self, offset: usize, s: T) -> Self {
        assert!(offset <= self.len());
        let r = s.into_rope();
        if offset == 0 {
            r.append(self)
        } else if offset == self.len() {
            self.append(r)
        } else {
            self.clone().slice_to(offset).append(r).append(self.slice_from(offset))
        }
    }

    fn into_chars(self) -> Vec<char> {
        match self {
            FlatCharVec { seq }         => seq,
            Concatenation { left, right, .. } => {
                let mut lchs = left.into_chars();
                let rchs = right.into_chars();
                lchs.extend(rchs);
                lchs
            }
            Reverse { rope }        => {
                let mut inner = rope.into_chars();
                inner.reverse();
                inner
            }
            SubString { rope, offset, length }  => {
                let inner = rope.into_chars();
                inner[offset .. offset+length].to_vec()
            }
        }
    }

    fn is_balanced(&self) -> bool {
        true
    }
}

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

impl fmt::Debug for Rope {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "R{:?}", self.to_string())
    }
}

pub trait IntoRope {
    fn into_rope(self) -> Rope;
}

impl IntoRope for char {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: vec![self] }
    }
}

impl IntoRope for String {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: self.chars().collect() }
    }
}

impl IntoRope for Rope {
    fn into_rope(self) -> Rope {
        self
    }
}

impl<'a> IntoRope for &'a str {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: self.chars().collect() }
    }
}

#[test]
fn test_rope() {
    let s = Rope::from_str("Hello").append(' ').append("World").append('!');

    println!("depth => {}", s.depth());
    println!("len => {}", s.len());
    println!("got => {:?}", s);

    let s = s.insert(0, "Oh, man, ");

    println!("got => {:?}", s);

    let s = s.insert(9, "wait! ");
    println!("got => {:?}", s);
    println!("got => {:?}", s.reverse());
}

#[test]
fn test_rope2() {
    let s = Rope::from_str("Hello")
        .append(" abcdefghijklmnopqrstuvwxyz")
        .append(" World")
        .append(" abcdefghijklmnopqrstuvwxyz")
        .append(" abcdefghijklmnopqrstuvwxyz")
        .append(" abcdefghijklmnopqrstuvwxyz");

    println!("depth => {}", s.depth());
    println!("len => {}", s.len());
    println!("got => {:?}", s);
    let s2 = s.slice(10, 50);
    println!("got => {:?}", s2);
    println!("len => {:?}", s2.len());
}

// pub trait Rope {
//     fn find(&self, ch: char) -> Option<usize>;
//     // fn find(&self, pat: &str) -> Option<usize>;
//     fn insert(self, offset: usize, s: &str) -> Self;

//     fn rebalance(self) -> Self;

//     fn trim_left(self) -> Self;
//     fn trim_right(self) -> Self;
//     fn trim(self) -> Self {
//         self.trim_left().trim_right()
//     }

//     fn starts_with(self, prefix: &str) -> bool;
//     fn ends_with(self, suffix: &str) -> bool;
// }
<commit_msg>rope: add peek()<commit_after>use std::fmt;

use self::Rope::*;

fn max<T: PartialOrd + Copy>(x: T, y: T) -> T {
    if x >= y {
        x
    } else {
        y
    }
}

#[derive(Clone)]
pub enum Rope {
    FlatCharVec { seq: Vec<char> },
    Concatenation { left: Box<Rope>, right: Box<Rope>, depth: usize, length: usize },
    Reverse { rope: Box<Rope> },
    SubString { rope: Box<Rope>, offset: usize, length: usize },
}

fn write_rope_to_string(rope: &Rope, s: &mut String) {
    match *rope {
        FlatCharVec { ref seq }                   => {
            s.push_str(&seq.iter().map(Clone::clone).collect::<String>());
        }
        Concatenation { ref left, ref right, .. } => {
            write_rope_to_string(left, s);
            write_rope_to_string(right, s);
        },
        Reverse { ref rope }                      => {
            let inner = rope.to_string();
            s.push_str(&inner.chars().rev().collect::<String>());
        }
        SubString { ref rope, offset, length }    => {
            let inner = rope.to_string();
            s.push_str(&inner[offset..offset+length]);
        }
    }
}

fn concatenate(left: Rope, right: Rope) -> Rope {
    if left.len() == 0 {
        return right;
    }
    if right.len() == 0 {
        return left;
    }

    const COMBINE_LENGTH: usize = 17;
    let length = left.len() + right.len();
    if length < COMBINE_LENGTH {
        let mut lchs = left.into_chars();
        lchs.extend(right.into_chars());
        return FlatCharVec { seq: lchs };
    }
    let depth = max(left.depth(), right.depth()) + 1;
    Concatenation { left: Box::new(left), right: Box::new(right), depth: depth, length: length }
}

impl Rope {
    pub fn from_str(s: &str) -> Rope {
        Rope::from_vec(s.chars().collect())
    }

    pub fn from_vec(seq: Vec<char>) -> Rope {
        Rope::FlatCharVec { seq: seq }
    }

    pub fn len(&self) -> usize {
        match *self {
            FlatCharVec { ref seq }      => seq.len(),
            Concatenation { length, .. } => length,
            Reverse { ref rope }         => rope.len(),
            SubString { length, .. }     => length
        }
    }

    pub fn depth(&self) -> usize {
        match *self {
            FlatCharVec { .. }          => 0,
            Concatenation { depth, .. } => depth,
            Reverse { ref rope }        => rope.depth(),
            SubString { ref rope, .. }  => rope.depth()
        }
    }

    pub fn append<RHS: IntoRope>(self, rhs: RHS) -> Self {
        concatenate(self, rhs.into_rope())
    }

    pub fn to_string(&self) -> String {
        let mut s = String::new();
        write_rope_to_string(self, &mut s);
        s
    }

    pub fn reverse(self) -> Self {
        match self {
            Reverse { rope } => *rope,
            Concatenation { left, right, .. } => {
                concatenate(right.reverse(), left.reverse())
            },
            this => Reverse { rope: Box::new(this) }
        }
    }

    // FIXME: clone?
    pub fn delete(self, start: usize, end: usize) -> Self {
        let tail = self.clone().slice_from(end);
        self.slice_to(start).append(tail)
    }

    pub fn slice_from(self, start: usize) -> Self {
        let len = self.len();
        self.slice(start, len)
    }

    pub fn slice_to(self, end: usize) -> Self {
        self.slice(0, end)
    }

    pub fn slice(self, start: usize, end: usize) -> Self {
        assert!(end <= self.len(), "illegal slice()");
        let slen = self.len();
        if start == 0 && end == slen {
            self
        } else {
            match self {
                Concatenation { left, right, .. } => {
                    let llen = left.len();
                    if end <= llen {
                        left.slice(start, end)
                    } else if start >= llen {
                        right.slice(start-llen, end-llen)
                    } else  {
                        concatenate(left.slice(start, llen), right.slice(0, end-llen))
                    }
                },
                this@FlatCharVec { .. } => {
                    if end - start < 16 {
                        if let FlatCharVec { seq } = this {
                            FlatCharVec { seq: seq[start..end].to_vec() }
                        } else {
                            unreachable!()
                        }
                    } else {
                        SubString { rope: Box::new(this), offset: start, length: end-start }
                    }
                },
                SubString { rope, offset, length }  => {
                    assert!(end - start <= length);
                    SubString { rope: rope, offset: offset + start, length: end - start }
                },
                Reverse { rope } => {
                    rope.slice(slen-end, slen-start).reverse()
                }
            }
        }
    }

    pub fn insert<T: IntoRope>(self, offset: usize, s: T) -> Self {
        assert!(offset <= self.len());
        let r = s.into_rope();
        if offset == 0 {
            r.append(self)
        } else if offset == self.len() {
            self.append(r)
        } else {
            self.clone().slice_to(offset).append(r).append(self.slice_from(offset))
        }
    }

    pub fn peek<F>(self, mut f: F) -> Self where F: FnMut(&Self) {
        f(&self);
        self
    }

    fn into_chars(self) -> Vec<char> {
        match self {
            FlatCharVec { seq }         => seq,
            Concatenation { left, right, .. } => {
                let mut lchs = left.into_chars();
                let rchs = right.into_chars();
                lchs.extend(rchs);
                lchs
            }
            Reverse { rope }        => {
                let mut inner = rope.into_chars();
                inner.reverse();
                inner
            }
            SubString { rope, offset, length }  => {
                let inner = rope.into_chars();
                inner[offset .. offset+length].to_vec()
            }
        }
    }
}

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

impl fmt::Debug for Rope {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "R{:?}", self.to_string())
    }
}

pub trait IntoRope {
    fn into_rope(self) -> Rope;
}

impl IntoRope for char {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: vec![self] }
    }
}

impl IntoRope for String {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: self.chars().collect() }
    }
}

impl IntoRope for Rope {
    fn into_rope(self) -> Rope {
        self
    }
}

impl<'a> IntoRope for &'a str {
    fn into_rope(self) -> Rope {
        FlatCharVec { seq: self.chars().collect() }
    }
}

#[test]
fn test_rope() {
    let s = Rope::from_str("Hello").append(' ').append("World").append('!');

    println!("depth => {}", s.depth());
    println!("len => {}", s.len());
    println!("got => {:?}", s);

    let s = s.insert(0, "Oh, man, ");

    println!("got => {:?}", s);

    let s = s.insert(9, "wait! ");
    println!("got => {:?}", s);
    println!("got => {:?}", s.reverse());
}

#[test]
fn test_rope2() {
    let s = Rope::from_str("Hello")
        .append(" abcdefghijklmnopqrstuvwxyz")
        .append(" World")
        .peek(|r| println!("D1 got => {}", r))
        .append(" abcdefghijklmnopqrstuvwxyz")
        .peek(|r| println!("D2 depth => {}", r.depth()))
        .append(" abcdefghijklmnopqrstuvwxyz")
        .append(" abcdefghijklmnopqrstuvwxyz");

    println!("depth => {}", s.depth());
    println!("len => {}", s.len());
    println!("got => {:?}", s);
    let s2 = s.slice(10, 50);
    println!("got => {:?}", s2);
    println!("len => {:?}", s2.len());
}

// pub trait Rope {
//     fn find(&self, ch: char) -> Option<usize>;
//     // fn find(&self, pat: &str) -> Option<usize>;
//     fn insert(self, offset: usize, s: &str) -> Self;

//     fn rebalance(self) -> Self;

//     fn trim_left(self) -> Self;
//     fn trim_right(self) -> Self;
//     fn trim(self) -> Self {
//         self.trim_left().trim_right()
//     }

//     fn starts_with(self, prefix: &str) -> bool;
//     fn ends_with(self, suffix: &str) -> bool;
// }
<|endoftext|>


<commit_before>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Common utilities.

mod text;
pub use self::text::{Text, TextSlice, TextIterator, IntoTextIterator, trim_newline};

mod nonnanfloat;
pub use self::nonnanfloat::NonNaNFloat;

mod interval;
pub use self::interval::{Interval, IntervalError};

/// Strand information.
#[derive(Debug, Clone, Copy)]
pub enum Strand {
    Forward,
    Reverse,
    Unknown,
}

impl PartialEq for Strand {
    /// Returns true if both are `Forward` or both are `Reverse`, otherwise returns false.
    fn eq(&self, other: &Strand) -> bool {
        match (self, other) {
            (&Strand::Forward, &Strand::Forward) => true,
            (&Strand::Reverse, &Strand::Reverse) => true,
            _ => false
        }
    }
}

impl Strand {

    /// Returns a `Strand` enum representing the given char.
    ///
    /// The mapping is as follows:
    ///     * '+', 'f', or 'F' becomes `Strand::Forward`
    ///     * '-', 'r', or 'R' becomes `Strand::Reverse`
    ///     * '.', '?' becomes `Strand::Unknown`
    ///     * Any other inputs will return an `Err(StrandError::InvalidChar)`
    pub fn from_char(strand_char: &char) -> Result<Strand, StrandError> {
        match *strand_char {
            '+' | 'f' | 'F' => Ok(Strand::Forward),
            '-' | 'r' | 'R' => Ok(Strand::Reverse),
            '.' | '?'  => Ok(Strand::Unknown),
            invalid => Err(StrandError::InvalidChar(invalid)),
        }
    }

    pub fn is_unknown(&self) -> bool {
        match self {
            &Strand::Unknown => true,
            _ => false,
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum StrandError {
        InvalidChar(invalid_char: char) {
            description("invalid character for strand conversion")
            display("character {:?} can not be converted to a Strand", invalid_char)
        }
    }
}

/// In place implementation of scan over a slice.
pub fn scan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], op: F) {
    let mut s = a[0];
    for v in a.iter_mut().skip(1) {
        s = op(s, *v);
        *v = s;
    }
}

// Inplace implementation of prescan over a slice.
pub fn prescan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], neutral: T, op: F) {
    let mut s = neutral;
    for v in a.iter_mut() {
        let t = *v;
        *v = s;
        s = op(s, t);
    }
}

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

    #[test]
    fn test_scan() {
        let mut a = vec![1, 0, 0, 1];
        scan(&mut a[..], |a, b| a + b);
        assert_eq!(a, vec![1, 1, 1, 2]);
    }

    #[test]
    fn test_prescan() {
        let mut a = vec![1, 0, 0, 1];
        prescan(&mut a[..], 0, |a, b| a + b);
        assert_eq!(a, vec![0, 1, 1, 1]);
    }

    #[test]
    fn test_strand() {
        assert_eq!(Strand::from_char(&'+').unwrap(), Strand::Forward);
        assert_eq!(Strand::from_char(&'-').unwrap(), Strand::Reverse);
        assert!(Strand::from_char(&'.').unwrap().is_unknown());
        assert!(Strand::from_char(&'o').is_err());
    }
}
<commit_msg>Use 'if let' for Strand.is_unknown<commit_after>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Common utilities.

mod text;
pub use self::text::{Text, TextSlice, TextIterator, IntoTextIterator, trim_newline};

mod nonnanfloat;
pub use self::nonnanfloat::NonNaNFloat;

mod interval;
pub use self::interval::{Interval, IntervalError};

/// Strand information.
#[derive(Debug, Clone, Copy)]
pub enum Strand {
    Forward,
    Reverse,
    Unknown,
}

impl PartialEq for Strand {
    /// Returns true if both are `Forward` or both are `Reverse`, otherwise returns false.
    fn eq(&self, other: &Strand) -> bool {
        match (self, other) {
            (&Strand::Forward, &Strand::Forward) => true,
            (&Strand::Reverse, &Strand::Reverse) => true,
            _ => false
        }
    }
}

impl Strand {

    /// Returns a `Strand` enum representing the given char.
    ///
    /// The mapping is as follows:
    ///     * '+', 'f', or 'F' becomes `Strand::Forward`
    ///     * '-', 'r', or 'R' becomes `Strand::Reverse`
    ///     * '.', '?' becomes `Strand::Unknown`
    ///     * Any other inputs will return an `Err(StrandError::InvalidChar)`
    pub fn from_char(strand_char: &char) -> Result<Strand, StrandError> {
        match *strand_char {
            '+' | 'f' | 'F' => Ok(Strand::Forward),
            '-' | 'r' | 'R' => Ok(Strand::Reverse),
            '.' | '?'  => Ok(Strand::Unknown),
            invalid => Err(StrandError::InvalidChar(invalid)),
        }
    }

    pub fn is_unknown(&self) -> bool {
        if let &Strand::Unknown = self {
            true
        } else {
            false
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum StrandError {
        InvalidChar(invalid_char: char) {
            description("invalid character for strand conversion")
            display("character {:?} can not be converted to a Strand", invalid_char)
        }
    }
}

/// In place implementation of scan over a slice.
pub fn scan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], op: F) {
    let mut s = a[0];
    for v in a.iter_mut().skip(1) {
        s = op(s, *v);
        *v = s;
    }
}

// Inplace implementation of prescan over a slice.
pub fn prescan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], neutral: T, op: F) {
    let mut s = neutral;
    for v in a.iter_mut() {
        let t = *v;
        *v = s;
        s = op(s, t);
    }
}

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

    #[test]
    fn test_scan() {
        let mut a = vec![1, 0, 0, 1];
        scan(&mut a[..], |a, b| a + b);
        assert_eq!(a, vec![1, 1, 1, 2]);
    }

    #[test]
    fn test_prescan() {
        let mut a = vec![1, 0, 0, 1];
        prescan(&mut a[..], 0, |a, b| a + b);
        assert_eq!(a, vec![0, 1, 1, 1]);
    }

    #[test]
    fn test_strand() {
        assert_eq!(Strand::from_char(&'+').unwrap(), Strand::Forward);
        assert_eq!(Strand::from_char(&'-').unwrap(), Strand::Reverse);
        assert!(Strand::from_char(&'.').unwrap().is_unknown());
        assert!(Strand::from_char(&'o').is_err());
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use self::regex::Regex;
use self::regex::Error;

#[cfg(test)] pub mod test;

pub struct VerEx {
    string: String
}

impl VerEx {
    // constructors
    pub fn new() -> VerEx {
        VerEx {
            string: String::new(),
        }
    }

    pub fn from_string(string: String) -> VerEx {
        VerEx {
            string: string,
        }
    }

    pub fn from_str(string: &str) -> VerEx {
        VerEx::from_string(string.to_string())
    }

    // fundamental methods
    pub fn add(&mut self, value: &str) -> &mut VerEx{
        self.string.push_str(value);
        self
    }

    pub fn compile(&mut self) -> Result<Regex, Error> {
        Regex::new(self.string.as_ref())
    }

    pub fn regex(&mut self) -> Result<Regex, Error> {
        self.compile()
    }

    pub fn source(& self) -> &str {
        self.string.as_ref()
    }

    pub fn raw(& self) -> &str {
        self.source()
    }

    // --------------------------------------------------

    /// Any of the given characters
    pub fn any(&mut self, chars: &str) -> &mut VerEx {
        let mut string = r"[".to_string();
        string.push_str(chars);
        string.push_str(r"]");
        self.add(string.as_ref())
    }

    pub fn any_of(&mut self, chars: &str) -> &mut VerEx {
        self.any(chars)
    }

    /// Any character zero or more times
    pub fn anything(&mut self) -> &mut VerEx {
        self.add(r"(.*)")
    }

    /// Any character zero or more times except the provided characters
    pub fn anything_but(&mut self, value: &str) -> &mut VerEx {
        let mut string = r"([^".to_string();
        string.push_str(value);
        string.push_str(r"]*)");
        self.add(string.as_ref())
    }

    pub fn br(&mut self) -> &mut VerEx {
        self.line_break()
    }

    pub fn end_of_line(&mut self) -> &mut VerEx {
        self.add(r"$")
    }

    /// Find a specific string
    pub fn find(&mut self, value: &str) -> &mut VerEx {
        let mut string = r"(".to_string();
        string.push_str(value);
        string.push_str(r")");
        self.add(string.as_ref())
    }

    /// A line break!
    pub fn line_break(&mut self) -> &mut VerEx {
        self.add(r"(\n|(\r\n))")
    }

    /// Any string either one or zero times
    pub fn maybe(&mut self, value: &str) -> &mut VerEx {
        let mut string = r"(".to_string();
        string.push_str(value);
        string.push_str(r")?");
        self.add(string.as_ref())
    }

    pub fn or(&mut self, value: &str) -> &mut VerEx {
        self.add(r"|");
        if value.is_empty() {
            return self;
        } else {
            return self.then(value);
        }
    }

    /// A range of characters e.g. [A-Z]
    /// Usage: verex.range(vec![('a', 'z'),('A', 'Z')])
    pub fn range(&mut self, range: Vec<(char, char)>) -> &mut VerEx {
        let mut string = r"[".to_string();
        for tuple in range {
            let from = tuple.0;
            let to = tuple.1;
            string.push(from);
            string.push('-');
            string.push(to);
        }
        string.push(']');
        self.add(string.as_ref())
    }

    /// Any character at least one time
    pub fn something(&mut self) -> &mut VerEx {
        self.add(r"(.+)")
    }

    /// Any character at least one time except for these characters
    pub fn something_but(&mut self, value: &str) -> &mut VerEx {
        let mut string = r"([^".to_string();
        string.push_str(value);
        string.push_str(r"]+)");
        self.add(string.as_ref())
    }

    pub fn start_of_line(&mut self) -> &mut VerEx {
        self.add(r"^")
    }

    // A tab
    pub fn tab(&mut self) -> &mut VerEx {
        self.add(r"\t")
    }

    /// To use find "in the sentence" and make the chaining flow better
    pub fn then(&mut self, value: &str) -> &mut VerEx {
        self.find(value)
    }

    /// Any alphanumeric characters
    pub fn word(&mut self) -> &mut VerEx {
        self.add(r"(\w+)")
    }
}
<commit_msg>refactor (use chaining of self.add )<commit_after>extern crate regex;

use self::regex::Regex;
use self::regex::Error;

#[cfg(test)] pub mod test;

pub struct VerEx {
    string: String
}

impl VerEx {
    // constructors
    pub fn new() -> VerEx {
        VerEx {
            string: String::new(),
        }
    }

    pub fn from_string(string: String) -> VerEx {
        VerEx {
            string: string,
        }
    }

    pub fn from_str(string: &str) -> VerEx {
        VerEx::from_string(string.to_string())
    }

    // fundamental methods
    pub fn add(&mut self, value: &str) -> &mut VerEx{
        self.string.push_str(value);
        self
    }

    pub fn compile(&mut self) -> Result<Regex, Error> {
        Regex::new(self.string.as_ref())
    }

    pub fn regex(&mut self) -> Result<Regex, Error> {
        self.compile()
    }

    pub fn source(& self) -> &str {
        self.string.as_ref()
    }

    pub fn raw(& self) -> &str {
        self.source()
    }

    // --------------------------------------------------

    /// Any of the given characters
    pub fn any(&mut self, chars: &str) -> &mut VerEx {
        self.add(r"[")
            .add(chars)
            .add(r"]")
    }

    pub fn any_of(&mut self, chars: &str) -> &mut VerEx {
        self.any(chars)
    }

    /// Any character zero or more times
    pub fn anything(&mut self) -> &mut VerEx {
        self.add(r"(.*)")
    }

    /// Any character zero or more times except the provided characters
    pub fn anything_but(&mut self, value: &str) -> &mut VerEx {
        self.add(r"([^")
            .add(value)
            .add(r"]*)")
    }

    pub fn br(&mut self) -> &mut VerEx {
        self.line_break()
    }

    pub fn end_of_line(&mut self) -> &mut VerEx {
        self.add(r"$")
    }

    /// Find a specific string
    pub fn find(&mut self, value: &str) -> &mut VerEx {
        self.add(r"(")
            .add(value)
            .add(r")")
    }

    /// A line break!
    pub fn line_break(&mut self) -> &mut VerEx {
        self.add(r"(\n|(\r\n))")
    }

    /// Any string either one or zero times
    pub fn maybe(&mut self, value: &str) -> &mut VerEx {
        self.add(r"(")
            .add(value)
            .add(r")?")
    }

    pub fn or(&mut self, value: &str) -> &mut VerEx {
        self.add(r"|");
        if value.is_empty() {
            return self;
        } else {
            return self.then(value);
        }
    }

    /// A range of characters e.g. [A-Z]
    /// Usage example: verex.range(vec![('a', 'z'),('A', 'Z')])
    pub fn range(&mut self, range: Vec<(char, char)>) -> &mut VerEx {
        let mut string = r"[".to_string();
        for tuple in range {
            let from = tuple.0;
            let to = tuple.1;
            string.push(from);
            string.push('-');
            string.push(to);
        }
        string.push(']');
        self.add(string.as_ref())
    }

    /// Any character at least one time
    pub fn something(&mut self) -> &mut VerEx {
        self.add(r"(.+)")
    }

    /// Any character at least one time except for these characters
    pub fn something_but(&mut self, value: &str) -> &mut VerEx {
        self.add(r"([^")
            .add(value)
            .add(r"]+)")
    }

    pub fn start_of_line(&mut self) -> &mut VerEx {
        self.add(r"^")
    }

    // A tab
    pub fn tab(&mut self) -> &mut VerEx {
        self.add(r"\t")
    }

    /// To use find "in the sentence" and make the chaining flow better
    pub fn then(&mut self, value: &str) -> &mut VerEx {
        self.find(value)
    }

    /// Any alphanumeric characters
    pub fn word(&mut self) -> &mut VerEx {
        self.add(r"(\w+)")
    }
}
<|endoftext|>


<commit_before>extern crate http;

use std::vec::Vec;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;
use http::server::{Config, Server, Request, ResponseWriter};
use http::headers;

#[test]
fn test_nothing() {
    assert_eq!(1, 1);
}

#[deriving(Clone)]
struct TileServer;

impl Server for TileServer {
    fn get_config(&self) -> Config {
        Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(0, 0, 0, 0),
                port: 8001,
            },
        }
    }

    fn handle_request(&self, _r: &Request, w: &mut ResponseWriter) {
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new(),
        });

        w.write(bytes!("Hello world!\n")).unwrap();
    }
}

fn main() {
    TileServer.serve_forever();
}
<commit_msg>index_html and 404 responses<commit_after>extern crate http;

use std::vec::Vec;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;
use http::server::{Config, Server, Request, ResponseWriter};
use http::server::request::AbsolutePath;
use http::status::NotFound;
use http::headers;

#[test]
fn test_nothing() {
    assert_eq!(1, 1);
}

#[deriving(Clone)]
struct TileServer;

impl Server for TileServer {
    fn get_config(&self) -> Config {
        Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(0, 0, 0, 0),
                port: 8001,
            },
        }
    }

    fn handle_request(&self, r: &Request, w: &mut ResponseWriter) {
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new(),
        });

        match r.request_uri {
            AbsolutePath(ref url) => {
                if url == &~"/" {
                    w.write(index_html.as_bytes()).unwrap();
                    return;
                }
            },
            _ => {}
        };

        w.status = NotFound;
        w.write("Page not found :(\n".as_bytes()).unwrap();

    }
}

fn main() {
    TileServer.serve_forever();
}

static index_html: &'static str = "<!doctype html>\
<meta charset='utf-8'>\n\
Hello world!\n\
";
<|endoftext|>


<commit_before>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<commit_msg>Deserializer expects a map, not simply map<commit_after>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<|endoftext|>


<commit_before>use super::{Open, Sink, SinkAsBytes};
use crate::audio::AudioPacket;
use crate::config::AudioFormat;
use crate::player::{NUM_CHANNELS, SAMPLE_RATE};
use gst::prelude::*;
use gst::*;
use std::sync::mpsc::{sync_channel, SyncSender};
use std::{io, thread};
use zerocopy::AsBytes;

#[allow(dead_code)]
pub struct GstreamerSink {
    tx: SyncSender<Vec<u8>>,
    pipeline: gst::Pipeline,
    format: AudioFormat,
}

impl Open for GstreamerSink {
    fn open(device: Option<String>, format: AudioFormat) -> GstreamerSink {
        info!("Using GStreamer sink with format: {:?}", format);
        gst::init().expect("failed to init GStreamer!");

        // GStreamer calls S24 and S24_3 different from the rest of the world
        let gst_format = match format {
            AudioFormat::S24 => "S24_32".to_string(),
            AudioFormat::S24_3 => "S24".to_string(),
            _ => format!("{:?}", format),
        };

        let pipeline_str_preamble = format!(
            "appsrc caps=\"audio/x-raw,format={}LE,layout=interleaved,channels={},rate={}\" block=true max-bytes=4096 name=appsrc0 ",
            gst_format, NUM_CHANNELS, SAMPLE_RATE
        );
        let pipeline_str_rest = r#" ! audioconvert ! autoaudiosink"#;
        let pipeline_str: String = match device {
            Some(x) => format!("{}{}", pipeline_str_preamble, x),
            None => format!("{}{}", pipeline_str_preamble, pipeline_str_rest),
        };
        info!("Pipeline: {}", pipeline_str);

        gst::init().unwrap();
        let pipelinee = gst::parse_launch(&*pipeline_str).expect("Couldn't launch pipeline; likely a GStreamer issue or an error in the pipeline string you specified in the 'device' argument to librespot.");
        let pipeline = pipelinee
            .dynamic_cast::<gst::Pipeline>()
            .expect("couldn't cast pipeline element at runtime!");
        let bus = pipeline.get_bus().expect("couldn't get bus from pipeline");
        let mainloop = glib::MainLoop::new(None, false);
        let appsrce: gst::Element = pipeline
            .get_by_name("appsrc0")
            .expect("couldn't get appsrc from pipeline");
        let appsrc: gst_app::AppSrc = appsrce
            .dynamic_cast::<gst_app::AppSrc>()
            .expect("couldn't cast AppSrc element at runtime!");
        let bufferpool = gst::BufferPool::new();
        let appsrc_caps = appsrc.get_caps().expect("couldn't get appsrc caps");
        let mut conf = bufferpool.get_config();
        conf.set_params(Some(&appsrc_caps), 2048 * format.size() as u32, 0, 0);
        bufferpool
            .set_config(conf)
            .expect("couldn't configure the buffer pool");
        bufferpool
            .set_active(true)
            .expect("couldn't activate buffer pool");

        let (tx, rx) = sync_channel::<Vec<u8>>(64 * format.size());
        thread::spawn(move || {
            for data in rx {
                let buffer = bufferpool.acquire_buffer(None);
                if !buffer.is_err() {
                    let mut okbuffer = buffer.unwrap();
                    let mutbuf = okbuffer.make_mut();
                    mutbuf.set_size(data.len());
                    mutbuf
                        .copy_from_slice(0, data.as_bytes())
                        .expect("failed to copy from slice");
                    let _eat = appsrc.push_buffer(okbuffer);
                }
            }
        });

        thread::spawn(move || {
            let thread_mainloop = mainloop;
            let watch_mainloop = thread_mainloop.clone();
            bus.add_watch(move |_, msg| {
                match msg.view() {
                    MessageView::Eos(..) => watch_mainloop.quit(),
                    MessageView::Error(err) => {
                        println!(
                            "Error from {:?}: {} ({:?})",
                            err.get_src().map(|s| s.get_path_string()),
                            err.get_error(),
                            err.get_debug()
                        );
                        watch_mainloop.quit();
                    }
                    _ => (),
                };

                glib::Continue(true)
            })
            .expect("failed to add bus watch");
            thread_mainloop.run();
        });

        pipeline
            .set_state(gst::State::Playing)
            .expect("unable to set the pipeline to the `Playing` state");

        Self {
            tx: tx,
            pipeline: pipeline,
            format: format,
        }
    }
}

impl Sink for GstreamerSink {
    start_stop_noop!();
    sink_as_bytes!();
}

impl SinkAsBytes for GstreamerSink {
    fn write_bytes(&mut self, data: &[u8]) -> io::Result<()> {
        // Copy expensively (in to_vec()) to avoid thread synchronization
        self.tx
            .send(data.to_vec())
            .expect("tx send failed in write function");
        Ok(())
    }
}
<commit_msg>Fix GStreamer buffer pool size [ref #660 review]<commit_after>use super::{Open, Sink, SinkAsBytes};
use crate::audio::AudioPacket;
use crate::config::AudioFormat;
use crate::player::{NUM_CHANNELS, SAMPLE_RATE};
use gst::prelude::*;
use gst::*;
use std::sync::mpsc::{sync_channel, SyncSender};
use std::{io, thread};
use zerocopy::AsBytes;

#[allow(dead_code)]
pub struct GstreamerSink {
    tx: SyncSender<Vec<u8>>,
    pipeline: gst::Pipeline,
    format: AudioFormat,
}

impl Open for GstreamerSink {
    fn open(device: Option<String>, format: AudioFormat) -> GstreamerSink {
        info!("Using GStreamer sink with format: {:?}", format);
        gst::init().expect("failed to init GStreamer!");

        // GStreamer calls S24 and S24_3 different from the rest of the world
        let gst_format = match format {
            AudioFormat::S24 => "S24_32".to_string(),
            AudioFormat::S24_3 => "S24".to_string(),
            _ => format!("{:?}", format),
        };
        let sample_size = format.size();
        let gst_bytes = 2048 * sample_size;

        let pipeline_str_preamble = format!(
            "appsrc caps=\"audio/x-raw,format={}LE,layout=interleaved,channels={},rate={}\" block=true max-bytes={} name=appsrc0 ",
            gst_format, NUM_CHANNELS, SAMPLE_RATE, gst_bytes
        );
        let pipeline_str_rest = r#" ! audioconvert ! autoaudiosink"#;
        let pipeline_str: String = match device {
            Some(x) => format!("{}{}", pipeline_str_preamble, x),
            None => format!("{}{}", pipeline_str_preamble, pipeline_str_rest),
        };
        info!("Pipeline: {}", pipeline_str);

        gst::init().unwrap();
        let pipelinee = gst::parse_launch(&*pipeline_str).expect("Couldn't launch pipeline; likely a GStreamer issue or an error in the pipeline string you specified in the 'device' argument to librespot.");
        let pipeline = pipelinee
            .dynamic_cast::<gst::Pipeline>()
            .expect("couldn't cast pipeline element at runtime!");
        let bus = pipeline.get_bus().expect("couldn't get bus from pipeline");
        let mainloop = glib::MainLoop::new(None, false);
        let appsrce: gst::Element = pipeline
            .get_by_name("appsrc0")
            .expect("couldn't get appsrc from pipeline");
        let appsrc: gst_app::AppSrc = appsrce
            .dynamic_cast::<gst_app::AppSrc>()
            .expect("couldn't cast AppSrc element at runtime!");
        let bufferpool = gst::BufferPool::new();
        let appsrc_caps = appsrc.get_caps().expect("couldn't get appsrc caps");
        let mut conf = bufferpool.get_config();
        conf.set_params(Some(&appsrc_caps), 4096 * sample_size as u32, 0, 0);
        bufferpool
            .set_config(conf)
            .expect("couldn't configure the buffer pool");
        bufferpool
            .set_active(true)
            .expect("couldn't activate buffer pool");

        let (tx, rx) = sync_channel::<Vec<u8>>(64 * sample_size);
        thread::spawn(move || {
            for data in rx {
                let buffer = bufferpool.acquire_buffer(None);
                if !buffer.is_err() {
                    let mut okbuffer = buffer.unwrap();
                    let mutbuf = okbuffer.make_mut();
                    mutbuf.set_size(data.len());
                    mutbuf
                        .copy_from_slice(0, data.as_bytes())
                        .expect("failed to copy from slice");
                    let _eat = appsrc.push_buffer(okbuffer);
                }
            }
        });

        thread::spawn(move || {
            let thread_mainloop = mainloop;
            let watch_mainloop = thread_mainloop.clone();
            bus.add_watch(move |_, msg| {
                match msg.view() {
                    MessageView::Eos(..) => watch_mainloop.quit(),
                    MessageView::Error(err) => {
                        println!(
                            "Error from {:?}: {} ({:?})",
                            err.get_src().map(|s| s.get_path_string()),
                            err.get_error(),
                            err.get_debug()
                        );
                        watch_mainloop.quit();
                    }
                    _ => (),
                };

                glib::Continue(true)
            })
            .expect("failed to add bus watch");
            thread_mainloop.run();
        });

        pipeline
            .set_state(gst::State::Playing)
            .expect("unable to set the pipeline to the `Playing` state");

        Self {
            tx: tx,
            pipeline: pipeline,
            format: format,
        }
    }
}

impl Sink for GstreamerSink {
    start_stop_noop!();
    sink_as_bytes!();
}

impl SinkAsBytes for GstreamerSink {
    fn write_bytes(&mut self, data: &[u8]) -> io::Result<()> {
        // Copy expensively (in to_vec()) to avoid thread synchronization
        self.tx
            .send(data.to_vec())
            .expect("tx send failed in write function");
        Ok(())
    }
}
<|endoftext|>