<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;
use std::cell::RefCell;
use std::fmt::Display;
use std::path::PathBuf;
use std::rc::Rc;
use std::slice::Iter;
use std::string::String;
use std::sync::Arc;

use dbus;
use dbus::Connection;
use dbus::Message;
use dbus::MessageItem;
use dbus::NameFlag;

use dbus::tree::Factory;
use dbus::tree::MethodErr;
use dbus::tree::MethodFn;
use dbus::tree::MethodResult;
use dbus::tree::Property;
use dbus::tree::Tree;

use dbus_consts::*;

use engine::Engine;
use types::{StratisResult, StratisError};

#[derive(Debug, Clone)]
pub struct DbusContext<'a> {
    name_prop: Arc<Property<MethodFn<'a>>>,
    pub remaining_prop: Arc<Property<MethodFn<'a>>>,
    pub total_prop: Arc<Property<MethodFn<'a>>>,
    pub status_prop: Arc<Property<MethodFn<'a>>>,
    pub running_status_prop: Arc<Property<MethodFn<'a>>>,
    pub block_devices_prop: Arc<Property<MethodFn<'a>>>,
}

impl<'a> DbusContext<'a> {
    pub fn update_one(prop: &Arc<Property<MethodFn<'a>>>, m: MessageItem) -> StratisResult<()> {
        match prop.set_value(m) {
            Ok(_) => Ok(()), // TODO: return signals
            Err(()) => Err(StratisError::Dbus(dbus::Error::new_custom(
                "UpdateError", "Could not update property with value"))),
        }
    }
}

fn listpools(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    Ok(vec![m.method_return()])
}

fn createpool(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    let raid_level: u16 = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner()
                .map_err(|_| MethodErr::invalid_arg(&i))
        }));

    let devs = match try!(items.pop().ok_or_else(MethodErr::no_arg)) {
        MessageItem::Array(x, _) => x,
        x => return Err(MethodErr::invalid_arg(&x)),
    };

    // Get the name of the pool from the parameters
    let name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    let blockdevs = devs.into_iter()
        .map(|x| PathBuf::from(x.inner::<&str>().unwrap()))
        .collect::<Vec<_>>();

    let result = engine.borrow().create_pool(&name, &blockdevs, raid_level);

    Ok(vec![m.method_return().append3("/dbus/newpool/path", 0, "Ok")])
}

fn destroypool(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    // Get the name of the pool from the parameters
    let name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    let result = engine.borrow().destroy_pool(&name);

    Ok(vec![m.method_return().append3("/dbus/pool/path", 0, "Ok")])
}

fn getpoolobjectpath(m: &Message) -> MethodResult {

    Ok(vec![m.method_return().append3("/dbus/pool/path", 0, "Ok")])
}

fn getvolumeobjectpath(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/volume/path", 0, "Ok")])
}

fn getdevobjectpath(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/dev/path", 0, "Ok")])
}

fn getcacheobjectpath(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn getlistitems<T: HasCodes + Display>(m: &Message, items: &Iter<T>) -> MethodResult {

    let mut msg_vec = Vec::new();
    for item in items.as_slice() {
        let entry = vec![MessageItem::Str(format!("{}", item)),
                         MessageItem::UInt16(item.get_error_int()),
                         MessageItem::Str(String::from(item.get_error_string()))];
        msg_vec.push(MessageItem::Struct(entry));
    }

    let item_array = MessageItem::Array(msg_vec, Cow::Borrowed("(sqs)"));
    Ok(vec![m.method_return().append1(item_array)])
}

fn geterrorcodes(m: &Message) -> MethodResult {
    getlistitems(m, &StratisErrorEnum::iterator())
}

fn getraidlevels(m: &Message) -> MethodResult {
    getlistitems(m, &StratisRaidType::iterator())
}

fn getdevtypes(m: &Message) -> MethodResult {
    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    let _name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    println!("method called");

    Ok(vec![m.method_return()])
}

pub fn get_base_tree<'a>(c: &'a Connection,
                         engine: Rc<RefCell<Engine>>)
                         -> StratisResult<Tree<MethodFn<'a>>> {
    c.register_name(STRATIS_BASE_SERVICE, NameFlag::ReplaceExisting as u32).unwrap();

    let f = Factory::new_fn();

    let base_tree = f.tree();

    let engine_clone = engine.clone();

    let createpool_method = f.method(CREATE_POOL, move |m, _, _| createpool(m, &engine_clone))
        .in_arg(("pool_name", "s"))
        .in_arg(("dev_list", "as"))
        .in_arg(("raid_type", "q"))
        .out_arg(("object_path", "s"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let engine_clone = engine.clone();

    let destroypool_method = f.method(DESTROY_POOL, move |m, _, _| destroypool(m, &engine_clone))
        .in_arg(("pool_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let engine_clone = engine.clone();

    let listpools_method = f.method(LIST_POOLS, move |m, _, _| listpools(m, &engine_clone))
        .out_arg(("pool_names", "as"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let getpoolobjectpath_method =
        f.method(GET_POOL_OBJECT_PATH, move |m, _, _| getpoolobjectpath(m))
            .in_arg(("pool_name", "s"))
            .out_arg(("object_path", "o"))
            .out_arg(("return_code", "q"))
            .out_arg(("return_string", "s"));

    let getvolumeobjectpath_method = f.method(GET_VOLUME_OBJECT_PATH,
                move |m, _, _| getvolumeobjectpath(m))
        .in_arg(("pool_name", "s"))
        .in_arg(("volume_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let getdevobjectpath_method = f.method(GET_DEV_OBJECT_PATH, move |m, _, _| getdevobjectpath(m))
        .in_arg(("dev_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let getcacheobjectpath_method =
        f.method(GET_CACHE_OBJECT_PATH, move |m, _, _| getcacheobjectpath(m))
            .in_arg(("cache_dev_name", "s"))
            .out_arg(("object_path", "o"))
            .out_arg(("return_code", "q"))
            .out_arg(("return_string", "s"));

    let geterrorcodes_method = f.method(GET_ERROR_CODES, move |m, _, _| geterrorcodes(m))
        .out_arg(("error_codes", "a(sqs)"));

    let getraidlevels_method = f.method(GET_RAID_LEVELS, move |m, _, _| getraidlevels(m))
        .out_arg(("error_codes", "a(sqs)"));

    let getdevtypes_method = f.method(GET_DEV_TYPES, move |m, _, _| getdevtypes(m));

    let obj_path = f.object_path(STRATIS_BASE_PATH)
        .introspectable()
        .add(f.interface(STRATIS_MANAGER_INTERFACE)
            .add_m(listpools_method)
            .add_m(createpool_method)
            .add_m(destroypool_method)
            .add_m(getpoolobjectpath_method)
            .add_m(getvolumeobjectpath_method)
            .add_m(getdevobjectpath_method)
            .add_m(getcacheobjectpath_method)
            .add_m(geterrorcodes_method)
            .add_m(getraidlevels_method)
            .add_m(getdevtypes_method));

    let base_tree = base_tree.add(obj_path);
    try!(base_tree.set_registered(c, true));

    Ok(base_tree)
}
<commit_msg>change method names to use underscores<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;
use std::cell::RefCell;
use std::fmt::Display;
use std::path::PathBuf;
use std::rc::Rc;
use std::slice::Iter;
use std::string::String;
use std::sync::Arc;

use dbus;
use dbus::Connection;
use dbus::Message;
use dbus::MessageItem;
use dbus::NameFlag;

use dbus::tree::Factory;
use dbus::tree::MethodErr;
use dbus::tree::MethodFn;
use dbus::tree::MethodResult;
use dbus::tree::Property;
use dbus::tree::Tree;

use dbus_consts::*;

use engine::Engine;
use types::{StratisResult, StratisError};

#[derive(Debug, Clone)]
pub struct DbusContext<'a> {
    name_prop: Arc<Property<MethodFn<'a>>>,
    pub remaining_prop: Arc<Property<MethodFn<'a>>>,
    pub total_prop: Arc<Property<MethodFn<'a>>>,
    pub status_prop: Arc<Property<MethodFn<'a>>>,
    pub running_status_prop: Arc<Property<MethodFn<'a>>>,
    pub block_devices_prop: Arc<Property<MethodFn<'a>>>,
}

impl<'a> DbusContext<'a> {
    pub fn update_one(prop: &Arc<Property<MethodFn<'a>>>, m: MessageItem) -> StratisResult<()> {
        match prop.set_value(m) {
            Ok(_) => Ok(()), // TODO: return signals
            Err(()) => Err(StratisError::Dbus(dbus::Error::new_custom(
                "UpdateError", "Could not update property with value"))),
        }
    }
}

fn list_pools(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    Ok(vec![m.method_return()])
}

fn create_pool(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    let raid_level: u16 = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner()
                .map_err(|_| MethodErr::invalid_arg(&i))
        }));

    let devs = match try!(items.pop().ok_or_else(MethodErr::no_arg)) {
        MessageItem::Array(x, _) => x,
        x => return Err(MethodErr::invalid_arg(&x)),
    };

    // Get the name of the pool from the parameters
    let name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    let blockdevs = devs.into_iter()
        .map(|x| PathBuf::from(x.inner::<&str>().unwrap()))
        .collect::<Vec<_>>();

    let result = engine.borrow().create_pool(&name, &blockdevs, raid_level);

    Ok(vec![m.method_return().append3("/dbus/newpool/path", 0, "Ok")])
}

fn destroy_pool(m: &Message, engine: &Rc<RefCell<Engine>>) -> MethodResult {

    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    // Get the name of the pool from the parameters
    let name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    let result = engine.borrow().destroy_pool(&name);

    Ok(vec![m.method_return().append3("/dbus/pool/path", 0, "Ok")])
}

fn get_pool_object_path(m: &Message) -> MethodResult {

    Ok(vec![m.method_return().append3("/dbus/pool/path", 0, "Ok")])
}

fn get_volume_object_path(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/volume/path", 0, "Ok")])
}

fn get_dev_object_path(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/dev/path", 0, "Ok")])
}

fn get_cache_object_path(m: &Message) -> MethodResult {
    Ok(vec![m.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn get_list_items<T: HasCodes + Display>(m: &Message, items: &Iter<T>) -> MethodResult {

    let mut msg_vec = Vec::new();
    for item in items.as_slice() {
        let entry = vec![MessageItem::Str(format!("{}", item)),
                         MessageItem::UInt16(item.get_error_int()),
                         MessageItem::Str(String::from(item.get_error_string()))];
        msg_vec.push(MessageItem::Struct(entry));
    }

    let item_array = MessageItem::Array(msg_vec, Cow::Borrowed("(sqs)"));
    Ok(vec![m.method_return().append1(item_array)])
}

fn get_error_codes(m: &Message) -> MethodResult {
    get_list_items(m, &StratisErrorEnum::iterator())
}

fn get_raid_levels(m: &Message) -> MethodResult {
    get_list_items(m, &StratisRaidType::iterator())
}

fn get_dev_types(m: &Message) -> MethodResult {
    let mut items = m.get_items();
    if items.len() < 1 {
        return Err(MethodErr::no_arg());
    }

    let _name = try!(items.pop()
        .ok_or_else(MethodErr::no_arg)
        .and_then(|i| {
            i.inner::<&str>()
                .map_err(|_| MethodErr::invalid_arg(&i))
                .map(|i| i.to_owned())
        }));

    println!("method called");

    Ok(vec![m.method_return()])
}

pub fn get_base_tree<'a>(c: &'a Connection,
                         engine: Rc<RefCell<Engine>>)
                         -> StratisResult<Tree<MethodFn<'a>>> {
    c.register_name(STRATIS_BASE_SERVICE, NameFlag::ReplaceExisting as u32).unwrap();

    let f = Factory::new_fn();

    let base_tree = f.tree();

    let engine_clone = engine.clone();

    let createpool_method = f.method(CREATE_POOL, move |m, _, _| create_pool(m, &engine_clone))
        .in_arg(("pool_name", "s"))
        .in_arg(("dev_list", "as"))
        .in_arg(("raid_type", "q"))
        .out_arg(("object_path", "s"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let engine_clone = engine.clone();

    let destroypool_method = f.method(DESTROY_POOL, move |m, _, _| destroy_pool(m, &engine_clone))
        .in_arg(("pool_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let engine_clone = engine.clone();

    let listpools_method = f.method(LIST_POOLS, move |m, _, _| list_pools(m, &engine_clone))
        .out_arg(("pool_names", "as"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let getpoolobjectpath_method =
        f.method(GET_POOL_OBJECT_PATH, move |m, _, _| get_pool_object_path(m))
            .in_arg(("pool_name", "s"))
            .out_arg(("object_path", "o"))
            .out_arg(("return_code", "q"))
            .out_arg(("return_string", "s"));

    let getvolumeobjectpath_method = f.method(GET_VOLUME_OBJECT_PATH,
                move |m, _, _| get_volume_object_path(m))
        .in_arg(("pool_name", "s"))
        .in_arg(("volume_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let getdevobjectpath_method =
        f.method(GET_DEV_OBJECT_PATH, move |m, _, _| get_dev_object_path(m))
            .in_arg(("dev_name", "s"))
            .out_arg(("object_path", "o"))
            .out_arg(("return_code", "q"))
            .out_arg(("return_string", "s"));

    let getcacheobjectpath_method = f.method(GET_CACHE_OBJECT_PATH,
                move |m, _, _| get_cache_object_path(m))
        .in_arg(("cache_dev_name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let geterrorcodes_method = f.method(GET_ERROR_CODES, move |m, _, _| get_error_codes(m))
        .out_arg(("error_codes", "a(sqs)"));

    let getraidlevels_method = f.method(GET_RAID_LEVELS, move |m, _, _| get_raid_levels(m))
        .out_arg(("error_codes", "a(sqs)"));

    let getdevtypes_method = f.method(GET_DEV_TYPES, move |m, _, _| get_dev_types(m));

    let obj_path = f.object_path(STRATIS_BASE_PATH)
        .introspectable()
        .add(f.interface(STRATIS_MANAGER_INTERFACE)
            .add_m(listpools_method)
            .add_m(createpool_method)
            .add_m(destroypool_method)
            .add_m(getpoolobjectpath_method)
            .add_m(getvolumeobjectpath_method)
            .add_m(getdevobjectpath_method)
            .add_m(getcacheobjectpath_method)
            .add_m(geterrorcodes_method)
            .add_m(getraidlevels_method)
            .add_m(getdevtypes_method));

    let base_tree = base_tree.add(obj_path);
    try!(base_tree.set_registered(c, true));

    Ok(base_tree)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor_set::Layout;
use descriptor_set::LayoutPossibleSuperset;
use descriptor_set::PipelineLayout;
use shader::ComputeShaderEntryPoint;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

///
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Arc<PipelineLayout<Pl>>,
}

impl<Pl> ComputePipeline<Pl> {
    ///
    ///
    /// # Panic
    ///
    /// Panicks if the pipeline layout and/or shader don't belong to the device.
    pub fn new<Csl>(device: &Arc<Device>, pipeline_layout: &Arc<PipelineLayout<Pl>>,
                    shader: &ComputeShaderEntryPoint<Csl>)
                    -> Result<Arc<ComputePipeline<Pl>>, OomError>
        where Pl: LayoutPossibleSuperset<Csl>, Csl: Layout
    {
        let vk = device.pointers();

        // TODO: should be an error instead
        assert!(LayoutPossibleSuperset::is_superset_of(pipeline_layout.layout(), shader.layout()));

        let pipeline = unsafe {
            /*let spec_descriptors = specialization.descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len(),
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const S as *const _,
            };*/

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: //if mem::size_of_val(specialization) == 0 {
                    ptr::null()
                /*} else {
                    &specialization
                }*/,
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: pipeline_layout.internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout.clone(),
        }))
    }

    /// Returns the `PipelineLayout` used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Arc<PipelineLayout<Pl>> {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<commit_msg>Add ComputePipeline::device()<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor_set::Layout;
use descriptor_set::LayoutPossibleSuperset;
use descriptor_set::PipelineLayout;
use shader::ComputeShaderEntryPoint;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

///
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Arc<PipelineLayout<Pl>>,
}

impl<Pl> ComputePipeline<Pl> {
    ///
    ///
    /// # Panic
    ///
    /// Panicks if the pipeline layout and/or shader don't belong to the device.
    pub fn new<Csl>(device: &Arc<Device>, pipeline_layout: &Arc<PipelineLayout<Pl>>,
                    shader: &ComputeShaderEntryPoint<Csl>)
                    -> Result<Arc<ComputePipeline<Pl>>, OomError>
        where Pl: LayoutPossibleSuperset<Csl>, Csl: Layout
    {
        let vk = device.pointers();

        // TODO: should be an error instead
        assert!(LayoutPossibleSuperset::is_superset_of(pipeline_layout.layout(), shader.layout()));

        let pipeline = unsafe {
            /*let spec_descriptors = specialization.descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len(),
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const S as *const _,
            };*/

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: //if mem::size_of_val(specialization) == 0 {
                    ptr::null()
                /*} else {
                    &specialization
                }*/,
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: pipeline_layout.internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout.clone(),
        }))
    }

    /// Returns the `Device` this compute pipeline was created with.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the `PipelineLayout` used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Arc<PipelineLayout<Pl>> {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<|endoftext|>


<commit_before>extern crate dft;
use dft::{Operation, Plan, Transform, c64};
use std::iter::FromIterator;
use std::f64::consts::PI;

extern crate arrayfire as af;

use af::*;

fn main() {
    let size: usize = 32;
    let planf = Plan::new(dft::Operation::Forward, size);
    let plani = Plan::new(dft::Operation::Inverse, size);
    let mut a = Vec::from_iter((0..size).map(|idx| c64::new((idx + 1) as f64, 0.0)));
    let mut kernel = Vec::from_iter((0..size).map(|idx| {
        c64::new((2.0 * PI * 3.0 * (idx as f64) / (size as f64)).cos(),
                 (2.0 * PI * 3.0 * (idx as f64) / (size as f64)).sin())
    }));
    println!("a: {:?}, kernel: {:?}", a, kernel);

    // forward Fourier transform
    a.transform(&planf);

    // convolution with the kernel
    let mut b = Vec::from_iter((0..size).map(|i| a[i] * kernel[i]));

    println!("b before ifft : {:?}", b);

    // inverse Fourier transform
    b.transform(&plani);
    println!("b: {:?}", b);

    // expected cyclic shift:
    // a = [1, 2, 3, ...]
    // b = [4, 5, 6, ...]

    // play with ArrayFire
    // only CPU
    set_backend(Backend::AF_BACKEND_CPU);
    let mut int_values = Vec::from_iter((0..size).map(|idx| idx + 1));
    let cta_grid = Dim4::new(&[size as u64, 1, 1, 1]);
    let af = Array::new(cta_grid,
        &Vec::from_iter(int_values.iter().map (|&i| c64::new(i as f64, 0.0) ) ), Aftype::C64).unwrap();

    println!("the constructed array has {} elements", af.elements().unwrap());
    print(&af);

    let kernelf = Array::new(cta_grid, &kernel, Aftype::C64).unwrap();
    println!("kernelf:");
    print(&kernelf);

    let mut bf = fft_convolve1(&af, &kernelf, ConvMode::DEFAULT).unwrap();

    println!("ArrayFire convolved array:");
    print(&bf);

    let af_transformed = fft(&af, 1.0, size as i64).unwrap();
    let convolved1 = convolve1(&af_transformed, &kernelf, ConvMode::DEFAULT, ConvDomain::AUTO).unwrap();
    println!("convolved1:");
    print(&convolved1);

}
<commit_msg>use case for ArrayFire - produces identical shift.<commit_after>extern crate dft;
use dft::{Operation, Plan, Transform, c64};
use std::iter::FromIterator;
use std::f64::consts::PI;

extern crate arrayfire as af;

use af::*;

fn main() {
    let size: usize = 32;
    let planf = Plan::new(dft::Operation::Forward, size);
    let plani = Plan::new(dft::Operation::Inverse, size);
    let mut a = Vec::from_iter((0..size).map(|idx| c64::new((idx + 1) as f64, 0.0)));
    let mut kernel = Vec::from_iter((0..size).map(|idx| {
        c64::new((2.0 * PI * 3.0 * (idx as f64) / (size as f64)).cos(),
                 (2.0 * PI * 3.0 * (idx as f64) / (size as f64)).sin())
    }));
    println!("a: {:?}, kernel: {:?}", a, kernel);

    // forward Fourier transform
    a.transform(&planf);
    println!("a after fft: {:?}", a);

    // convolution with the kernel
    let mut b = Vec::from_iter((0..size).map(|i| a[i] * kernel[i]));

    println!("b before ifft : {:?}", b);

    // inverse Fourier transform
    b.transform(&plani);
    println!("b: {:?}", b);

    // expected cyclic shift:
    // a = [1, 2, 3, ...]
    // b = [4, 5, 6, ...]

    // the same with ArrayFire
    // only CPU
    set_backend(Backend::AF_BACKEND_CPU);
    let mut int_values = Vec::from_iter((0..size).map(|idx| idx + 1));
    let cta_grid = Dim4::new(&[size as u64, 1, 1, 1]);
    let af = Array::new(cta_grid,
        &Vec::from_iter(int_values.iter().map (|&i| c64::new(i as f64, 0.0) ) ), Aftype::C64).unwrap();

    println!("the constructed array has {} elements", af.elements().unwrap());
    print(&af);

    let kernelf = Array::new(cta_grid, &kernel, Aftype::C64).unwrap();
    println!("kernelf:");
    print(&kernelf);

    let isize = size as i64;
    let scale = 1.0f64 / (size as f64);
    let af_transformed = fft(&af, 1.0, isize).unwrap();
    println!("af_transformed:");
    print(&af_transformed);
    let convolved1 = &af_transformed * &kernelf;
    println!("convolved1:");
    print(&convolved1);
    let shifted = ifft(&convolved1, scale, isize).unwrap();
    println!("shifted:");
    print(&shifted);
}
<|endoftext|>


<commit_before>// This is a part of rust-encoding.
// Copyright (c) 2013, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

/*!
 * Character encoding support for Rust. It is based on [WHATWG Encoding
 * Standard](http://encoding.spec.whatwg.org/), and also provides an advanced interface for
 * error detection and recovery.
 */

#[link(name = "encoding",
       vers = "0.1.0",
       uuid = "05AC43C2-6959-409F-B95A-C58EBF217527",
       url = "https://github.com/lifthrasiir/rust-encoding/")];

#[comment = "Character encoding support for Rust"];
#[license = "MIT"];
#[crate_type = "lib"];

#[feature(globs, macro_rules)];

pub use self::types::*; // reexport

mod util;
#[cfg(test)] mod testutils;

pub mod types;

/// Indices used for character encoding implementation. Semi-internal.
pub mod index {
    pub mod ibm866;
    pub mod iso_8859_2;
    pub mod iso_8859_3;
    pub mod iso_8859_4;
    pub mod iso_8859_5;
    pub mod iso_8859_6;
    pub mod iso_8859_7;
    pub mod iso_8859_8;
    pub mod iso_8859_10;
    pub mod iso_8859_13;
    pub mod iso_8859_14;
    pub mod iso_8859_15;
    pub mod iso_8859_16;
    pub mod koi8_r;
    pub mod koi8_u;
    pub mod macintosh;
    pub mod windows_874;
    pub mod windows_1250;
    pub mod windows_1251;
    pub mod windows_1252;
    pub mod windows_1253;
    pub mod windows_1254;
    pub mod windows_1255;
    pub mod windows_1256;
    pub mod windows_1257;
    pub mod windows_1258;
    pub mod x_mac_cyrillic;
    pub mod big5;
    pub mod euc_kr;
    pub mod gbk;
    pub mod gb18030;
    pub mod jis0208;
    pub mod jis0212;
}

/// Codec implementations.
pub mod codec {
    pub mod error;
    pub mod ascii;
    pub mod singlebyte;
    pub mod utf_8;
    pub mod utf_16;
    pub mod korean;
    pub mod japanese;
    pub mod simpchinese;
    pub mod tradchinese;
    pub mod whatwg;
}

pub mod all;
pub mod label;

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

    #[test]
    fn test_readme() {
        assert_eq!(all::ISO_8859_1.encode("caf\xe9", EncodeStrict), Ok(~[99,97,102,233]));

        assert!(all::ISO_8859_2.encode("Acme\xa9", EncodeStrict).is_err());
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeReplace), Ok(~[65,99,109,101,63]));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeIgnore), Ok(~[65,99,109,101]));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeNcrEscape),
                   Ok(~[65,99,109,101,38,35,49,54,57,59])); // Acme©

        assert_eq!(all::ISO_8859_1.decode([99,97,102,233], DecodeStrict), Ok(~"caf\xe9"));

        assert!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeStrict).is_err());
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeReplace), Ok(~"Acme\ufffd"));
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeIgnore), Ok(~"Acme"));
    }

    #[test]
    fn test_readme_hex_ncr_escape() {
        // hexadecimal numeric character reference replacement
        fn hex_ncr_escape(_encoder: &Encoder, input: &str, output: &mut ByteWriter) -> bool {
            let escapes: ~[~str] =
                input.chars().map(|ch| format!("&\\#x{:x};", ch as int)).collect();
            let escapes = escapes.concat();
            output.write_bytes(escapes.as_bytes());
            true
        }
        let HexNcrEscape = EncoderTrap(hex_ncr_escape);
        let orig = ~"Hello, 世界!";
        let encoded = all::ASCII.encode(orig, HexNcrEscape).unwrap();
        let decoded = all::ASCII.decode(encoded, DecodeStrict).unwrap();
        assert_eq!(decoded, ~"Hello, 世界!");
    }

    #[test]
    fn test_readme_whatwg() {
        let euckr = label::encoding_from_whatwg_label("euc-kr").unwrap();
        assert_eq!(euckr.name(), "windows-949");
        assert_eq!(euckr.whatwg_name(), Some("euc-kr")); // for the sake of compatibility
        let broken = &[0xbf, 0xec, 0xbf, 0xcd, 0xff, 0xbe, 0xd3];
        assert_eq!(euckr.decode(broken, DecodeReplace), Ok(~"\uc6b0\uc640\ufffd\uc559"));

        // corresponding rust-encoding native API:
        assert_eq!(all::WINDOWS_949.decode(broken, DecodeReplace), Ok(~"\uc6b0\uc640\ufffd\uc559"));
    }

    #[test]
    fn test_decode() {
        fn test_one(input: &[u8], expected_result: &str, expected_encoding: &str) {
            let (result, used_encoding) = decode(
                input, DecodeStrict, all::ISO_8859_1 as EncodingRef);
            let result = result.unwrap();
            assert_eq!(used_encoding.name(), expected_encoding);
            assert_eq!(result.as_slice(), expected_result);
        }

        test_one([0xEF, 0xBB, 0xBF, 0xC3, 0xA9], "é", "utf-8");
        test_one([0xC3, 0xA9], "Ã©", "iso-8859-1");

        test_one([0xFE, 0xFF, 0x00, 0xE9], "é", "utf-16be");
        test_one([0x00, 0xE9], "\x00é", "iso-8859-1");

        test_one([0xFF, 0xFE, 0xE9, 0x00], "é", "utf-16le");
        test_one([0xE9, 0x00], "é\x00", "iso-8859-1");
    }
}

<commit_msg>language update: #[link] -> #[crate_id].<commit_after>// This is a part of rust-encoding.
// Copyright (c) 2013, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

/*!
 * Character encoding support for Rust. It is based on [WHATWG Encoding
 * Standard](http://encoding.spec.whatwg.org/), and also provides an advanced interface for
 * error detection and recovery.
 */

#[crate_id = "encoding#0.1.0"];
#[crate_type = "lib"];
#[comment = "Character encoding support for Rust"];
#[license = "MIT"];

#[feature(globs, macro_rules)];

pub use self::types::*; // reexport

mod util;
#[cfg(test)] mod testutils;

pub mod types;

/// Indices used for character encoding implementation. Semi-internal.
pub mod index {
    pub mod ibm866;
    pub mod iso_8859_2;
    pub mod iso_8859_3;
    pub mod iso_8859_4;
    pub mod iso_8859_5;
    pub mod iso_8859_6;
    pub mod iso_8859_7;
    pub mod iso_8859_8;
    pub mod iso_8859_10;
    pub mod iso_8859_13;
    pub mod iso_8859_14;
    pub mod iso_8859_15;
    pub mod iso_8859_16;
    pub mod koi8_r;
    pub mod koi8_u;
    pub mod macintosh;
    pub mod windows_874;
    pub mod windows_1250;
    pub mod windows_1251;
    pub mod windows_1252;
    pub mod windows_1253;
    pub mod windows_1254;
    pub mod windows_1255;
    pub mod windows_1256;
    pub mod windows_1257;
    pub mod windows_1258;
    pub mod x_mac_cyrillic;
    pub mod big5;
    pub mod euc_kr;
    pub mod gbk;
    pub mod gb18030;
    pub mod jis0208;
    pub mod jis0212;
}

/// Codec implementations.
pub mod codec {
    pub mod error;
    pub mod ascii;
    pub mod singlebyte;
    pub mod utf_8;
    pub mod utf_16;
    pub mod korean;
    pub mod japanese;
    pub mod simpchinese;
    pub mod tradchinese;
    pub mod whatwg;
}

pub mod all;
pub mod label;

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

    #[test]
    fn test_readme() {
        assert_eq!(all::ISO_8859_1.encode("caf\xe9", EncodeStrict), Ok(~[99,97,102,233]));

        assert!(all::ISO_8859_2.encode("Acme\xa9", EncodeStrict).is_err());
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeReplace), Ok(~[65,99,109,101,63]));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeIgnore), Ok(~[65,99,109,101]));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeNcrEscape),
                   Ok(~[65,99,109,101,38,35,49,54,57,59])); // Acme©

        assert_eq!(all::ISO_8859_1.decode([99,97,102,233], DecodeStrict), Ok(~"caf\xe9"));

        assert!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeStrict).is_err());
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeReplace), Ok(~"Acme\ufffd"));
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeIgnore), Ok(~"Acme"));
    }

    #[test]
    fn test_readme_hex_ncr_escape() {
        // hexadecimal numeric character reference replacement
        fn hex_ncr_escape(_encoder: &Encoder, input: &str, output: &mut ByteWriter) -> bool {
            let escapes: ~[~str] =
                input.chars().map(|ch| format!("&\\#x{:x};", ch as int)).collect();
            let escapes = escapes.concat();
            output.write_bytes(escapes.as_bytes());
            true
        }
        let HexNcrEscape = EncoderTrap(hex_ncr_escape);
        let orig = ~"Hello, 世界!";
        let encoded = all::ASCII.encode(orig, HexNcrEscape).unwrap();
        let decoded = all::ASCII.decode(encoded, DecodeStrict).unwrap();
        assert_eq!(decoded, ~"Hello, 世界!");
    }

    #[test]
    fn test_readme_whatwg() {
        let euckr = label::encoding_from_whatwg_label("euc-kr").unwrap();
        assert_eq!(euckr.name(), "windows-949");
        assert_eq!(euckr.whatwg_name(), Some("euc-kr")); // for the sake of compatibility
        let broken = &[0xbf, 0xec, 0xbf, 0xcd, 0xff, 0xbe, 0xd3];
        assert_eq!(euckr.decode(broken, DecodeReplace), Ok(~"\uc6b0\uc640\ufffd\uc559"));

        // corresponding rust-encoding native API:
        assert_eq!(all::WINDOWS_949.decode(broken, DecodeReplace), Ok(~"\uc6b0\uc640\ufffd\uc559"));
    }

    #[test]
    fn test_decode() {
        fn test_one(input: &[u8], expected_result: &str, expected_encoding: &str) {
            let (result, used_encoding) = decode(
                input, DecodeStrict, all::ISO_8859_1 as EncodingRef);
            let result = result.unwrap();
            assert_eq!(used_encoding.name(), expected_encoding);
            assert_eq!(result.as_slice(), expected_result);
        }

        test_one([0xEF, 0xBB, 0xBF, 0xC3, 0xA9], "é", "utf-8");
        test_one([0xC3, 0xA9], "Ã©", "iso-8859-1");

        test_one([0xFE, 0xFF, 0x00, 0xE9], "é", "utf-16be");
        test_one([0x00, 0xE9], "\x00é", "iso-8859-1");

        test_one([0xFF, 0xFE, 0xE9, 0x00], "é", "utf-16le");
        test_one([0xE9, 0x00], "é\x00", "iso-8859-1");
    }
}

<|endoftext|>


<commit_before>use std::io::Read;
use std::io::Write;
use std::io::Result;
use std::fs::File;

pub struct FileData
{
	path: Option<String>, //the original path of the file, if provided
	content: Vec<Vec<char>>, //the content as a semi 2D-array of chars
	cursor_line: usize, //the line the cursor is in
	cursor_char: usize, //the character the cursor is in the current line
	modified: bool //ind. wether data has been changed since last save
}

impl FileData
{
	pub fn new() -> FileData
	{
		let mut linevec = Vec::new();
		let charvec = Vec::new();
		linevec.push(charvec);
		FileData
		{
			path: None,
			content: linevec,
			cursor_line: 0,
			cursor_char: 0,
			modified: false
		}
	}

	pub fn new_with_name(path: String) -> FileData
	{
		let mut result = FileData::new();
		result.path = Some(path);
		result
	}

	//load data from path
	pub fn from(filepath: String) -> Result<FileData>
	{
		let mut file = try!(File::open(filepath.clone()));
		let mut filecontent = String::new();
		try!(file.read_to_string(&mut filecontent));
		let mut linevec = Vec::new();
		let mut charvec = Vec::new();
		for ch in filecontent.chars()
		{
			if ch == '\n'
			{
				linevec.push(charvec);
				charvec = Vec::new();
			}
			else
			{
			    charvec.push(ch);
			}
		}
		linevec.push(charvec);
		Ok(FileData
		{
			path: Some(filepath),
			content: linevec,
			cursor_line: 0,
			cursor_char: 0,
			modified: false
		})
	}

	//reset to untitled document
	pub fn clear(&mut self)
	{
		let dummy = FileData::new();
		self.path = dummy.path;
		self.content = dummy.content;
		self.cursor_line = dummy.cursor_line;
		self.cursor_char = dummy.cursor_char;
		self.modified = dummy.modified;
	}

	//return line at "line"
	pub fn get_line(&self, line: usize) -> Option<&Vec<char>>
	{
		if line < self.content.len()
		{
			Some(self.content.get(line).unwrap())
		}
		else
		{
		    None
		}
	}

	pub fn get_cursor_line(&self) -> usize
	{
		self.cursor_line
	}

	pub fn get_cursor_char(&self) -> usize
	{
		self.cursor_char
	}

	pub fn get_path(&self) -> Option<String>
	{
		self.path.clone()
	}

	pub fn set_path(&mut self, path: Option<String>)
	{
		self.path = path;
	}

	pub fn get_title(&self) -> String
	{
		match self.path
		{
			None => String::from("<Untitled>"),
			Some(ref v) => v.clone()
		}
	}

	pub fn get_lines(&self) -> usize
	{
		self.content.len()
	}

	/*pub fn get_line_number_len(&self) -> usize
	{
		format!("{}", self.get_lines()).len()
	}*/

	pub fn is_modified(&self) -> bool
	{
		self.modified
	}

	//CURSOR FUNCTIONS

	pub fn move_cursor_up(&mut self)
	{
		if self.cursor_line != 0
		{
			self.cursor_line -= 1;
			let line_len = self.content.get(self.cursor_line).unwrap().len();
			if self.cursor_char > line_len
			{
				self.cursor_char = line_len;
			}
		}
	}

	pub fn move_cursor_left(&mut self)
	{
		if self.cursor_char != 0
		{
			self.cursor_char -= 1;
		}
		else
		{
			if self.cursor_line != 0
			{
				self.move_cursor_up();
		    	self.cursor_char = self.get_line(self.get_cursor_line()).unwrap().len();
		    }
		}
	}

	pub fn move_cursor_down(&mut self)
	{
		if self.cursor_line < self.get_lines() - 1
		{
			self.cursor_line += 1;
			let line_len = self.content.get(self.cursor_line).unwrap().len();
			if self.cursor_char > line_len
			{
				self.cursor_char = line_len;
			}
		}
	}

	pub fn move_cursor_right(&mut self)
	{
		let cur_line_len = self.get_line(self.get_cursor_line()).unwrap().len();
		if self.cursor_char < cur_line_len
		{
			self.cursor_char += 1;
		}
		else
		{
		    if self.cursor_line < self.get_lines() - 1
		    {
		    	self.move_cursor_down();
		    	self.cursor_char = 0;
		    }
		}
	}

	//EDITING FUNCTIONS

	pub fn write_char(&mut self, ch: char)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		self.content.get_mut(cline).unwrap().insert(cchar, ch);
		self.move_cursor_right();
		self.modified = true;
	}

	pub fn backspace(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		if cchar != 0
		{
			self.content.get_mut(cline).unwrap().remove(cchar-1);
			self.cursor_char -= 1;
		}
		else if cline != 0
		{
		    let mut cur_line = self.content.get(cline).unwrap().clone();
		    let new_char = self.content.get(cline-1).unwrap().len();
		    self.content.get_mut(cline-1).unwrap().append(&mut cur_line);
		    self.content.remove(cline);
		    self.cursor_char = new_char;
		    self.cursor_line -= 1;
		}
		self.modified = true;
	}

	pub fn remove(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		let line_len = self.content.get(cline).unwrap().len();
		if cchar != line_len
		{
			self.content.get_mut(cline).unwrap().remove(cchar);
		}
		else if cline != self.content.len()-1
		{
		    let mut next_line = self.content.get(cline+1).unwrap().clone();
		    self.content.get_mut(cline).unwrap().append(&mut next_line);
		    self.content.remove(cline + 1);
		}
		self.modified = true;
	}

	pub fn enter(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		let clip = self.content.get_mut(cline).unwrap().split_off(cchar);
		self.content.insert(cline+1, clip);
		self.cursor_char = 0;
		self.cursor_line += 1;
		self.modified = true;
	}

	//copy-move to string
	pub fn to_string_copy(&self) -> String
	{
		let mut result = String::new();
		for line in &self.content
		{
			for ch in line
			{
				result.push(ch.clone());
			}
			result.push('\n');
		}
		result
	}

	//load from file
	pub fn open(&mut self, path: String) -> Result<()>
	{
		let dummy = try!(FileData::from(path));
		self.path = dummy.path;
		self.content = dummy.content;
		self.cursor_line = dummy.cursor_line;
		self.cursor_char = dummy.cursor_char;
		self.modified = dummy.modified;
		Ok(())
	}

	//save to original file at self.path
	pub fn save(&mut self) -> Result<()>
	{
		let dummy = String::new();
		let path = match self.path
		{
			Some(ref v) => v.clone(),
			None => dummy //should not happen! check this!
		};
		self.save_to(path)
	}

	//save to file other than original file at self.path
	pub fn save_to(&mut self, path: String) -> Result<()>
	{
		let content = self.to_string_copy();
		let bytes = content.into_bytes();
		let mut file = try!(File::create(path));
		try!(file.write_all(&bytes[..]));
		self.modified = false;
		Ok(())
	}
}<commit_msg>fixed appending an empty line on file load<commit_after>use std::io::Read;
use std::io::Write;
use std::io::Result;
use std::fs::File;

pub struct FileData
{
	path: Option<String>, //the original path of the file, if provided
	content: Vec<Vec<char>>, //the content as a semi 2D-array of chars
	cursor_line: usize, //the line the cursor is in
	cursor_char: usize, //the character the cursor is in the current line
	modified: bool //ind. wether data has been changed since last save
}

impl FileData
{
	pub fn new() -> FileData
	{
		let mut linevec = Vec::new();
		let charvec = Vec::new();
		linevec.push(charvec);
		FileData
		{
			path: None,
			content: linevec,
			cursor_line: 0,
			cursor_char: 0,
			modified: false
		}
	}

	pub fn new_with_name(path: String) -> FileData
	{
		let mut result = FileData::new();
		result.path = Some(path);
		result
	}

	//load data from path
	pub fn from(filepath: String) -> Result<FileData>
	{
		let mut file = try!(File::open(filepath.clone()));
		let mut filecontent = String::new();
		try!(file.read_to_string(&mut filecontent));
		let mut linevec = Vec::new();
		let mut charvec = Vec::new();
		for ch in filecontent.chars()
		{
			if ch == '\n'
			{
				linevec.push(charvec);
				charvec = Vec::new();
			}
			else
			{
			    charvec.push(ch);
			}
		}
		if charvec.len() != 0
		{
			linevec.push(charvec);
		}
		Ok(FileData
		{
			path: Some(filepath),
			content: linevec,
			cursor_line: 0,
			cursor_char: 0,
			modified: false
		})
	}

	//reset to untitled document
	pub fn clear(&mut self)
	{
		let dummy = FileData::new();
		self.path = dummy.path;
		self.content = dummy.content;
		self.cursor_line = dummy.cursor_line;
		self.cursor_char = dummy.cursor_char;
		self.modified = dummy.modified;
	}

	//return line at "line"
	pub fn get_line(&self, line: usize) -> Option<&Vec<char>>
	{
		if line < self.content.len()
		{
			Some(self.content.get(line).unwrap())
		}
		else
		{
		    None
		}
	}

	pub fn get_cursor_line(&self) -> usize
	{
		self.cursor_line
	}

	pub fn get_cursor_char(&self) -> usize
	{
		self.cursor_char
	}

	pub fn get_path(&self) -> Option<String>
	{
		self.path.clone()
	}

	pub fn set_path(&mut self, path: Option<String>)
	{
		self.path = path;
	}

	pub fn get_title(&self) -> String
	{
		match self.path
		{
			None => String::from("<Untitled>"),
			Some(ref v) => v.clone()
		}
	}

	pub fn get_lines(&self) -> usize
	{
		self.content.len()
	}

	/*pub fn get_line_number_len(&self) -> usize
	{
		format!("{}", self.get_lines()).len()
	}*/

	pub fn is_modified(&self) -> bool
	{
		self.modified
	}

	//CURSOR FUNCTIONS

	pub fn move_cursor_up(&mut self)
	{
		if self.cursor_line != 0
		{
			self.cursor_line -= 1;
			let line_len = self.content.get(self.cursor_line).unwrap().len();
			if self.cursor_char > line_len
			{
				self.cursor_char = line_len;
			}
		}
	}

	pub fn move_cursor_left(&mut self)
	{
		if self.cursor_char != 0
		{
			self.cursor_char -= 1;
		}
		else
		{
			if self.cursor_line != 0
			{
				self.move_cursor_up();
		    	self.cursor_char = self.get_line(self.get_cursor_line()).unwrap().len();
		    }
		}
	}

	pub fn move_cursor_down(&mut self)
	{
		if self.cursor_line < self.get_lines() - 1
		{
			self.cursor_line += 1;
			let line_len = self.content.get(self.cursor_line).unwrap().len();
			if self.cursor_char > line_len
			{
				self.cursor_char = line_len;
			}
		}
	}

	pub fn move_cursor_right(&mut self)
	{
		let cur_line_len = self.get_line(self.get_cursor_line()).unwrap().len();
		if self.cursor_char < cur_line_len
		{
			self.cursor_char += 1;
		}
		else
		{
		    if self.cursor_line < self.get_lines() - 1
		    {
		    	self.move_cursor_down();
		    	self.cursor_char = 0;
		    }
		}
	}

	//EDITING FUNCTIONS

	pub fn write_char(&mut self, ch: char)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		self.content.get_mut(cline).unwrap().insert(cchar, ch);
		self.move_cursor_right();
		self.modified = true;
	}

	pub fn backspace(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		if cchar != 0
		{
			self.content.get_mut(cline).unwrap().remove(cchar-1);
			self.cursor_char -= 1;
		}
		else if cline != 0
		{
		    let mut cur_line = self.content.get(cline).unwrap().clone();
		    let new_char = self.content.get(cline-1).unwrap().len();
		    self.content.get_mut(cline-1).unwrap().append(&mut cur_line);
		    self.content.remove(cline);
		    self.cursor_char = new_char;
		    self.cursor_line -= 1;
		}
		self.modified = true;
	}

	pub fn remove(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		let line_len = self.content.get(cline).unwrap().len();
		if cchar != line_len
		{
			self.content.get_mut(cline).unwrap().remove(cchar);
		}
		else if cline != self.content.len()-1
		{
		    let mut next_line = self.content.get(cline+1).unwrap().clone();
		    self.content.get_mut(cline).unwrap().append(&mut next_line);
		    self.content.remove(cline + 1);
		}
		self.modified = true;
	}

	pub fn enter(&mut self)
	{
		let cline = self.get_cursor_line();
		let cchar = self.get_cursor_char();
		let clip = self.content.get_mut(cline).unwrap().split_off(cchar);
		self.content.insert(cline+1, clip);
		self.cursor_char = 0;
		self.cursor_line += 1;
		self.modified = true;
	}

	//copy-move to string
	pub fn to_string_copy(&self) -> String
	{
		let mut result = String::new();
		for line in &self.content
		{
			for ch in line
			{
				result.push(ch.clone());
			}
			result.push('\n');
		}
		result
	}

	//load from file
	pub fn open(&mut self, path: String) -> Result<()>
	{
		let dummy = try!(FileData::from(path));
		self.path = dummy.path;
		self.content = dummy.content;
		self.cursor_line = dummy.cursor_line;
		self.cursor_char = dummy.cursor_char;
		self.modified = dummy.modified;
		Ok(())
	}

	//save to original file at self.path
	pub fn save(&mut self) -> Result<()>
	{
		let dummy = String::new();
		let path = match self.path
		{
			Some(ref v) => v.clone(),
			None => dummy //should not happen! check this!
		};
		self.save_to(path)
	}

	//save to file other than original file at self.path
	pub fn save_to(&mut self, path: String) -> Result<()>
	{
		let content = self.to_string_copy();
		let bytes = content.into_bytes();
		let mut file = try!(File::create(path));
		try!(file.write_all(&bytes[..]));
		self.modified = false;
		Ok(())
	}
}<|endoftext|>


<commit_before>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::io;
use std::os::unix::fs::FileExt;
use std::result;
use libc;

type Result<T> = Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;
}

impl<T> ReadUnixExt for T where T: FileExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        FileExt::read_at(self, buf, offset).map_err(|e| e.raw_os_error().map_or_else(|| libc::EIO, |x| x as libc::c_int))
    }
}

impl<T> WriteUnixExt for T where T: FileExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        FileExt::write_at(self, buf, offset).map_err(|e| e.raw_os_error().map_or_else(|| libc::EIO, |x| x as libc::c_int))
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadUnixExt for ReadWriteAdaptor<R, _> where R: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteUnixExt for ReadWriteAdaptor<_, W> where W: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.reader.write_at(buf, offset)
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadUnixExt for ModalFileLike<R, _, RW> where
    R: ReadUnixExt, RW: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteUnixExt for ModalFileLike<_, W, RW> where
    W: WriteUnixExt, RW: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadUnixExt+WriteUnixExt;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }
}
<commit_msg>Killed impl for FileExt, added flush.<commit_after>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::result;
use libc;

type Result<T> = Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;

    fn flush(&self) -> Result<()> {
        Ok(())
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadUnixExt for ReadWriteAdaptor<R, _> where R: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteUnixExt for ReadWriteAdaptor<_, W> where W: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.reader.write_at(buf, offset)
    }

    fn flush(&self) -> Result<()> {
        self.writer.flush()
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadUnixExt for ModalFileLike<R, _, RW> where
    R: ReadUnixExt, RW: ReadUnixExt {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteUnixExt for ModalFileLike<_, W, RW> where
    W: WriteUnixExt, RW: WriteUnixExt {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }

    fn flush(&self) -> Result<()> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.flush(),
            ReadWrite(rw) => rw.flush(),
        }
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadUnixExt+WriteUnixExt;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }

    fn fsync(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _datasync: bool) -> ResultEmpty {
        Err(libc::ENOSYS)
    }
}
<|endoftext|>


<commit_before>use crate::ptr;
use crate::ops::{Deref, DerefMut};

/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
/// about all values being initialized at their type.  In particular, initializing
/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// the type:
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// struct Peach;
/// struct Banana;
/// struct Melon;
/// struct FruitBox {
///     // Immediately clear there’s something non-trivial going on with these fields.
///     peach: ManuallyDrop<Peach>,
///     melon: Melon, // Field that’s independent of the other two.
///     banana: ManuallyDrop<Banana>,
/// }
///
/// impl Drop for FruitBox {
///     fn drop(&mut self) {
///         unsafe {
///             // Explicit ordering in which field destructors are run specified in the intuitive
///             // location – the destructor of the structure containing the fields.
///             // Moreover, one can now reorder fields within the struct however much they want.
///             ManuallyDrop::drop(&mut self.peach);
///             ManuallyDrop::drop(&mut self.banana);
///         }
///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
///     }
/// }
/// ```
///
/// [`mem::zeroed`]: fn.zeroed.html
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ManuallyDrop<T: ?Sized> {
    value: T,
}

impl<T> ManuallyDrop<T> {
    /// Wrap a value to be manually dropped.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use std::mem::ManuallyDrop;
    /// ManuallyDrop::new(Box::new(()));
    /// ```
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline(always)]
    pub const fn new(value: T) -> ManuallyDrop<T> {
        ManuallyDrop { value }
    }

    /// Extracts the value from the `ManuallyDrop` container.
    ///
    /// This allows the value to be dropped again.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use std::mem::ManuallyDrop;
    /// let x = ManuallyDrop::new(Box::new(()));
    /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
    /// ```
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline(always)]
    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
        slot.value
    }

    /// Takes the contained value out.
    ///
    /// This method is primarily intended for moving out values in drop.
    /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
    /// you can use this method to take the value and use it however desired.
    /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
    ///
    /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
    ///
    /// # Safety
    ///
    /// This function semantically moves out the contained value without preventing further usage.
    /// It is up to the user of this method to ensure that this container is not used again.
    ///
    /// [`ManuallyDrop::drop`]: #method.drop
    /// [`ManuallyDrop::into_inner`]: #method.into_inner
    #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
    #[unstable(feature = "manually_drop_take", issue = "55422")]
    #[inline]
    pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
        ManuallyDrop::into_inner(ptr::read(slot))
    }
}

impl<T: ?Sized> ManuallyDrop<T> {
    /// Manually drops the contained value.
    ///
    /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
    ///
    /// # Safety
    ///
    /// This function runs the destructor of the contained value and thus the wrapped value
    /// now represents uninitialized data. It is up to the user of this method to ensure the
    /// uninitialized data is not actually used, and that this function is called at most once
    /// for a given instance of `ManuallyDrop<T>`.
    ///
    /// [`ManuallyDrop::into_inner`]: #method.into_inner
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline]
    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
        ptr::drop_in_place(&mut slot.value)
    }
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> Deref for ManuallyDrop<T> {
    type Target = T;
    #[inline(always)]
    fn deref(&self) -> &T {
        &self.value
    }
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}
<commit_msg>Update wording<commit_after>use crate::ptr;
use crate::ops::{Deref, DerefMut};

/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
/// about all values being initialized at their type.  In particular, initializing
/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// the type:
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// struct Peach;
/// struct Banana;
/// struct Melon;
/// struct FruitBox {
///     // Immediately clear there’s something non-trivial going on with these fields.
///     peach: ManuallyDrop<Peach>,
///     melon: Melon, // Field that’s independent of the other two.
///     banana: ManuallyDrop<Banana>,
/// }
///
/// impl Drop for FruitBox {
///     fn drop(&mut self) {
///         unsafe {
///             // Explicit ordering in which field destructors are run specified in the intuitive
///             // location – the destructor of the structure containing the fields.
///             // Moreover, one can now reorder fields within the struct however much they want.
///             ManuallyDrop::drop(&mut self.peach);
///             ManuallyDrop::drop(&mut self.banana);
///         }
///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
///     }
/// }
/// ```
///
/// [`mem::zeroed`]: fn.zeroed.html
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ManuallyDrop<T: ?Sized> {
    value: T,
}

impl<T> ManuallyDrop<T> {
    /// Wrap a value to be manually dropped.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use std::mem::ManuallyDrop;
    /// ManuallyDrop::new(Box::new(()));
    /// ```
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline(always)]
    pub const fn new(value: T) -> ManuallyDrop<T> {
        ManuallyDrop { value }
    }

    /// Extracts the value from the `ManuallyDrop` container.
    ///
    /// This allows the value to be dropped again.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use std::mem::ManuallyDrop;
    /// let x = ManuallyDrop::new(Box::new(()));
    /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
    /// ```
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline(always)]
    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
        slot.value
    }

    /// Takes the contained value out.
    ///
    /// This method is primarily intended for moving out values in drop.
    /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
    /// you can use this method to take the value and use it however desired.
    /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
    ///
    /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
    ///
    /// # Safety
    ///
    /// This function semantically moves out the contained value without preventing further usage.
    /// It is up to the user of this method to ensure that this container is not used again.
    ///
    /// [`ManuallyDrop::drop`]: #method.drop
    /// [`ManuallyDrop::into_inner`]: #method.into_inner
    #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
    #[unstable(feature = "manually_drop_take", issue = "55422")]
    #[inline]
    pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
        ManuallyDrop::into_inner(ptr::read(slot))
    }
}

impl<T: ?Sized> ManuallyDrop<T> {
    /// Manually drops the contained value.
    ///
    /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
    ///
    /// # Safety
    ///
    /// This function runs the destructor of the contained value and thus the wrapped value
    /// now represents uninitialized data. It is up to the user of this method to ensure the
    /// uninitialized data is not actually used.
    /// In particular, this function can only be called called at most once
    /// for a given instance of `ManuallyDrop<T>`.
    ///
    /// [`ManuallyDrop::into_inner`]: #method.into_inner
    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[inline]
    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
        ptr::drop_in_place(&mut slot.value)
    }
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> Deref for ManuallyDrop<T> {
    type Target = T;
    #[inline(always)]
    fn deref(&self) -> &T {
        &self.value
    }
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}
<|endoftext|>


<commit_before>//! Handles encoding of a Bitterlemon image

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Run {
	Set(u8),
	Clear(u8)
}

impl Into<u8> for Run {
	fn into(self) -> u8 {

		use self::Run::*;

		match self {
			Set(n)   => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0xc0u8 + n_out
			},
			Clear(n) => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0x80u8 + n_out
			},
		}

	}
}

#[derive(Debug)]
pub struct RunIterator<S> {
	state: Option<Run>,
	source: S,
}

fn rle_new_run(pp: bool) -> Run {
	if pp {Run::Set(1)} else {Run::Clear(1)}
}

const RLE_MAX_RUN: u8 = 64;

impl<S: Iterator<Item=bool>> RunIterator<S> {

	pub fn from_pixels(source: S) -> RunIterator<S> {
		RunIterator {
			state: None,
			source: source
		}
	}
}

impl<S: Iterator<Item=bool>> Iterator for RunIterator<S> {
	type Item = Run;

	fn next(&mut self) -> Option<Run> {
		use self::Run::*;
		loop {

			// Grab next bit from source; early return if None upstream
			let pp = match self.source.next() {
				Some(b) => b,
				None    => return match self.state {
					Some(x) => {
						// Push out current state and clear for next time
						let old = x;
						self.state = None;
						Some(old)
					},
					// All done
					None => None
				}
			};

			match self.state {

				// Can't fit any more in this run
				Some(Set(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Set(RLE_MAX_RUN));
				},

				// Can't fit any more in this run
				Some(Clear(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Clear(RLE_MAX_RUN));
				}

				// Increase existing Set run
				Some(Set(count)) if pp => {
					self.state = Some(Set(count + 1));
					continue;
				},

				// Swap from Set to Clear
				Some(Set(_)) if ! pp => {
					let old = self.state;
					self.state = Some(Clear(1));
					return old;
				},

				// Increase existing Clear run
				Some(Clear(count)) if ! pp => {
					self.state = Some(Clear(count + 1));
					continue;
				},

				// Swap from Clear to Set
				Some(Clear(_)) if pp => {
					let old = self.state;
					self.state = Some(Set(1));
					return old;
				},

				// All cases covered, but can't convince rustc
				Some(_) => {
					unreachable!();
				}

				None => {
					self.state = Some(rle_new_run(pp));
					continue;
				}
			}

		}

	}
}

#[cfg(test)]
mod test_runs {

	use std::iter::Iterator;

	use super::{Run, RunIterator};
	use super::Run::*;

	#[test]
	fn runs() {

		let op = |input: &[u8], output: &[Run]| {

			let bool_stream : Vec<bool> = input.iter().map(|&c| c == b'1').collect();
			let collected : Vec<Run> = RunIterator::from_pixels(bool_stream.iter().map(|&b| b)).collect();

			assert_eq!(output, collected.as_slice());
		};

		// simple single runs
		op(b"1", &[Set(1)]);
		op(b"1111", &[Set(4)]);
		op(b"00", &[Clear(2)]);
		op(b"", &[]);

		// alterations
		op(b"011", &[Clear(1), Set(2)]);
		op(b"110", &[Set(2), Clear(1)]);
		op(b"0101", &[Clear(1), Set(1), Clear(1), Set(1)]);

		// run size limits
		let large_set = [b'1'; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_set, &[Set(super::RLE_MAX_RUN), Set(1)]);

		// clear size limits
		let large_clear = [b'0' ; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_clear, &[Clear(super::RLE_MAX_RUN), Clear(1)]);
	}
}

<commit_msg>Important groundwork: allow counting the size of an array of runs in either runs or frames<commit_after>//! Handles encoding of a Bitterlemon image

extern crate arrayvec;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Run {
	Set(u8),
	Clear(u8)
}

impl Into<u8> for Run {
	fn into(self) -> u8 {

		use self::Run::*;

		match self {
			Set(n)   => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0xc0u8 + n_out
			},
			Clear(n) => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0x80u8 + n_out
			},
		}

	}
}

#[derive(Debug)]
pub struct RunIterator<S> {
	state: Option<Run>,
	source: S,
}

fn rle_new_run(pp: bool) -> Run {
	if pp {Run::Set(1)} else {Run::Clear(1)}
}

const RLE_MAX_RUN: u8 = 64;

impl<S: Iterator<Item=bool>> RunIterator<S> {

	pub fn from_pixels(source: S) -> RunIterator<S> {
		RunIterator {
			state: None,
			source: source
		}
	}
}

impl<S: Iterator<Item=bool>> Iterator for RunIterator<S> {
	type Item = Run;

	fn next(&mut self) -> Option<Run> {
		use self::Run::*;
		loop {

			// Grab next bit from source; early return if None upstream
			let pp = match self.source.next() {
				Some(b) => b,
				None    => return match self.state {
					Some(x) => {
						// Push out current state and clear for next time
						let old = x;
						self.state = None;
						Some(old)
					},
					// All done
					None => None
				}
			};

			match self.state {

				// Can't fit any more in this run
				Some(Set(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Set(RLE_MAX_RUN));
				},

				// Can't fit any more in this run
				Some(Clear(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Clear(RLE_MAX_RUN));
				}

				// Increase existing Set run
				Some(Set(count)) if pp => {
					self.state = Some(Set(count + 1));
					continue;
				},

				// Swap from Set to Clear
				Some(Set(_)) if ! pp => {
					let old = self.state;
					self.state = Some(Clear(1));
					return old;
				},

				// Increase existing Clear run
				Some(Clear(count)) if ! pp => {
					self.state = Some(Clear(count + 1));
					continue;
				},

				// Swap from Clear to Set
				Some(Clear(_)) if pp => {
					let old = self.state;
					self.state = Some(Set(1));
					return old;
				},

				// All cases covered, but can't convince rustc
				Some(_) => {
					unreachable!();
				}

				None => {
					self.state = Some(rle_new_run(pp));
					continue;
				}
			}

		}

	}
}

type RunHolding = arrayvec::ArrayVec<[Run; 128]>;

#[derive(Debug, PartialEq, Eq)]
pub struct WithFrames<S> {
	runs: RunHolding,
	source: S
}

impl<S: Iterator<Item=Run>> WithFrames<S> {
	pub fn new(source: S) -> WithFrames<S> {
		WithFrames {
			runs: RunHolding::new(),
			source: source,
		}
	}
}

fn bytes_as_frame(runs: &RunHolding) -> usize {
	let total_bits: usize = runs.iter().map(|&run| match run {
		Run::Set(x) => x as usize,
		Run::Clear(x) => x as usize,
	}).sum();

	(total_bits + 15) >> 3 // round up to next byte, add header
}

fn bytes_as_runs(runs: &RunHolding) -> usize {
	// runs in bytes are next highest multiples of 64
	runs.iter().map(|&run| {
		let found = match run {
			Run::Set(x) => x,
			Run::Clear(x) => x,
		};
		debug_assert!(found > 0);
		(found + 63) >> 6
	} as usize).sum()
}

#[cfg(test)]
mod test_frame_sizer {

	use super::*;
	use super::Run::*;

	fn op(input: &[Run], frame_size: usize, run_size: usize) {
		let mut builder = RunHolding::new();

		for element in input {
			assert_eq!(None, builder.push(element.clone()));
		}

		assert_eq!(frame_size, bytes_as_frame(&builder));
		assert_eq!(run_size, bytes_as_runs(&builder));
	}

	#[test]
	fn empty() {
		op(&[], 1, 0);
	}

	#[test]
	fn single_set() {
		op(&[Set(1)], 2, 1);
	}

	#[test]
	fn single_clear() {
		op(&[Clear(1)], 2, 1);
	}
	#[test]
	fn enough_to_overflow_a_frame_to_2_post_header_bytes() {
		op(&[Set(5), Clear(5)], 3, 2);
	}

	#[test]
	fn can_pack_3_runs_into_a_single_frame_byte() {
		op(&[Clear(3), Set(2), Clear(3)], 2, 3);
	}
}

impl<S> Iterator for WithFrames<S> {
	type Item = u8;

	fn next(&mut self) -> Option<Self::Item> {
		unimplemented!();
	}

}

#[cfg(test)]
mod test_runs {

	use std::iter::Iterator;

	use super::{Run, RunIterator};
	use super::Run::*;

	#[test]
	fn runs() {

		let op = |input: &[u8], output: &[Run]| {

			let bool_stream : Vec<bool> = input.iter().map(|&c| c == b'1').collect();
			let collected : Vec<Run> = RunIterator::from_pixels(bool_stream.iter().map(|&b| b)).collect();

			assert_eq!(output, collected.as_slice());
		};

		// simple single runs
		op(b"1", &[Set(1)]);
		op(b"1111", &[Set(4)]);
		op(b"00", &[Clear(2)]);
		op(b"", &[]);

		// alterations
		op(b"011", &[Clear(1), Set(2)]);
		op(b"110", &[Set(2), Clear(1)]);
		op(b"0101", &[Clear(1), Set(1), Clear(1), Set(1)]);

		// run size limits
		let large_set = [b'1'; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_set, &[Set(super::RLE_MAX_RUN), Set(1)]);

		// clear size limits
		let large_clear = [b'0' ; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_clear, &[Clear(super::RLE_MAX_RUN), Clear(1)]);
	}
}

<|endoftext|>


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

mod strategy {
    mod dragon;
    mod grisu;
}

use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
use core::num::flt2dec::MAX_SIG_DIGITS;

pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
    match decode(v).1 {
        FullDecoded::Finite(decoded) => decoded,
        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
    }
}
<commit_msg>num: add minimal benchmarks for full floating-point formatting<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod strategy {
    mod dragon;
    mod grisu;
}

use std::f64;
use std::io::Write;
use std::vec::Vec;
use test::Bencher;
use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
use core::num::flt2dec::MAX_SIG_DIGITS;

pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
    match decode(v).1 {
        FullDecoded::Finite(decoded) => decoded,
        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
    }
}

#[bench]
fn bench_small_shortest(b: &mut Bencher) {
    let mut buf = Vec::with_capacity(20);

    b.iter(|| {
        buf.clear();
        write!(&mut buf, "{}", 3.1415926f64).unwrap()
    });
}

#[bench]
fn bench_big_shortest(b: &mut Bencher) {
    let mut buf = Vec::with_capacity(300);

    b.iter(|| {
        buf.clear();
        write!(&mut buf, "{}", f64::MAX).unwrap()
    });
}
<|endoftext|>


<commit_before>//! Simplification of where-clauses and parameter bounds into a prettier and
//! more canonical form.
//!
//! Currently all cross-crate-inlined function use `rustc_middle::ty` to reconstruct
//! the AST (e.g., see all of `clean::inline`), but this is not always a
//! non-lossy transformation. The current format of storage for where-clauses
//! for functions and such is simply a list of predicates. One example of this
//! is that the AST predicate of: `where T: Trait<Foo = Bar>` is encoded as:
//! `where T: Trait, <T as Trait>::Foo = Bar`.
//!
//! This module attempts to reconstruct the original where and/or parameter
//! bounds by special casing scenarios such as these. Fun!

use std::collections::BTreeMap;

use rustc_hir::def_id::DefId;
use rustc_middle::ty;
use rustc_span::Symbol;

use crate::clean;
use crate::clean::GenericArgs as PP;
use crate::clean::WherePredicate as WP;
use crate::core::DocContext;

crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
    // First, partition the where clause into its separate components
    let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new();
    let mut lifetimes = Vec::new();
    let mut equalities = Vec::new();
    let mut tybounds = Vec::new();

    for clause in clauses {
        match clause {
            WP::BoundPredicate { ty, bounds, bound_params } => match ty {
                clean::Generic(s) => {
                    let (b, p) = params.entry(s).or_default();
                    b.extend(bounds);
                    p.extend(bound_params);
                }
                t => tybounds.push((t, (bounds, bound_params))),
            },
            WP::RegionPredicate { lifetime, bounds } => {
                lifetimes.push((lifetime, bounds));
            }
            WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
        }
    }

    // Look for equality predicates on associated types that can be merged into
    // general bound predicates
    equalities.retain(|&(ref lhs, ref rhs)| {
        let (self_, trait_did, name) = if let Some(p) = lhs.projection() {
            p
        } else {
            return true;
        };
        let generic = match self_ {
            clean::Generic(s) => s,
            _ => return true,
        };
        let (bounds, _) = match params.get_mut(generic) {
            Some(bound) => bound,
            None => return true,
        };

        merge_bounds(cx, bounds, trait_did, name, rhs)
    });

    // And finally, let's reassemble everything
    let mut clauses = Vec::new();
    clauses.extend(
        lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
    );
    clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
        ty: clean::Generic(k),
        bounds,
        bound_params: params,
    }));
    clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
        ty,
        bounds,
        bound_params,
    }));
    clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
    clauses
}

crate fn merge_bounds(
    cx: &clean::DocContext<'_>,
    bounds: &mut Vec<clean::GenericBound>,
    trait_did: DefId,
    name: Symbol,
    rhs: &clean::Type,
) -> bool {
    !bounds.iter_mut().any(|b| {
        let trait_ref = match *b {
            clean::GenericBound::TraitBound(ref mut tr, _) => tr,
            clean::GenericBound::Outlives(..) => return false,
        };
        let (did, path) = match trait_ref.trait_ {
            clean::ResolvedPath { did, ref mut path, .. } => (did, path),
            _ => return false,
        };
        // If this QPath's trait `trait_did` is the same as, or a supertrait
        // of, the bound's trait `did` then we can keep going, otherwise
        // this is just a plain old equality bound.
        if !trait_is_same_or_supertrait(cx, did, trait_did) {
            return false;
        }
        let last = path.segments.last_mut().expect("segments were empty");
        match last.args {
            PP::AngleBracketed { ref mut bindings, .. } => {
                bindings.push(clean::TypeBinding {
                    name,
                    kind: clean::TypeBindingKind::Equality { ty: rhs.clone() },
                });
            }
            PP::Parenthesized { ref mut output, .. } => match output {
                Some(o) => assert_eq!(o.as_ref(), rhs),
                None => {
                    if *rhs != clean::Type::Tuple(Vec::new()) {
                        *output = Some(Box::new(rhs.clone()));
                    }
                }
            },
        };
        true
    })
}

fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool {
    if child == trait_ {
        return true;
    }
    let predicates = cx.tcx.super_predicates_of(child);
    debug_assert!(cx.tcx.generics_of(child).has_self);
    let self_ty = cx.tcx.types.self_param;
    predicates
        .predicates
        .iter()
        .filter_map(|(pred, _)| {
            if let ty::PredicateKind::Trait(pred) = pred.kind().skip_binder() {
                if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None }
            } else {
                None
            }
        })
        .any(|did| trait_is_same_or_supertrait(cx, did, trait_))
}
<commit_msg>Rollup merge of #89098 - GuillaumeGomez:where-bounds-order, r=camelid<commit_after>//! Simplification of where-clauses and parameter bounds into a prettier and
//! more canonical form.
//!
//! Currently all cross-crate-inlined function use `rustc_middle::ty` to reconstruct
//! the AST (e.g., see all of `clean::inline`), but this is not always a
//! non-lossy transformation. The current format of storage for where-clauses
//! for functions and such is simply a list of predicates. One example of this
//! is that the AST predicate of: `where T: Trait<Foo = Bar>` is encoded as:
//! `where T: Trait, <T as Trait>::Foo = Bar`.
//!
//! This module attempts to reconstruct the original where and/or parameter
//! bounds by special casing scenarios such as these. Fun!

use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
use rustc_middle::ty;
use rustc_span::Symbol;

use crate::clean;
use crate::clean::GenericArgs as PP;
use crate::clean::WherePredicate as WP;
use crate::core::DocContext;

crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
    // First, partition the where clause into its separate components.
    //
    // We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to
    // the order of the generated bounds.
    let mut params: FxIndexMap<Symbol, (Vec<_>, Vec<_>)> = FxIndexMap::default();
    let mut lifetimes = Vec::new();
    let mut equalities = Vec::new();
    let mut tybounds = Vec::new();

    for clause in clauses {
        match clause {
            WP::BoundPredicate { ty, bounds, bound_params } => match ty {
                clean::Generic(s) => {
                    let (b, p) = params.entry(s).or_default();
                    b.extend(bounds);
                    p.extend(bound_params);
                }
                t => tybounds.push((t, (bounds, bound_params))),
            },
            WP::RegionPredicate { lifetime, bounds } => {
                lifetimes.push((lifetime, bounds));
            }
            WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
        }
    }

    // Look for equality predicates on associated types that can be merged into
    // general bound predicates
    equalities.retain(|&(ref lhs, ref rhs)| {
        let (self_, trait_did, name) = if let Some(p) = lhs.projection() {
            p
        } else {
            return true;
        };
        let generic = match self_ {
            clean::Generic(s) => s,
            _ => return true,
        };
        let (bounds, _) = match params.get_mut(generic) {
            Some(bound) => bound,
            None => return true,
        };

        merge_bounds(cx, bounds, trait_did, name, rhs)
    });

    // And finally, let's reassemble everything
    let mut clauses = Vec::new();
    clauses.extend(
        lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
    );
    clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
        ty: clean::Generic(k),
        bounds,
        bound_params: params,
    }));
    clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
        ty,
        bounds,
        bound_params,
    }));
    clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
    clauses
}

crate fn merge_bounds(
    cx: &clean::DocContext<'_>,
    bounds: &mut Vec<clean::GenericBound>,
    trait_did: DefId,
    name: Symbol,
    rhs: &clean::Type,
) -> bool {
    !bounds.iter_mut().any(|b| {
        let trait_ref = match *b {
            clean::GenericBound::TraitBound(ref mut tr, _) => tr,
            clean::GenericBound::Outlives(..) => return false,
        };
        let (did, path) = match trait_ref.trait_ {
            clean::ResolvedPath { did, ref mut path, .. } => (did, path),
            _ => return false,
        };
        // If this QPath's trait `trait_did` is the same as, or a supertrait
        // of, the bound's trait `did` then we can keep going, otherwise
        // this is just a plain old equality bound.
        if !trait_is_same_or_supertrait(cx, did, trait_did) {
            return false;
        }
        let last = path.segments.last_mut().expect("segments were empty");
        match last.args {
            PP::AngleBracketed { ref mut bindings, .. } => {
                bindings.push(clean::TypeBinding {
                    name,
                    kind: clean::TypeBindingKind::Equality { ty: rhs.clone() },
                });
            }
            PP::Parenthesized { ref mut output, .. } => match output {
                Some(o) => assert_eq!(o.as_ref(), rhs),
                None => {
                    if *rhs != clean::Type::Tuple(Vec::new()) {
                        *output = Some(Box::new(rhs.clone()));
                    }
                }
            },
        };
        true
    })
}

fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool {
    if child == trait_ {
        return true;
    }
    let predicates = cx.tcx.super_predicates_of(child);
    debug_assert!(cx.tcx.generics_of(child).has_self);
    let self_ty = cx.tcx.types.self_param;
    predicates
        .predicates
        .iter()
        .filter_map(|(pred, _)| {
            if let ty::PredicateKind::Trait(pred) = pred.kind().skip_binder() {
                if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None }
            } else {
                None
            }
        })
        .any(|did| trait_is_same_or_supertrait(cx, did, trait_))
}
<|endoftext|>