<commit_before>/*!
`SHA-256`.

There has been considerable degradation of public confidence in the
security conjectures for many hash functions, including `SHA-256`.
However, for the moment, there do not appear to be alternatives that
inspire satisfactory levels of confidence. One can hope that NIST's
SHA-3 competition will improve the situation.
*/
#[cfg(test)]
extern crate rustc_serialize;
use ffi::{crypto_hash_sha256, crypto_hash_sha256_BYTES};

hash_module!(crypto_hash_sha256,
             crypto_hash_sha256_BYTES,
             64);

#[test]
fn test_vector_1() {
    // hash of empty string
    let x = [];
    let h_expected = [0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
                      0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
                      0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
                      0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55];
    let Digest(h) = hash(&x);
    assert!(h == h_expected);
}

#[test]
fn test_vector_2() {
    // The quick brown fox jumps over the lazy dog
    let x = [0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63,
             0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20,
             0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70,
             0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
             0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20,
             0x64, 0x6f, 0x67];
    let h_expected = [0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
                      0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
                      0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
                      0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92];
    let Digest(h) = hash(&x);
    assert!(h == h_expected);
}

#[cfg(test)]
fn test_nist_vector(filename: &str) {
    use self::rustc_serialize::hex::{FromHex};
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    let mut r = BufReader::new(File::open(filename).unwrap());
    let mut line = String::new();
    loop {
        line.clear();
        r.read_line(&mut line).unwrap();
        if line.len() == 0 {
            break;
        }
        let starts_with_len = line.starts_with("Len = ");
        if  starts_with_len {
            let len: usize = line[6..].trim().parse().unwrap();
            line.clear();
            r.read_line(&mut line).unwrap();
            let rawmsg = line[6..].from_hex().unwrap();
            let msg = &rawmsg[..len/8];
            line.clear();
            r.read_line(&mut line).unwrap();
            let md = line[5..].from_hex().unwrap();
            let Digest(digest) = hash(msg);
            assert!(digest == md);
       }
    }
}

#[test]
fn test_vectors_nist_short() {
    test_nist_vector("testvectors/SHA256ShortMsg.rsp");
}

#[test]
fn test_vectors_nist_long() {
    test_nist_vector("testvectors/SHA256LongMsg.rsp");
}
<commit_msg>Fixes for latest rust-nightly<commit_after>/*!
`SHA-256`.

There has been considerable degradation of public confidence in the
security conjectures for many hash functions, including `SHA-256`.
However, for the moment, there do not appear to be alternatives that
inspire satisfactory levels of confidence. One can hope that NIST's
SHA-3 competition will improve the situation.
*/
#[cfg(test)]
extern crate rustc_serialize;
use ffi::{crypto_hash_sha256, crypto_hash_sha256_BYTES};

hash_module!(crypto_hash_sha256,
             crypto_hash_sha256_BYTES,
             64);

#[test]
fn test_vector_1() {
    // hash of empty string
    let x = [];
    let h_expected = [0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
                      0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
                      0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
                      0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55];
    let Digest(h) = hash(&x);
    assert!(h == h_expected);
}

#[test]
fn test_vector_2() {
    // The quick brown fox jumps over the lazy dog
    let x = [0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63,
             0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20,
             0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70,
             0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
             0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20,
             0x64, 0x6f, 0x67];
    let h_expected = [0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
                      0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
                      0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
                      0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92];
    let Digest(h) = hash(&x);
    assert!(h == h_expected);
}

#[cfg(test)]
fn test_nist_vector(filename: &str) {
    use self::rustc_serialize::hex::{FromHex};
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    let mut r = BufReader::new(File::open(filename).unwrap());
    let mut line = String::new();
    loop {
        line.clear();
        r.read_line(&mut line).unwrap();
        if line.len() == 0 {
            break;
        }
        let starts_with_len = line.starts_with("Len = ");
        if  starts_with_len {
            let len: usize = line[6..].trim().parse().unwrap();
            line.clear();
            r.read_line(&mut line).unwrap();
            let rawmsg = line[6..].from_hex().unwrap();
            let msg = &rawmsg[..len/8];
            line.clear();
            r.read_line(&mut line).unwrap();
            let md = line[5..].from_hex().unwrap();
            let Digest(digest) = hash(msg);
            assert!(&digest[..] == &md[..]);
       }
    }
}

#[test]
fn test_vectors_nist_short() {
    test_nist_vector("testvectors/SHA256ShortMsg.rsp");
}

#[test]
fn test_vectors_nist_long() {
    test_nist_vector("testvectors/SHA256LongMsg.rsp");
}
<|endoftext|>


<commit_before>use super::{roles::*, SubsurfaceRole, SurfaceAttributes};
use std::sync::Mutex;
use wayland_server::protocol::wl_surface::WlSurface;

/// Node of a subsurface tree, holding some user specified data type U
/// at each node
///
/// This type is internal to Smithay, and should not appear in the
/// public API
///
/// It is a bidirectional tree, meaning we can move along it in both
/// direction (top-bottom or bottom-up). We are taking advantage of the
/// fact that lifetime of objects are decided by Wayland-server to ensure
/// the cleanup will be done properly, and we won't leak anything.
///
/// Each node also appears within its children list, to allow relative placement
/// between them.
pub struct SurfaceData<R> {
    parent: Option<WlSurface>,
    children: Vec<WlSurface>,
    role: R,
    attributes: SurfaceAttributes,
}

pub enum Location {
    Before,
    After,
}

/// Possible actions to do after handling a node diring tree traversal
pub enum TraversalAction<T> {
    /// Traverse its children as well, providing them the data T
    DoChildren(T),
    /// Skip its children
    SkipChildren,
    /// Stop traversal completely
    Break,
}

impl<R: Default> SurfaceData<R> {
    pub fn new() -> Mutex<SurfaceData<R>> {
        Mutex::new(SurfaceData {
            parent: None,
            children: vec![],
            role: Default::default(),
            attributes: Default::default(),
        })
    }
}

impl<R> SurfaceData<R>
where
    R: 'static,
{
    /// Initializes the surface, must be called at creation for state coherence
    pub fn init(surface: &WlSurface) {
        let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut my_data = my_data_mutex.lock().unwrap();
        debug_assert!(my_data.children.is_empty());
        my_data.children.push(surface.clone());
    }

    /// Cleans the `as_ref().user_data` of that surface, must be called when it is destroyed
    pub fn cleanup(surface: &WlSurface) {
        let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut my_data = my_data_mutex.lock().unwrap();
        if let Some(old_parent) = my_data.parent.take() {
            // We had a parent, lets unregister ourselves from it
            let old_parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut old_parent_guard = old_parent_mutex.lock().unwrap();
            old_parent_guard
                .children
                .retain(|c| !c.as_ref().equals(surface.as_ref()));
        }
        // orphan all our children
        for child in &my_data.children {
            // don't do anything if this child is ourselves
            if child.as_ref().equals(surface.as_ref()) {
                continue;
            }
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut child_guard = child_mutex.lock().unwrap();
            child_guard.parent = None;
        }
    }
}

impl<R: RoleType + 'static> SurfaceData<R> {
    pub fn has_a_role(surface: &WlSurface) -> bool {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let data_guard = data_mutex.lock().unwrap();
        <R as RoleType>::has_role(&data_guard.role)
    }

    /// Check whether a surface has a given role
    pub fn has_role<RoleData>(surface: &WlSurface) -> bool
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::has(&data_guard.role)
    }

    /// Register that this surface has a role, fails if it already has one
    pub fn give_role<RoleData>(surface: &WlSurface) -> Result<(), ()>
    where
        R: Role<RoleData>,
        RoleData: Default,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::set(&mut data_guard.role)
    }

    /// Register that this surface has a role with given data
    ///
    /// Fails if it already has one and returns the data
    pub fn give_role_with<RoleData>(surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::set_with(&mut data_guard.role, data)
    }

    /// Register that this surface has no role and returns the data
    ///
    /// It is a noop if this surface already didn't have one, but fails if
    /// the role was "subsurface", it must be removed by the `unset_parent` method.
    pub fn remove_role<RoleData>(surface: &WlSurface) -> Result<RoleData, WrongRole>
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::unset(&mut data_guard.role)
    }

    /// Access to the role data
    pub fn with_role_data<RoleData, F, T>(surface: &WlSurface, f: F) -> Result<T, WrongRole>
    where
        R: Role<RoleData>,
        F: FnOnce(&mut RoleData) -> T,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
        Ok(f(data))
    }
}

impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
    /// Checks if the first surface is an ancestor of the second
    pub fn is_ancestor(a: &WlSurface, b: &WlSurface) -> bool {
        let b_mutex = b.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let b_guard = b_mutex.lock().unwrap();
        if let Some(ref parent) = b_guard.parent {
            if parent.as_ref().equals(a.as_ref()) {
                true
            } else {
                Self::is_ancestor(a, parent)
            }
        } else {
            false
        }
    }

    /// Sets the parent of a surface
    ///
    /// if this surface already has a role, does nothing and fails, otherwise
    /// its role is now to be a subsurface
    pub fn set_parent(child: &WlSurface, parent: &WlSurface) -> Result<(), ()> {
        debug_assert!(child.as_ref().is_alive());
        debug_assert!(parent.as_ref().is_alive());
        // ensure the child is not already a parent of the parent
        if Self::is_ancestor(child, parent) {
            return Err(());
        }

        // change child's parent
        {
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut child_guard = child_mutex.lock().unwrap();
            // if surface already has a role, it cannot become a subsurface
            <R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
            debug_assert!(child_guard.parent.is_none());
            child_guard.parent = Some(parent.clone());
        }
        // register child to new parent
        {
            let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut parent_guard = parent_mutex.lock().unwrap();
            parent_guard.children.push(child.clone())
        }
        Ok(())
    }

    /// Remove a pre-existing parent of this child
    ///
    /// Does nothing if it has no parent
    pub fn unset_parent(child: &WlSurface) {
        debug_assert!(child.as_ref().is_alive());
        let old_parent = {
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut child_guard = child_mutex.lock().unwrap();
            let old_parent = child_guard.parent.take();
            if old_parent.is_some() {
                // We had a parent, so this does not have a role any more
                <R as Role<SubsurfaceRole>>::unset(&mut child_guard.role)
                    .expect("Surface had a parent but not the subsurface role?!");
            }
            old_parent
        };
        // unregister from our parent
        if let Some(old_parent) = old_parent {
            let parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut parent_guard = parent_mutex.lock().unwrap();
            parent_guard
                .children
                .retain(|c| !c.as_ref().equals(child.as_ref()));
        }
    }

    /// Retrieve the parent surface (if any) of this surface
    pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
        let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let child_guard = child_mutex.lock().unwrap();
        child_guard.parent.as_ref().cloned()
    }

    /// Retrieve the children surface (if any) of this surface
    pub fn get_children(parent: &WlSurface) -> Vec<WlSurface> {
        let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let parent_guard = parent_mutex.lock().unwrap();
        parent_guard
            .children
            .iter()
            .filter(|s| !s.as_ref().equals(parent.as_ref()))
            .cloned()
            .collect()
    }

    /// Reorders a surface relative to one of its sibling
    ///
    /// Fails if `relative_to` is not a sibling or parent of `surface`.
    pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
        let parent = {
            let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let data_guard = data_mutex.lock().unwrap();
            data_guard.parent.as_ref().cloned().unwrap()
        };

        fn index_of(surface: &WlSurface, slice: &[WlSurface]) -> Option<usize> {
            for (i, s) in slice.iter().enumerate() {
                if s.as_ref().equals(surface.as_ref()) {
                    return Some(i);
                }
            }
            None
        }

        let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut parent_guard = parent_mutex.lock().unwrap();
        let my_index = index_of(surface, &parent_guard.children).unwrap();
        let mut other_index = match index_of(relative_to, &parent_guard.children) {
            Some(idx) => idx,
            None => return Err(()),
        };
        let me = parent_guard.children.remove(my_index);
        if my_index < other_index {
            other_index -= 1;
        }
        let new_index = match to {
            Location::Before => other_index,
            Location::After => other_index + 1,
        };
        parent_guard.children.insert(new_index, me);
        Ok(())
    }
}

impl<R: 'static> SurfaceData<R> {
    /// Access the attributes associated with a surface
    ///
    /// Note that an internal lock is taken during access of this data,
    /// so the tree cannot be manipulated at the same time
    pub fn with_data<T, F>(surface: &WlSurface, f: F) -> T
    where
        F: FnOnce(&mut SurfaceAttributes) -> T,
    {
        let data_mutex = surface
            .as_ref()
            .user_data::<Mutex<SurfaceData<R>>>()
            .expect("Accessing the data of foreign surfaces is not supported.");
        let mut data_guard = data_mutex.lock().unwrap();
        f(&mut data_guard.attributes)
    }

    /// Access sequentially the attributes associated with a surface tree,
    /// in a depth-first order.
    ///
    /// Note that an internal lock is taken during access of this data,
    /// so the tree cannot be manipulated at the same time.
    ///
    /// The first callback determines if this node children should be processed or not.
    ///
    /// The second actually does the processing, being called on children in display depth
    /// order.
    ///
    /// The third is called once all the children of a node has been processed (including itself), only if the first
    /// returned `DoChildren`, and gives an opportunity to early stop
    pub fn map_tree<F1, F2, F3, T>(
        surface: &WlSurface,
        initial: &T,
        mut filter: F1,
        mut processor: F2,
        mut post_filter: F3,
        reverse: bool,
    ) where
        F1: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction<T>,
        F2: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T),
        F3: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> bool,
    {
        Self::map(
            surface,
            initial,
            &mut filter,
            &mut processor,
            &mut post_filter,
            reverse,
        );
    }

    // helper function for map_tree
    fn map<F1, F2, F3, T>(
        surface: &WlSurface,
        initial: &T,
        filter: &mut F1,
        processor: &mut F2,
        post_filter: &mut F3,
        reverse: bool,
    ) -> bool
    where
        F1: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction<T>,
        F2: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T),
        F3: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> bool,
    {
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        let data_guard = &mut *data_guard;
        // call the filter on ourselves
        match filter(surface, &mut data_guard.attributes, &mut data_guard.role, initial) {
            TraversalAction::DoChildren(t) => {
                // loop over children
                if reverse {
                    for c in data_guard.children.iter().rev() {
                        if c.as_ref().equals(surface.as_ref()) {
                            processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                        } else if !Self::map(c, &t, filter, processor, post_filter, true) {
                            return false;
                        }
                    }
                } else {
                    for c in &data_guard.children {
                        if c.as_ref().equals(surface.as_ref()) {
                            processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                        } else if !Self::map(c, &t, filter, processor, post_filter, false) {
                            return false;
                        }
                    }
                }
                post_filter(surface, &mut data_guard.attributes, &mut data_guard.role, initial)
            }
            TraversalAction::SkipChildren => {
                // still process ourselves
                processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                true
            }
            TraversalAction::Break => false,
        }
    }
}
<commit_msg>wayland: fix deadlock in SurfaceData::cleanup (#166)<commit_after>use super::{roles::*, SubsurfaceRole, SurfaceAttributes};
use std::sync::Mutex;
use wayland_server::protocol::wl_surface::WlSurface;

/// Node of a subsurface tree, holding some user specified data type U
/// at each node
///
/// This type is internal to Smithay, and should not appear in the
/// public API
///
/// It is a bidirectional tree, meaning we can move along it in both
/// direction (top-bottom or bottom-up). We are taking advantage of the
/// fact that lifetime of objects are decided by Wayland-server to ensure
/// the cleanup will be done properly, and we won't leak anything.
///
/// Each node also appears within its children list, to allow relative placement
/// between them.
pub struct SurfaceData<R> {
    parent: Option<WlSurface>,
    children: Vec<WlSurface>,
    role: R,
    attributes: SurfaceAttributes,
}

pub enum Location {
    Before,
    After,
}

/// Possible actions to do after handling a node diring tree traversal
pub enum TraversalAction<T> {
    /// Traverse its children as well, providing them the data T
    DoChildren(T),
    /// Skip its children
    SkipChildren,
    /// Stop traversal completely
    Break,
}

impl<R: Default> SurfaceData<R> {
    pub fn new() -> Mutex<SurfaceData<R>> {
        Mutex::new(SurfaceData {
            parent: None,
            children: vec![],
            role: Default::default(),
            attributes: Default::default(),
        })
    }
}

impl<R> SurfaceData<R>
where
    R: 'static,
{
    /// Initializes the surface, must be called at creation for state coherence
    pub fn init(surface: &WlSurface) {
        let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut my_data = my_data_mutex.lock().unwrap();
        debug_assert!(my_data.children.is_empty());
        my_data.children.push(surface.clone());
    }

    /// Cleans the `as_ref().user_data` of that surface, must be called when it is destroyed
    pub fn cleanup(surface: &WlSurface) {
        let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut my_data = my_data_mutex.lock().unwrap();
        if let Some(old_parent) = my_data.parent.take() {
            // We had a parent, lets unregister ourselves from it
            let old_parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut old_parent_guard = old_parent_mutex.lock().unwrap();
            old_parent_guard
                .children
                .retain(|c| !c.as_ref().equals(surface.as_ref()));
        }
        // orphan all our children
        for child in &my_data.children {
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            if std::ptr::eq(child_mutex, my_data_mutex) {
                // This child is ourselves, don't do anything.
                continue;
            }

            let mut child_guard = child_mutex.lock().unwrap();
            child_guard.parent = None;
        }
    }
}

impl<R: RoleType + 'static> SurfaceData<R> {
    pub fn has_a_role(surface: &WlSurface) -> bool {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let data_guard = data_mutex.lock().unwrap();
        <R as RoleType>::has_role(&data_guard.role)
    }

    /// Check whether a surface has a given role
    pub fn has_role<RoleData>(surface: &WlSurface) -> bool
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::has(&data_guard.role)
    }

    /// Register that this surface has a role, fails if it already has one
    pub fn give_role<RoleData>(surface: &WlSurface) -> Result<(), ()>
    where
        R: Role<RoleData>,
        RoleData: Default,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::set(&mut data_guard.role)
    }

    /// Register that this surface has a role with given data
    ///
    /// Fails if it already has one and returns the data
    pub fn give_role_with<RoleData>(surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::set_with(&mut data_guard.role, data)
    }

    /// Register that this surface has no role and returns the data
    ///
    /// It is a noop if this surface already didn't have one, but fails if
    /// the role was "subsurface", it must be removed by the `unset_parent` method.
    pub fn remove_role<RoleData>(surface: &WlSurface) -> Result<RoleData, WrongRole>
    where
        R: Role<RoleData>,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        <R as Role<RoleData>>::unset(&mut data_guard.role)
    }

    /// Access to the role data
    pub fn with_role_data<RoleData, F, T>(surface: &WlSurface, f: F) -> Result<T, WrongRole>
    where
        R: Role<RoleData>,
        F: FnOnce(&mut RoleData) -> T,
    {
        debug_assert!(surface.as_ref().is_alive());
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
        Ok(f(data))
    }
}

impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
    /// Checks if the first surface is an ancestor of the second
    pub fn is_ancestor(a: &WlSurface, b: &WlSurface) -> bool {
        let b_mutex = b.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let b_guard = b_mutex.lock().unwrap();
        if let Some(ref parent) = b_guard.parent {
            if parent.as_ref().equals(a.as_ref()) {
                true
            } else {
                Self::is_ancestor(a, parent)
            }
        } else {
            false
        }
    }

    /// Sets the parent of a surface
    ///
    /// if this surface already has a role, does nothing and fails, otherwise
    /// its role is now to be a subsurface
    pub fn set_parent(child: &WlSurface, parent: &WlSurface) -> Result<(), ()> {
        debug_assert!(child.as_ref().is_alive());
        debug_assert!(parent.as_ref().is_alive());
        // ensure the child is not already a parent of the parent
        if Self::is_ancestor(child, parent) {
            return Err(());
        }

        // change child's parent
        {
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut child_guard = child_mutex.lock().unwrap();
            // if surface already has a role, it cannot become a subsurface
            <R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
            debug_assert!(child_guard.parent.is_none());
            child_guard.parent = Some(parent.clone());
        }
        // register child to new parent
        {
            let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut parent_guard = parent_mutex.lock().unwrap();
            parent_guard.children.push(child.clone())
        }
        Ok(())
    }

    /// Remove a pre-existing parent of this child
    ///
    /// Does nothing if it has no parent
    pub fn unset_parent(child: &WlSurface) {
        debug_assert!(child.as_ref().is_alive());
        let old_parent = {
            let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut child_guard = child_mutex.lock().unwrap();
            let old_parent = child_guard.parent.take();
            if old_parent.is_some() {
                // We had a parent, so this does not have a role any more
                <R as Role<SubsurfaceRole>>::unset(&mut child_guard.role)
                    .expect("Surface had a parent but not the subsurface role?!");
            }
            old_parent
        };
        // unregister from our parent
        if let Some(old_parent) = old_parent {
            let parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let mut parent_guard = parent_mutex.lock().unwrap();
            parent_guard
                .children
                .retain(|c| !c.as_ref().equals(child.as_ref()));
        }
    }

    /// Retrieve the parent surface (if any) of this surface
    pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
        let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let child_guard = child_mutex.lock().unwrap();
        child_guard.parent.as_ref().cloned()
    }

    /// Retrieve the children surface (if any) of this surface
    pub fn get_children(parent: &WlSurface) -> Vec<WlSurface> {
        let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let parent_guard = parent_mutex.lock().unwrap();
        parent_guard
            .children
            .iter()
            .filter(|s| !s.as_ref().equals(parent.as_ref()))
            .cloned()
            .collect()
    }

    /// Reorders a surface relative to one of its sibling
    ///
    /// Fails if `relative_to` is not a sibling or parent of `surface`.
    pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
        let parent = {
            let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
            let data_guard = data_mutex.lock().unwrap();
            data_guard.parent.as_ref().cloned().unwrap()
        };

        fn index_of(surface: &WlSurface, slice: &[WlSurface]) -> Option<usize> {
            for (i, s) in slice.iter().enumerate() {
                if s.as_ref().equals(surface.as_ref()) {
                    return Some(i);
                }
            }
            None
        }

        let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut parent_guard = parent_mutex.lock().unwrap();
        let my_index = index_of(surface, &parent_guard.children).unwrap();
        let mut other_index = match index_of(relative_to, &parent_guard.children) {
            Some(idx) => idx,
            None => return Err(()),
        };
        let me = parent_guard.children.remove(my_index);
        if my_index < other_index {
            other_index -= 1;
        }
        let new_index = match to {
            Location::Before => other_index,
            Location::After => other_index + 1,
        };
        parent_guard.children.insert(new_index, me);
        Ok(())
    }
}

impl<R: 'static> SurfaceData<R> {
    /// Access the attributes associated with a surface
    ///
    /// Note that an internal lock is taken during access of this data,
    /// so the tree cannot be manipulated at the same time
    pub fn with_data<T, F>(surface: &WlSurface, f: F) -> T
    where
        F: FnOnce(&mut SurfaceAttributes) -> T,
    {
        let data_mutex = surface
            .as_ref()
            .user_data::<Mutex<SurfaceData<R>>>()
            .expect("Accessing the data of foreign surfaces is not supported.");
        let mut data_guard = data_mutex.lock().unwrap();
        f(&mut data_guard.attributes)
    }

    /// Access sequentially the attributes associated with a surface tree,
    /// in a depth-first order.
    ///
    /// Note that an internal lock is taken during access of this data,
    /// so the tree cannot be manipulated at the same time.
    ///
    /// The first callback determines if this node children should be processed or not.
    ///
    /// The second actually does the processing, being called on children in display depth
    /// order.
    ///
    /// The third is called once all the children of a node has been processed (including itself), only if the first
    /// returned `DoChildren`, and gives an opportunity to early stop
    pub fn map_tree<F1, F2, F3, T>(
        surface: &WlSurface,
        initial: &T,
        mut filter: F1,
        mut processor: F2,
        mut post_filter: F3,
        reverse: bool,
    ) where
        F1: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction<T>,
        F2: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T),
        F3: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> bool,
    {
        Self::map(
            surface,
            initial,
            &mut filter,
            &mut processor,
            &mut post_filter,
            reverse,
        );
    }

    // helper function for map_tree
    fn map<F1, F2, F3, T>(
        surface: &WlSurface,
        initial: &T,
        filter: &mut F1,
        processor: &mut F2,
        post_filter: &mut F3,
        reverse: bool,
    ) -> bool
    where
        F1: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction<T>,
        F2: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T),
        F3: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> bool,
    {
        let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
        let mut data_guard = data_mutex.lock().unwrap();
        let data_guard = &mut *data_guard;
        // call the filter on ourselves
        match filter(surface, &mut data_guard.attributes, &mut data_guard.role, initial) {
            TraversalAction::DoChildren(t) => {
                // loop over children
                if reverse {
                    for c in data_guard.children.iter().rev() {
                        if c.as_ref().equals(surface.as_ref()) {
                            processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                        } else if !Self::map(c, &t, filter, processor, post_filter, true) {
                            return false;
                        }
                    }
                } else {
                    for c in &data_guard.children {
                        if c.as_ref().equals(surface.as_ref()) {
                            processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                        } else if !Self::map(c, &t, filter, processor, post_filter, false) {
                            return false;
                        }
                    }
                }
                post_filter(surface, &mut data_guard.attributes, &mut data_guard.role, initial)
            }
            TraversalAction::SkipChildren => {
                // still process ourselves
                processor(surface, &mut data_guard.attributes, &mut data_guard.role, initial);
                true
            }
            TraversalAction::Break => false,
        }
    }
}
<|endoftext|>


<commit_before>use curve::point::*;
use field::prime_field::PrimeField;
use std::ops::Add;
use std::ops::AddAssign;

pub trait EdwardsCurve : Copy {
    type Scalar : PrimeField + Copy;

    fn d_val() -> Self::Scalar;
}

/// Edwards curve point in homogeneous extended coordinates.
#[derive(Copy, Clone)]
pub struct EdwardsExtended<C : EdwardsCurve> {
    x : C::Scalar,
    y : C::Scalar,
    z : C::Scalar,
    t : C::Scalar
}

impl<'b, C : EdwardsCurve> AddAssign<&'b EdwardsExtended<C>>
    for EdwardsExtended<C> {
    fn add_assign(&mut self, rhs: &'b EdwardsExtended<C>) {
        let a = self.x * rhs.x;
        let b = self.y * rhs.y;
        let c = self.t * C::d_val() * rhs.t;
        let d = self.z * rhs.z;
        let e = ((self.x + self.y) * (rhs.x + rhs.y)) - a - b;
        let f = d - c;
        let g = d + c;
        let h = b - a;
        let x3 = e * f;
        let y3 = g * h;
        let z3 = f * g;
        let t3 = e * h;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }
}

impl<C : EdwardsCurve> AddAssign<EdwardsExtended<C>>
    for EdwardsExtended<C> {
    fn add_assign(&mut self, rhs: EdwardsExtended<C>) {
        *self += &rhs;
    }
}

impl<'a, 'b, C : EdwardsCurve> Add<&'b EdwardsExtended<C>>
    for &'a EdwardsExtended<C> {
    type Output = EdwardsExtended<C>;

    fn add(self, rhs: &'b EdwardsExtended<C>) -> EdwardsExtended<C> {
        let mut out = self.clone();
        out += rhs;
        out
    }
}

impl<C : EdwardsCurve> Add<EdwardsExtended<C>> for EdwardsExtended<C> {
    type Output = EdwardsExtended<C>;

    fn add(self, rhs: EdwardsExtended<C>) -> EdwardsExtended<C> {
        &self + &rhs
    }
}

impl<C: EdwardsCurve> Point for EdwardsExtended<C> {
    type Scalar = C::Scalar;

    fn zero() -> Self {
        EdwardsExtended {
            x: C::Scalar::zero(),
            y: C::Scalar::one(),
            z: C::Scalar::one(),
            t: C::Scalar::one()
        }
    }

    fn init(&mut self, x: C::Scalar, y: C::Scalar) {
        self.x = x;
        self.y = y;
        self.z = C::Scalar::one();
        self.t = C::Scalar::one();
    }

    fn scalar_mult(&mut self, rhs: &mut Self::Scalar) {
        rhs.normalize();
        self.scalar_mult_normalized(rhs);
    }

    fn scalar_mult_normalized(&mut self, rhs: &Self::Scalar) {
        let mut r0 = Self::zero();
        let mut r1 = self.clone();
        let nbits = C::Scalar::nbits();

        for i in 0..nbits {
            let idx = nbits - 1 - i;
            let bit = rhs.bit_normalized(idx);
            let tmask = C::Scalar::filled(bit);
            let fmask = C::Scalar::filled(!bit);
            let mut r0d = r0.doubled();
            let mut r1d = r1.doubled();

            r0 += r1;
            r0.x.normalize();
            r0.y.normalize();
            r0.z.normalize();
            r0.t.normalize();
            r1 = r0;

            r0.x.normalized_bitand(&fmask);
            r0.y.normalized_bitand(&fmask);
            r0.z.normalized_bitand(&fmask);
            r0.t.normalized_bitand(&fmask);

            r1.x.normalized_bitand(&tmask);
            r1.y.normalized_bitand(&tmask);
            r1.z.normalized_bitand(&tmask);
            r1.t.normalized_bitand(&tmask);

            r0d.x.normalize_self_bitand(&tmask);
            r0d.y.normalize_self_bitand(&tmask);
            r0d.z.normalize_self_bitand(&tmask);
            r0d.t.normalize_self_bitand(&tmask);

            r1d.x.normalize_self_bitand(&fmask);
            r1d.y.normalize_self_bitand(&fmask);
            r1d.z.normalize_self_bitand(&fmask);
            r1d.t.normalize_self_bitand(&fmask);

            r0.x.normalized_bitor(&r0d.x);
            r0.y.normalized_bitor(&r0d.y);
            r0.z.normalized_bitor(&r0d.z);
            r0.t.normalized_bitor(&r0d.t);

            r1.x.normalized_bitor(&r1d.x);
            r1.y.normalized_bitor(&r1d.y);
            r1.z.normalized_bitor(&r1d.z);
            r1.t.normalized_bitor(&r1d.t);
        }

        self.x = r0.x;
        self.y = r0.y;
        self.z = r0.z;
        self.t = r0.t;
    }

    fn double(&mut self) {
        let a = self.x.squared();
        let b = self.y.squared();
        let c = self.z.squared().small_mul(2);
        let d = a;
        let e = (self.x + self.y).squared() - a - b;
        let g = d + b;
        let f = g - c;
        let h = d - b;
        let x3 = e * f;
        let y3 = g * h;
        let z3 = f * g;
        let t3 = e * h;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }

    fn doubled(&self) -> Self {
        let mut out = self.clone();
        out.double();
        out
    }

    fn triple(&mut self) {
        let yy = self.y.squared();
        let xx = self.x.squared();
        let ap = yy + xx;
        let b = (self.z.squared().small_mul(2) - ap).small_mul(2);
        let xb = xx * b;
        let yb = yy * b;
        let aa = ap * (yy - xx);
        let f = aa - yb;
        let g = aa - xb;
        let xe = self.x * (yb + aa);
        let yh = self.y * (xb - aa);
        let zf = self.z * f;
        let zg = self.z * g;
        let x3 = xe * zf;
        let y3 = yh * zg;
        let z3 = zf * zg;
        let t3 = xe * yh;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }

    fn tripled(&self) -> Self {
        let mut out = self.clone();
        out.triple();
        out
    }
}
<commit_msg>Add comment on Montgomery ladder<commit_after>use curve::point::*;
use field::prime_field::PrimeField;
use std::ops::Add;
use std::ops::AddAssign;

pub trait EdwardsCurve : Copy {
    type Scalar : PrimeField + Copy;

    fn d_val() -> Self::Scalar;
}

/// Edwards curve point in homogeneous extended coordinates.
#[derive(Copy, Clone)]
pub struct EdwardsExtended<C : EdwardsCurve> {
    x : C::Scalar,
    y : C::Scalar,
    z : C::Scalar,
    t : C::Scalar
}

impl<'b, C : EdwardsCurve> AddAssign<&'b EdwardsExtended<C>>
    for EdwardsExtended<C> {
    fn add_assign(&mut self, rhs: &'b EdwardsExtended<C>) {
        let a = self.x * rhs.x;
        let b = self.y * rhs.y;
        let c = self.t * C::d_val() * rhs.t;
        let d = self.z * rhs.z;
        let e = ((self.x + self.y) * (rhs.x + rhs.y)) - a - b;
        let f = d - c;
        let g = d + c;
        let h = b - a;
        let x3 = e * f;
        let y3 = g * h;
        let z3 = f * g;
        let t3 = e * h;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }
}

impl<C : EdwardsCurve> AddAssign<EdwardsExtended<C>>
    for EdwardsExtended<C> {
    fn add_assign(&mut self, rhs: EdwardsExtended<C>) {
        *self += &rhs;
    }
}

impl<'a, 'b, C : EdwardsCurve> Add<&'b EdwardsExtended<C>>
    for &'a EdwardsExtended<C> {
    type Output = EdwardsExtended<C>;

    fn add(self, rhs: &'b EdwardsExtended<C>) -> EdwardsExtended<C> {
        let mut out = self.clone();
        out += rhs;
        out
    }
}

impl<C : EdwardsCurve> Add<EdwardsExtended<C>> for EdwardsExtended<C> {
    type Output = EdwardsExtended<C>;

    fn add(self, rhs: EdwardsExtended<C>) -> EdwardsExtended<C> {
        &self + &rhs
    }
}

impl<C: EdwardsCurve> Point for EdwardsExtended<C> {
    type Scalar = C::Scalar;

    fn zero() -> Self {
        EdwardsExtended {
            x: C::Scalar::zero(),
            y: C::Scalar::one(),
            z: C::Scalar::one(),
            t: C::Scalar::one()
        }
    }

    fn init(&mut self, x: C::Scalar, y: C::Scalar) {
        self.x = x;
        self.y = y;
        self.z = C::Scalar::one();
        self.t = C::Scalar::one();
    }

    fn scalar_mult(&mut self, rhs: &mut Self::Scalar) {
        rhs.normalize();
        self.scalar_mult_normalized(rhs);
    }

    fn scalar_mult_normalized(&mut self, rhs: &Self::Scalar) {
        // This is a branchless variant of the classic Montgomery
        // ladder using bitwise operations in lieu of branches.  It
        // costs an additional doubling operation per step, but
        // eliminates all control-flow dependence on the data.

        let mut r0 = Self::zero();
        let mut r1 = self.clone();
        let nbits = C::Scalar::nbits();

        for i in 0..nbits {
            let idx = nbits - 1 - i;
            let bit = rhs.bit_normalized(idx);
            let tmask = C::Scalar::filled(bit);
            let fmask = C::Scalar::filled(!bit);
            let mut r0d = r0.doubled();
            let mut r1d = r1.doubled();

            r0 += r1;
            r0.x.normalize();
            r0.y.normalize();
            r0.z.normalize();
            r0.t.normalize();
            r1 = r0;

            r0.x.normalized_bitand(&fmask);
            r0.y.normalized_bitand(&fmask);
            r0.z.normalized_bitand(&fmask);
            r0.t.normalized_bitand(&fmask);

            r0d.x.normalize_self_bitand(&tmask);
            r0d.y.normalize_self_bitand(&tmask);
            r0d.z.normalize_self_bitand(&tmask);
            r0d.t.normalize_self_bitand(&tmask);

            r0.x.normalized_bitor(&r0d.x);
            r0.y.normalized_bitor(&r0d.y);
            r0.z.normalized_bitor(&r0d.z);
            r0.t.normalized_bitor(&r0d.t);

            r1.x.normalized_bitand(&tmask);
            r1.y.normalized_bitand(&tmask);
            r1.z.normalized_bitand(&tmask);
            r1.t.normalized_bitand(&tmask);

            r1d.x.normalize_self_bitand(&fmask);
            r1d.y.normalize_self_bitand(&fmask);
            r1d.z.normalize_self_bitand(&fmask);
            r1d.t.normalize_self_bitand(&fmask);

            r1.x.normalized_bitor(&r1d.x);
            r1.y.normalized_bitor(&r1d.y);
            r1.z.normalized_bitor(&r1d.z);
            r1.t.normalized_bitor(&r1d.t);
        }

        self.x = r0.x;
        self.y = r0.y;
        self.z = r0.z;
        self.t = r0.t;
    }

    fn double(&mut self) {
        let a = self.x.squared();
        let b = self.y.squared();
        let c = self.z.squared().small_mul(2);
        let d = a;
        let e = (self.x + self.y).squared() - a - b;
        let g = d + b;
        let f = g - c;
        let h = d - b;
        let x3 = e * f;
        let y3 = g * h;
        let z3 = f * g;
        let t3 = e * h;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }

    fn doubled(&self) -> Self {
        let mut out = self.clone();
        out.double();
        out
    }

    fn triple(&mut self) {
        let yy = self.y.squared();
        let xx = self.x.squared();
        let ap = yy + xx;
        let b = (self.z.squared().small_mul(2) - ap).small_mul(2);
        let xb = xx * b;
        let yb = yy * b;
        let aa = ap * (yy - xx);
        let f = aa - yb;
        let g = aa - xb;
        let xe = self.x * (yb + aa);
        let yh = self.y * (xb - aa);
        let zf = self.z * f;
        let zg = self.z * g;
        let x3 = xe * zf;
        let y3 = yh * zg;
        let z3 = zf * zg;
        let t3 = xe * yh;

        self.x = x3;
        self.y = y3;
        self.z = z3;
        self.t = t3;
    }

    fn tripled(&self) -> Self {
        let mut out = self.clone();
        out.triple();
        out
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, Write};

use library;
use analysis;
use analysis::bounds::Bounds;
use analysis::functions::Visibility;
use analysis::namespaces;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body_chunk;
use super::general::{
    cfg_condition, cfg_deprecated, doc_hidden, not_version_condition, version_condition,
};
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use writer::primitives::tabs;
use writer::ToCode;

use std::result::Result as StdResult;
use std::fmt;

pub fn generate(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::functions::Info,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    if analysis.is_async_finish(env) {
        return Ok(());
    }

    let mut commented = false;
    let mut comment_prefix = "";
    let mut pub_prefix = if in_trait { "" } else { "pub " };

    match analysis.visibility {
        Visibility::Public => {}
        Visibility::Comment => {
            commented = true;
            comment_prefix = "//";
        }
        Visibility::Private => if in_trait {
            warn!(
                "Generating trait method for private function {}",
                analysis.glib_name
            );
        } else {
            pub_prefix = "";
        },
        Visibility::Hidden => return Ok(()),
    }
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(writeln!(w));
    if !in_trait || only_declaration {
        try!(cfg_deprecated(w, env, analysis.deprecated_version, commented, indent));
    }
    try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
    try!(version_condition(
        w,
        env,
        analysis.version,
        commented,
        indent,
    ));
    try!(not_version_condition(
        w,
        analysis.not_version,
        commented,
        indent,
    ));
    try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
    try!(writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        declaration,
        suffix
    ));

    if !only_declaration {
        let body = body_chunk(env, analysis).to_code(env);
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
    }

    if analysis.async_future.is_some() {
        let declaration = declaration_futures(env, analysis);
        let suffix = if only_declaration { ";" } else { " {" };

        try!(writeln!(w));
        if !in_trait || only_declaration {
            try!(cfg_deprecated(w, env, analysis.deprecated_version, commented, indent));
        }

        try!(writeln!(w, "{}{}#[cfg(feature = \"futures\")]", tabs(indent), comment_prefix));
        try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
        try!(version_condition(
            w,
            env,
            analysis.version,
            commented,
            indent,
        ));
        try!(not_version_condition(
            w,
            analysis.not_version,
            commented,
            indent,
        ));
        try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
        try!(writeln!(
            w,
            "{}{}{}{}{}",
            tabs(indent),
            comment_prefix,
            pub_prefix,
            declaration,
            suffix
        ));

        if !only_declaration {
            let body = body_chunk_futures(env, analysis).unwrap();
            for s in body.lines() {
                if !s.is_empty() {
                    try!(writeln!(w, "{}{}{}", tabs(indent+1), comment_prefix, s));
                } else {
                    try!(writeln!(w));
                }
            }
            try!(writeln!(w, "{}{}}}", tabs(indent), comment_prefix));
        }
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else if analysis.ret.bool_return_is_error.is_some() {
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            " -> Result<(), error::BoolError>".into()
        } else {
            " -> Result<(), glib::error::BoolError>".into()
        }
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let bounds = bounds(&analysis.bounds, &[], false);

    for (pos, par) in analysis.parameters.rust_parameters.iter().enumerate() {
        if pos > 0 {
            param_str.push_str(", ")
        }
        let c_par = &analysis.parameters.c_parameters[par.ind_c];
        let s = c_par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    format!(
        "fn {}{}({}){}",
        analysis.name,
        bounds,
        param_str,
        return_str
    )
}

pub fn declaration_futures(env: &Env, analysis: &analysis::functions::Info) -> String {
    let async_future = analysis.async_future.as_ref().unwrap();

    let return_str = if async_future.is_method {
        format!(" -> Box_<futures_core::Future<Item = (Self, {}), Error = (Self, {})>>", async_future.success_parameters, async_future.error_parameters)
    } else {
        format!(" -> Box_<futures_core::Future<Item = {}, Error = {}>>", async_future.success_parameters, async_future.error_parameters)
    };

    let mut param_str = String::with_capacity(100);

    let mut skipped = 0;
    let mut skipped_bounds = vec![];
    for (pos, par) in analysis.parameters.rust_parameters.iter().enumerate() {
        let c_par = &analysis.parameters.c_parameters[par.ind_c];

        if c_par.name == "callback" || c_par.name == "cancellable" {
            skipped += 1;
            if let Some((t, _)) = analysis.bounds.get_parameter_alias_info(&c_par.name) {
                skipped_bounds.push(t);
            }
            continue;
        }

        if pos - skipped > 0 {
            param_str.push_str(", ")
        }

        let s = c_par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    let bounds = bounds(&analysis.bounds, skipped_bounds.as_ref(), true);

    format!(
        "fn {}{}({}){}",
        async_future.name,
        bounds,
        param_str,
        return_str
    )
}

pub fn bounds(bounds: &Bounds, skip: &[char], async: bool) -> String {
    use analysis::bounds::BoundType::*;
    if bounds.is_empty() {
        return String::new();
    }

    let skip_lifetimes = bounds.iter()
        .filter(|bound| skip.contains(&bound.alias))
        .filter_map(|bound| match bound.bound_type {
            IsA(Some(lifetime)) |
            AsRef(Some(lifetime)) |
            Into(Some(lifetime), _) => Some(lifetime),
            _ => None,
        })
        .collect::<Vec<_>>();

    let strs: Vec<String> = bounds
        .iter_lifetimes()
        .filter(|s| !skip_lifetimes.contains(s))
        .map(|s| format!("'{}", s))
        .chain(bounds.iter().filter(|bound| !skip.contains(&bound.alias)).map(|bound| match bound.bound_type {
            NoWrapper => {
                format!("{}: {}", bound.alias, bound.type_str)
            }
            IsA(Some(lifetime)) => {
                format!("{}: IsA<{}> + {}", bound.alias, bound.type_str, if async { "Clone + 'static".into() } else { format!("'{}", lifetime) })
            }
            IsA(None) => format!("{}: IsA<{}>{}", bound.alias, bound.type_str, if async { " + Clone + 'static" } else { "" }),
            // This case should normally never happened
            AsRef(Some(lifetime)) => {
                format!("{}: AsRef<{}> + '{}", bound.alias, bound.type_str, lifetime)
            }
            AsRef(None) => format!("{}: AsRef<{}>", bound.alias, bound.type_str),
            Into(Some(l), _) => {
                format!("{}: Into<Option<&'{} {}>>", bound.alias, l, bound.type_str)
            }
            Into(None, _) => format!("{}: Into<Option<{}>>", bound.alias, bound.type_str),
        }))
        .collect();

    if strs.is_empty() {
        String::new()
    } else {
        format!("<{}>", strs.join(", "))
    }
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info) -> Chunk {
    if analysis.visibility == Visibility::Comment {
        return ffi_function_todo(&analysis.glib_name);
    }

    let outs_as_return = !analysis.outs.is_empty();

    let mut builder = function_body_chunk::Builder::new();
    builder
        .glib_name(&analysis.glib_name)
        .assertion(analysis.assertion)
        .ret(&analysis.ret)
        .transformations(&analysis.parameters.transformations)
        .outs_mode(analysis.outs.mode);

    if analysis.async {
        if let Some(ref trampoline) = analysis.trampoline {
            builder.async_trampoline(trampoline);
        } else {
            warn!("Async function {} has no associated _finish function", analysis.name);
        }
    }

    for par in &analysis.parameters.c_parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name == par.name) {
            builder.out_parameter(env, par);
        } else {
            builder.parameter();
        }
    }

    builder.generate(env)
}

pub fn body_chunk_futures(env: &Env, analysis: &analysis::functions::Info) -> StdResult<String, fmt::Error> {
    use std::fmt::Write;
    use analysis::bounds::BoundType;
    use analysis::ref_mode::RefMode;

    let async_future = analysis.async_future.as_ref().unwrap();

    let mut body = String::new();

    if env.config.library_name != "Gio" {
        try!(writeln!(body, "use gio::GioFuture;"));
    } else {
        try!(writeln!(body, "use GioFuture;"));
    }
    try!(writeln!(body, "use send_cell::SendCell;"));
    try!(writeln!(body));

    let skip = if async_future.is_method { 1 } else { 0 };

    // Skip the instance parameter
    for par in analysis.parameters.rust_parameters.iter().skip(skip) {
        if par.name == "cancellable" || par.name == "callback" {
            continue;
        }

        let c_par = &analysis.parameters.c_parameters[par.ind_c];

        let bounds = analysis.bounds.get_parameter_alias_info(&par.name);
        let is_into = if let Some((_, BoundType::Into(..))) = bounds { true } else { false };

        let type_ = env.type_(par.typ);
        let is_str = if let library::Type::Fundamental(library::Fundamental::Utf8) = *type_ { true } else { false };

        if is_into {
            try!(writeln!(body, "let {} = {}.into();", par.name, par.name));
            if is_str || c_par.nullable.0 {
                try!(writeln!(body, "let {} = {}.map(ToOwned::to_owned);", par.name, par.name));
            }
        } else if is_str {
            try!(writeln!(body, "let {} = String::from({});", par.name, par.name));
        } else if c_par.ref_mode != RefMode::None {
            try!(writeln!(body, "let {} = {}.clone();", par.name, par.name));
        }
    }

    if async_future.is_method {
        try!(writeln!(body, "GioFuture::new(self, move |obj, send| {{"));
    } else {
        try!(writeln!(body, "GioFuture::new(&(), move |_obj, send| {{"));
    }

    if env.config.library_name != "Gio" {
        try!(writeln!(body, "    let cancellable = gio::Cancellable::new();"));
    } else {
        try!(writeln!(body, "    let cancellable = Cancellable::new();"));
    }
    try!(writeln!(body, "    let send = SendCell::new(send);"));

    if async_future.is_method {
        try!(writeln!(body, "    let obj_clone = SendCell::new(obj.clone());"));
        try!(writeln!(body, "    obj.{}(", analysis.name));
    } else if analysis.type_name.is_ok() {
        try!(writeln!(body, "    Self::{}(", analysis.name));
    } else {
        try!(writeln!(body, "    {}(", analysis.name));
    }

    // Skip the instance parameter
    for par in analysis.parameters.rust_parameters.iter().skip(skip) {
        if par.name == "cancellable" {
            try!(writeln!(body, "         Some(&cancellable),"));
        } else if par.name == "callback" {
            continue;
        } else {
            let c_par = &analysis.parameters.c_parameters[par.ind_c];

            let bounds = analysis.bounds.get_parameter_alias_info(&par.name);
            let is_into = if let Some((_, BoundType::Into(..))) = bounds { true } else { false };

            if is_into {
                try!(writeln!(body, "         {}.as_ref().map(::std::borrow::Borrow::borrow),", par.name));
            } else if c_par.ref_mode != RefMode::None {
                try!(writeln!(body, "         &{},", par.name));
            } else {
                try!(writeln!(body, "         {},", par.name));
            }
        }
    }

    try!(writeln!(body, "         move |res| {{"));
    if async_future.is_method {
        try!(writeln!(body, "             let obj = obj_clone.into_inner();"));
        try!(writeln!(body, "             let res = res.map(|v| (obj.clone(), v)).map_err(|v| (obj.clone(), v));"));
    }
    try!(writeln!(body, "             let _ = send.into_inner().send(res);"));
    try!(writeln!(body, "         }},"));
    try!(writeln!(body, "    );"));
    try!(writeln!(body));
    try!(writeln!(body, "    cancellable"));
    try!(writeln!(body, "}})"));

    Ok(body)
}
<commit_msg>Move from send-cell to fragile<commit_after>use std::io::{Result, Write};

use library;
use analysis;
use analysis::bounds::Bounds;
use analysis::functions::Visibility;
use analysis::namespaces;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body_chunk;
use super::general::{
    cfg_condition, cfg_deprecated, doc_hidden, not_version_condition, version_condition,
};
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use writer::primitives::tabs;
use writer::ToCode;

use std::result::Result as StdResult;
use std::fmt;

pub fn generate(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::functions::Info,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    if analysis.is_async_finish(env) {
        return Ok(());
    }

    let mut commented = false;
    let mut comment_prefix = "";
    let mut pub_prefix = if in_trait { "" } else { "pub " };

    match analysis.visibility {
        Visibility::Public => {}
        Visibility::Comment => {
            commented = true;
            comment_prefix = "//";
        }
        Visibility::Private => if in_trait {
            warn!(
                "Generating trait method for private function {}",
                analysis.glib_name
            );
        } else {
            pub_prefix = "";
        },
        Visibility::Hidden => return Ok(()),
    }
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(writeln!(w));
    if !in_trait || only_declaration {
        try!(cfg_deprecated(w, env, analysis.deprecated_version, commented, indent));
    }
    try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
    try!(version_condition(
        w,
        env,
        analysis.version,
        commented,
        indent,
    ));
    try!(not_version_condition(
        w,
        analysis.not_version,
        commented,
        indent,
    ));
    try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
    try!(writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        declaration,
        suffix
    ));

    if !only_declaration {
        let body = body_chunk(env, analysis).to_code(env);
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
    }

    if analysis.async_future.is_some() {
        let declaration = declaration_futures(env, analysis);
        let suffix = if only_declaration { ";" } else { " {" };

        try!(writeln!(w));
        if !in_trait || only_declaration {
            try!(cfg_deprecated(w, env, analysis.deprecated_version, commented, indent));
        }

        try!(writeln!(w, "{}{}#[cfg(feature = \"futures\")]", tabs(indent), comment_prefix));
        try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
        try!(version_condition(
            w,
            env,
            analysis.version,
            commented,
            indent,
        ));
        try!(not_version_condition(
            w,
            analysis.not_version,
            commented,
            indent,
        ));
        try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
        try!(writeln!(
            w,
            "{}{}{}{}{}",
            tabs(indent),
            comment_prefix,
            pub_prefix,
            declaration,
            suffix
        ));

        if !only_declaration {
            let body = body_chunk_futures(env, analysis).unwrap();
            for s in body.lines() {
                if !s.is_empty() {
                    try!(writeln!(w, "{}{}{}", tabs(indent+1), comment_prefix, s));
                } else {
                    try!(writeln!(w));
                }
            }
            try!(writeln!(w, "{}{}}}", tabs(indent), comment_prefix));
        }
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else if analysis.ret.bool_return_is_error.is_some() {
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            " -> Result<(), error::BoolError>".into()
        } else {
            " -> Result<(), glib::error::BoolError>".into()
        }
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let bounds = bounds(&analysis.bounds, &[], false);

    for (pos, par) in analysis.parameters.rust_parameters.iter().enumerate() {
        if pos > 0 {
            param_str.push_str(", ")
        }
        let c_par = &analysis.parameters.c_parameters[par.ind_c];
        let s = c_par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    format!(
        "fn {}{}({}){}",
        analysis.name,
        bounds,
        param_str,
        return_str
    )
}

pub fn declaration_futures(env: &Env, analysis: &analysis::functions::Info) -> String {
    let async_future = analysis.async_future.as_ref().unwrap();

    let return_str = if async_future.is_method {
        format!(" -> Box_<futures_core::Future<Item = (Self, {}), Error = (Self, {})>>", async_future.success_parameters, async_future.error_parameters)
    } else {
        format!(" -> Box_<futures_core::Future<Item = {}, Error = {}>>", async_future.success_parameters, async_future.error_parameters)
    };

    let mut param_str = String::with_capacity(100);

    let mut skipped = 0;
    let mut skipped_bounds = vec![];
    for (pos, par) in analysis.parameters.rust_parameters.iter().enumerate() {
        let c_par = &analysis.parameters.c_parameters[par.ind_c];

        if c_par.name == "callback" || c_par.name == "cancellable" {
            skipped += 1;
            if let Some((t, _)) = analysis.bounds.get_parameter_alias_info(&c_par.name) {
                skipped_bounds.push(t);
            }
            continue;
        }

        if pos - skipped > 0 {
            param_str.push_str(", ")
        }

        let s = c_par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    let bounds = bounds(&analysis.bounds, skipped_bounds.as_ref(), true);

    format!(
        "fn {}{}({}){}",
        async_future.name,
        bounds,
        param_str,
        return_str
    )
}

pub fn bounds(bounds: &Bounds, skip: &[char], async: bool) -> String {
    use analysis::bounds::BoundType::*;
    if bounds.is_empty() {
        return String::new();
    }

    let skip_lifetimes = bounds.iter()
        .filter(|bound| skip.contains(&bound.alias))
        .filter_map(|bound| match bound.bound_type {
            IsA(Some(lifetime)) |
            AsRef(Some(lifetime)) |
            Into(Some(lifetime), _) => Some(lifetime),
            _ => None,
        })
        .collect::<Vec<_>>();

    let strs: Vec<String> = bounds
        .iter_lifetimes()
        .filter(|s| !skip_lifetimes.contains(s))
        .map(|s| format!("'{}", s))
        .chain(bounds.iter().filter(|bound| !skip.contains(&bound.alias)).map(|bound| match bound.bound_type {
            NoWrapper => {
                format!("{}: {}", bound.alias, bound.type_str)
            }
            IsA(Some(lifetime)) => {
                format!("{}: IsA<{}> + {}", bound.alias, bound.type_str, if async { "Clone + 'static".into() } else { format!("'{}", lifetime) })
            }
            IsA(None) => format!("{}: IsA<{}>{}", bound.alias, bound.type_str, if async { " + Clone + 'static" } else { "" }),
            // This case should normally never happened
            AsRef(Some(lifetime)) => {
                format!("{}: AsRef<{}> + '{}", bound.alias, bound.type_str, lifetime)
            }
            AsRef(None) => format!("{}: AsRef<{}>", bound.alias, bound.type_str),
            Into(Some(l), _) => {
                format!("{}: Into<Option<&'{} {}>>", bound.alias, l, bound.type_str)
            }
            Into(None, _) => format!("{}: Into<Option<{}>>", bound.alias, bound.type_str),
        }))
        .collect();

    if strs.is_empty() {
        String::new()
    } else {
        format!("<{}>", strs.join(", "))
    }
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info) -> Chunk {
    if analysis.visibility == Visibility::Comment {
        return ffi_function_todo(&analysis.glib_name);
    }

    let outs_as_return = !analysis.outs.is_empty();

    let mut builder = function_body_chunk::Builder::new();
    builder
        .glib_name(&analysis.glib_name)
        .assertion(analysis.assertion)
        .ret(&analysis.ret)
        .transformations(&analysis.parameters.transformations)
        .outs_mode(analysis.outs.mode);

    if analysis.async {
        if let Some(ref trampoline) = analysis.trampoline {
            builder.async_trampoline(trampoline);
        } else {
            warn!("Async function {} has no associated _finish function", analysis.name);
        }
    }

    for par in &analysis.parameters.c_parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name == par.name) {
            builder.out_parameter(env, par);
        } else {
            builder.parameter();
        }
    }

    builder.generate(env)
}

pub fn body_chunk_futures(env: &Env, analysis: &analysis::functions::Info) -> StdResult<String, fmt::Error> {
    use std::fmt::Write;
    use analysis::bounds::BoundType;
    use analysis::ref_mode::RefMode;

    let async_future = analysis.async_future.as_ref().unwrap();

    let mut body = String::new();

    if env.config.library_name != "Gio" {
        try!(writeln!(body, "use gio::GioFuture;"));
    } else {
        try!(writeln!(body, "use GioFuture;"));
    }
    try!(writeln!(body, "use fragile::Fragile;"));
    try!(writeln!(body));

    let skip = if async_future.is_method { 1 } else { 0 };

    // Skip the instance parameter
    for par in analysis.parameters.rust_parameters.iter().skip(skip) {
        if par.name == "cancellable" || par.name == "callback" {
            continue;
        }

        let c_par = &analysis.parameters.c_parameters[par.ind_c];

        let bounds = analysis.bounds.get_parameter_alias_info(&par.name);
        let is_into = if let Some((_, BoundType::Into(..))) = bounds { true } else { false };

        let type_ = env.type_(par.typ);
        let is_str = if let library::Type::Fundamental(library::Fundamental::Utf8) = *type_ { true } else { false };

        if is_into {
            try!(writeln!(body, "let {} = {}.into();", par.name, par.name));
            if is_str || c_par.nullable.0 {
                try!(writeln!(body, "let {} = {}.map(ToOwned::to_owned);", par.name, par.name));
            }
        } else if is_str {
            try!(writeln!(body, "let {} = String::from({});", par.name, par.name));
        } else if c_par.ref_mode != RefMode::None {
            try!(writeln!(body, "let {} = {}.clone();", par.name, par.name));
        }
    }

    if async_future.is_method {
        try!(writeln!(body, "GioFuture::new(self, move |obj, send| {{"));
    } else {
        try!(writeln!(body, "GioFuture::new(&(), move |_obj, send| {{"));
    }

    if env.config.library_name != "Gio" {
        try!(writeln!(body, "    let cancellable = gio::Cancellable::new();"));
    } else {
        try!(writeln!(body, "    let cancellable = Cancellable::new();"));
    }
    try!(writeln!(body, "    let send = Fragile::new(send);"));

    if async_future.is_method {
        try!(writeln!(body, "    let obj_clone = Fragile::new(obj.clone());"));
        try!(writeln!(body, "    obj.{}(", analysis.name));
    } else if analysis.type_name.is_ok() {
        try!(writeln!(body, "    Self::{}(", analysis.name));
    } else {
        try!(writeln!(body, "    {}(", analysis.name));
    }

    // Skip the instance parameter
    for par in analysis.parameters.rust_parameters.iter().skip(skip) {
        if par.name == "cancellable" {
            try!(writeln!(body, "         Some(&cancellable),"));
        } else if par.name == "callback" {
            continue;
        } else {
            let c_par = &analysis.parameters.c_parameters[par.ind_c];

            let bounds = analysis.bounds.get_parameter_alias_info(&par.name);
            let is_into = if let Some((_, BoundType::Into(..))) = bounds { true } else { false };

            if is_into {
                try!(writeln!(body, "         {}.as_ref().map(::std::borrow::Borrow::borrow),", par.name));
            } else if c_par.ref_mode != RefMode::None {
                try!(writeln!(body, "         &{},", par.name));
            } else {
                try!(writeln!(body, "         {},", par.name));
            }
        }
    }

    try!(writeln!(body, "         move |res| {{"));
    if async_future.is_method {
        try!(writeln!(body, "             let obj = obj_clone.into_inner();"));
        try!(writeln!(body, "             let res = res.map(|v| (obj.clone(), v)).map_err(|v| (obj.clone(), v));"));
    }
    try!(writeln!(body, "             let _ = send.into_inner().send(res);"));
    try!(writeln!(body, "         }},"));
    try!(writeln!(body, "    );"));
    try!(writeln!(body));
    try!(writeln!(body, "    cancellable"));
    try!(writeln!(body, "}})"));

    Ok(body)
}
<|endoftext|>


<commit_before>use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));
    println!("Generating file {:?}", path);

    save_to_file(path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_enums(w, &ns.name, &prepare(ns)));
    try!(generate_bitfields(w, &ns.name, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &prepare_records(ns)));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn prepare_records(ns: &library::Namespace) -> Vec<&library::Record> {
    let mut vec = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(rec) = typ.maybe_ref_as::<library::Record>() {
            // We don't want the FooBarPrivate and similar records where FooBar is a type
            if ["Private", "Class", "Iface", "Interface"].iter()
                    .filter_map(|s| strip_suffix(&rec.name, s))
                    .any(|s| ns.index.get(s).is_some()) {
                continue;
            }
            vec.push(rec);
        }
    }
    vec.sort();
    vec
}

fn generate_bitfields<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: i32 {{", tabs(1), item.name));
        for member in &item.members {
            try!(writeln!(w, "{}const {} = {},",
                          tabs(2), strip_prefix(ns_name, &member.c_identifier), member.value));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.name));
        for member in &item.members {
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};",
                          strip_prefix(ns_name, &member.c_identifier),
                          item.name, &prepare_enum_member_name(&member.name)));
        }
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.glib_type_name));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.glib_type_name));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut has_union = false;
        for field in &record.fields {
            if has_union {
                warn!("A record has fields after the union placeholder");
                lines.push(format!("{}// ignoring the fields after the union", tabs(1)));
                break;
            }
            if env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some() {
                lines.push(format!("{}_union_placeholder: (),", tabs(1)));
                has_union = true;
            }
            else if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{} {}: {},", tabs(1), "pub", name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{} {}: fn{},", tabs(1), "pub", name, sig));
                    commented |= com;
                }
                else {
                    lines.push(format!("{}{} {}: [{:?}],", tabs(1), "pub", name, field.typ));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.glib_type_name));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.glib_type_name));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<commit_msg>sys: Discard duplicate enum members, use typedef i32 for single-variant enums<commit_after>use std::collections::HashMap;
use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));
    println!("Generating file {:?}", path);

    save_to_file(path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_enums(w, &ns.name, &prepare(ns)));
    try!(generate_bitfields(w, &ns.name, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &prepare_records(ns)));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn prepare_records(ns: &library::Namespace) -> Vec<&library::Record> {
    let mut vec = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(rec) = typ.maybe_ref_as::<library::Record>() {
            // We don't want the FooBarPrivate and similar records where FooBar is a type
            if ["Private", "Class", "Iface", "Interface"].iter()
                    .filter_map(|s| strip_suffix(&rec.name, s))
                    .any(|s| ns.index.get(s).is_some()) {
                continue;
            }
            vec.push(rec);
        }
    }
    vec.sort();
    vec
}

fn generate_bitfields<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: i32 {{", tabs(1), item.name));
        for member in &item.members {
            try!(writeln!(w, "{}const {} = {},",
                          tabs(2), strip_prefix(ns_name, &member.c_identifier), member.value));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if item.members.len() == 1 {
            try!(writeln!(w, "pub type {} = i32;", item.name));
            try!(writeln!(w, "pub const {}: {} = {};",
                          item.members[0].c_identifier, item.name, item.members[0].value));
            try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
            try!(writeln!(w, ""));
            continue;
        }

        let mut vals = HashMap::new();
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.name));
        for member in &item.members {
            if vals.get(&member.value).is_some() {
                continue;
            }
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
            vals.insert(member.value.clone(), member.name.clone());
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};",
                          strip_prefix(ns_name, &member.c_identifier),
                          item.name, &prepare_enum_member_name(vals.get(&member.value).unwrap())));
        }
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.glib_type_name));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.glib_type_name));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut has_union = false;
        for field in &record.fields {
            if has_union {
                warn!("A record has fields after the union placeholder");
                lines.push(format!("{}// ignoring the fields after the union", tabs(1)));
                break;
            }
            if env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some() {
                lines.push(format!("{}_union_placeholder: (),", tabs(1)));
                has_union = true;
            }
            else if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{} {}: {},", tabs(1), "pub", name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{} {}: fn{},", tabs(1), "pub", name, sig));
                    commented |= com;
                }
                else {
                    lines.push(format!("{}{} {}: [{:?}],", tabs(1), "pub", name, field.typ));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.glib_type_name));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.glib_type_name));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use protobuf::rustproto;
use protobuf::descriptor::FieldOptions;
use protobuf::descriptor::MessageOptions;
use protobuf::descriptor::FileOptions;

/// Specifies style of generated code.
/// Generated files can be customized using this proto
/// or using `rustproto.proto` options.
#[derive(Default, Debug, Clone)]
pub struct Customize {
    /// Make oneof enum public.
    pub expose_oneof: Option<bool>,
    /// When true all fields are public, and accessors are not generated
    pub expose_fields: Option<bool>,
    /// When false, `get_`, `set_`, `mut_` etc. accessors are not generated
    pub generate_accessors: Option<bool>,
    /// When false, `get_` is not generated even if `syntax = "proto2"`
    pub generate_getter: Option<bool>,
    /// Use `bytes::Bytes` for `bytes` fields
    pub carllerche_bytes_for_bytes: Option<bool>,
    /// Use `bytes::Bytes` for `string` fields
    pub carllerche_bytes_for_string: Option<bool>,
    /// Use `std::Vec` to store repeated messages fields
    pub repeated_field_vec: Option<bool>,
}

impl Customize {
    /// Update fields of self with fields defined in other customize
    pub fn update_with(&mut self, that: &Customize) {
        if let Some(v) = that.expose_oneof {
            self.expose_oneof = Some(v);
        }
        if let Some(v) = that.expose_fields {
            self.expose_fields = Some(v);
        }
        if let Some(v) = that.generate_accessors {
            self.generate_accessors = Some(v);
        }
        if let Some(v) = that.generate_getter {
            self.generate_getter = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_bytes {
            self.carllerche_bytes_for_bytes = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_string {
            self.carllerche_bytes_for_string = Some(v);
        }
        if let Some(v) = that.repeated_field_vec {
            self.repeated_field_vec = Some(v);
        }
    }

    /// Update unset fields of self with fields from other customize
    pub fn set_defaults_from(&mut self, other: &Customize) {
        let mut tmp = other.clone();
        tmp.update_with(self);
        *self = tmp;
    }
}

pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof.get(source);
    let expose_fields = rustproto::exts::expose_fields.get(source);
    let generate_accessors = rustproto::exts::generate_accessors.get(source);
    let generate_getter = rustproto::exts::generate_getter.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
    }
}

pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
    let expose_oneof = None;
    let expose_fields = rustproto::exts::expose_fields_field.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_field.get(source);
    let generate_getter = rustproto::exts::generate_getter_field.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_field.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_field.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_field.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
    }
}

pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof_all.get(source);
    let expose_fields = rustproto::exts::expose_fields_all.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_all.get(source);
    let generate_getter = rustproto::exts::generate_getter_all.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_all.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_all.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_all.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
    }
}
<commit_msg>Make sure `Customize` is always used with `..Default::default()`<commit_after>use protobuf::rustproto;
use protobuf::descriptor::FieldOptions;
use protobuf::descriptor::MessageOptions;
use protobuf::descriptor::FileOptions;

/// Specifies style of generated code.
/// Generated files can be customized using this proto
/// or using `rustproto.proto` options.
#[derive(Default, Debug, Clone)]
pub struct Customize {
    /// Make oneof enum public.
    pub expose_oneof: Option<bool>,
    /// When true all fields are public, and accessors are not generated
    pub expose_fields: Option<bool>,
    /// When false, `get_`, `set_`, `mut_` etc. accessors are not generated
    pub generate_accessors: Option<bool>,
    /// When false, `get_` is not generated even if `syntax = "proto2"`
    pub generate_getter: Option<bool>,
    /// Use `bytes::Bytes` for `bytes` fields
    pub carllerche_bytes_for_bytes: Option<bool>,
    /// Use `bytes::Bytes` for `string` fields
    pub carllerche_bytes_for_string: Option<bool>,
    /// Use `std::Vec` to store repeated messages fields
    pub repeated_field_vec: Option<bool>,
    /// Make sure `Customize` is always used with `..Default::default()`
    /// for future compatibility.
    _future_options: (),
}

impl Customize {
    /// Update fields of self with fields defined in other customize
    pub fn update_with(&mut self, that: &Customize) {
        if let Some(v) = that.expose_oneof {
            self.expose_oneof = Some(v);
        }
        if let Some(v) = that.expose_fields {
            self.expose_fields = Some(v);
        }
        if let Some(v) = that.generate_accessors {
            self.generate_accessors = Some(v);
        }
        if let Some(v) = that.generate_getter {
            self.generate_getter = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_bytes {
            self.carllerche_bytes_for_bytes = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_string {
            self.carllerche_bytes_for_string = Some(v);
        }
        if let Some(v) = that.repeated_field_vec {
            self.repeated_field_vec = Some(v);
        }
    }

    /// Update unset fields of self with fields from other customize
    pub fn set_defaults_from(&mut self, other: &Customize) {
        let mut tmp = other.clone();
        tmp.update_with(self);
        *self = tmp;
    }
}

pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof.get(source);
    let expose_fields = rustproto::exts::expose_fields.get(source);
    let generate_accessors = rustproto::exts::generate_accessors.get(source);
    let generate_getter = rustproto::exts::generate_getter.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
    let expose_oneof = None;
    let expose_fields = rustproto::exts::expose_fields_field.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_field.get(source);
    let generate_getter = rustproto::exts::generate_getter_field.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_field.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_field.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_field.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof_all.get(source);
    let expose_fields = rustproto::exts::expose_fields_all.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_all.get(source);
    let generate_getter = rustproto::exts::generate_getter_all.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_all.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_all.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_all.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        _future_options: (),
    }
}
<|endoftext|>