<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 dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule;
use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use dom::bindings::error::Error::IndexSize;
use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers};
use dom::imagedata::{ImageData, ImageDataHelpers};

use cssparser::Color as CSSColor;
use cssparser::{Parser, RGBA, ToCss};
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

use canvas::canvas_paint_task::{CanvasMsg, CanvasPaintTask, FillOrStrokeStyle};

use std::cell::Cell;
use std::num::{Float, ToPrimitive};
use std::sync::mpsc::{channel, Sender};

#[dom_struct]
pub struct CanvasRenderingContext2D {
    reflector_: Reflector,
    global: GlobalField,
    renderer: Sender<CanvasMsg>,
    canvas: JS<HTMLCanvasElement>,
    stroke_color: Cell<RGBA>,
    fill_color: Cell<RGBA>,
    transform: Cell<Matrix2D<f32>>,
}

impl CanvasRenderingContext2D {
    fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>)
                     -> CanvasRenderingContext2D {
        let black = RGBA {
            red: 0.0,
            green: 0.0,
            blue: 0.0,
            alpha: 1.0,
        };
        CanvasRenderingContext2D {
            reflector_: Reflector::new(),
            global: GlobalField::from_rooted(&global),
            renderer: CanvasPaintTask::start(size),
            canvas: JS::from_rooted(canvas),
            stroke_color: Cell::new(black),
            fill_color: Cell::new(black),
            transform: Cell::new(Matrix2D::identity()),
        }
    }

    pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>)
               -> Temporary<CanvasRenderingContext2D> {
        reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size),
                           global, CanvasRenderingContext2DBinding::Wrap)
    }

    pub fn recreate(&self, size: Size2D<i32>) {
        self.renderer.send(CanvasMsg::Recreate(size)).unwrap();
    }

    fn update_transform(&self) {
        self.renderer.send(CanvasMsg::SetTransform(self.transform.get())).unwrap()
    }
}

pub trait LayoutCanvasRenderingContext2DHelpers {
    unsafe fn get_renderer(&self) -> Sender<CanvasMsg>;
}

impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D> {
    unsafe fn get_renderer(&self) -> Sender<CanvasMsg> {
        (*self.unsafe_get()).renderer.clone()
    }
}

impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> {
    fn Canvas(self) -> Temporary<HTMLCanvasElement> {
        Temporary::new(self.canvas)
    }

    fn Scale(self, x: f64, y: f64) {
        self.transform.set(self.transform.get().scale(x as f32, y as f32));
        self.update_transform()
    }

    fn Translate(self, x: f64, y: f64) {
        self.transform.set(self.transform.get().translate(x as f32, y as f32));
        self.update_transform()
    }

    fn Transform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
        self.transform.set(self.transform.get().mul(&Matrix2D::new(a as f32,
                                                                   b as f32,
                                                                   c as f32,
                                                                   d as f32,
                                                                   e as f32,
                                                                   f as f32)));
        self.update_transform()
    }

    fn SetTransform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
        self.transform.set(Matrix2D::new(a as f32,
                                         b as f32,
                                         c as f32,
                                         d as f32,
                                         e as f32,
                                         f as f32));
        self.update_transform()
    }

    fn FillRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::FillRect(rect)).unwrap();
    }

    fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::ClearRect(rect)).unwrap();
    }

    fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::StrokeRect(rect)).unwrap();
    }

    fn BeginPath(self) {
        self.renderer.send(CanvasMsg::BeginPath).unwrap();
    }

    fn ClosePath(self) {
        self.renderer.send(CanvasMsg::ClosePath).unwrap();
    }

    fn Fill(self, _: CanvasWindingRule) {
        self.renderer.send(CanvasMsg::Fill).unwrap();
    }

    fn MoveTo(self, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::MoveTo(Point2D(x as f32, y as f32))).unwrap();
    }

    fn LineTo(self, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::LineTo(Point2D(x as f32, y as f32)));
    }

    fn BezierCurveTo(self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::BezierCurveTo(Point2D(cp1x as f32, cp1y as f32),
                                                    Point2D(cp2x as f32, cp2y as f32),
                                                    Point2D(x as f32, y as f32))).unwrap();
    }

    fn StrokeStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
        // FIXME(pcwalton, #4761): This is not spec-compliant. See:
        //
        // https://html.spec.whatwg.org/multipage/scripting.html#serialisation-of-a-colour
        let mut result = String::new();
        self.stroke_color.get().to_css(&mut result).unwrap();
        StringOrCanvasGradientOrCanvasPattern::eString(result)
    }

    fn SetStrokeStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
        match value {
            StringOrCanvasGradientOrCanvasPattern::eString(string) => {
                match parse_color(string.as_slice()) {
                    Ok(rgba) => {
                        self.stroke_color.set(rgba);
                        self.renderer
                            .send(CanvasMsg::SetStrokeStyle(FillOrStrokeStyle::Color(rgba)))
                            .unwrap();
                    }
                    _ => {}
                }
            }
            _ => {
                // TODO(pcwalton)
            }
        }
    }

    fn FillStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
        // FIXME(pcwalton, #4761): This is not spec-compliant. See:
        //
        // https://html.spec.whatwg.org/multipage/scripting.html#serialisation-of-a-colour
        let mut result = String::new();
        self.stroke_color.get().to_css(&mut result).unwrap();
        StringOrCanvasGradientOrCanvasPattern::eString(result)
    }

    fn SetFillStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
        match value {
            StringOrCanvasGradientOrCanvasPattern::eString(string) => {
                match parse_color(string.as_slice()) {
                    Ok(rgba) => {
                        self.fill_color.set(rgba);
                        self.renderer
                            .send(CanvasMsg::SetFillStyle(FillOrStrokeStyle::Color(rgba)))
                            .unwrap()
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> {
        if sw == 0.0 || sh == 0.0 {
            return Err(IndexSize)
        }

        Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), None))
    }

    fn CreateImageData_(self, imagedata: JSRef<ImageData>) -> Fallible<Temporary<ImageData>> {
        Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None))
    }

    fn GetImageData(self, sx: f64, sy: f64, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> {
        if sw == 0.0 || sh == 0.0 {
            return Err(IndexSize)
        }

        let (sender, receiver) = channel::<Vec<u8>>();
        let dest_rect = Rect(Point2D(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D(sw.to_i32().unwrap(), sh.to_i32().unwrap()));
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::GetImageData(dest_rect, canvas_size, sender)).unwrap();
        let data = receiver.recv().unwrap();
        Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), Some(data)))
    }

    fn PutImageData(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64) {
        let data = imagedata.get_data_array(&self.global.root().r());
        let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()), imagedata.get_size());
        let dirty_rect = None;
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap()
    }

    fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64,
                     dirtyX: f64, dirtyY: f64, dirtyWidth: f64, dirtyHeight: f64) {
        let data = imagedata.get_data_array(&self.global.root().r());
        let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()),
                                   Size2D(imagedata.Width().to_i32().unwrap(),
                                          imagedata.Height().to_i32().unwrap()));
        let dirty_rect = Some(Rect(Point2D(dirtyX.to_i32().unwrap(), dirtyY.to_i32().unwrap()),
                                   Size2D(dirtyWidth.to_i32().unwrap(),
                                          dirtyHeight.to_i32().unwrap())));
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap()
    }
}

#[unsafe_destructor]
impl Drop for CanvasRenderingContext2D {
    fn drop(&mut self) {
        self.renderer.send(CanvasMsg::Close).unwrap();
    }
}

pub fn parse_color(string: &str) -> Result<RGBA,()> {
    match CSSColor::parse(&mut Parser::new(string.as_slice())) {
        Ok(CSSColor::RGBA(rgba)) => Ok(rgba),
        _ => Err(()),
    }
}

<commit_msg>Cleanup compilation warning.<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 dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule;
use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use dom::bindings::error::Error::IndexSize;
use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers};
use dom::imagedata::{ImageData, ImageDataHelpers};

use cssparser::Color as CSSColor;
use cssparser::{Parser, RGBA, ToCss};
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

use canvas::canvas_paint_task::{CanvasMsg, CanvasPaintTask, FillOrStrokeStyle};

use std::cell::Cell;
use std::num::{Float, ToPrimitive};
use std::sync::mpsc::{channel, Sender};

#[dom_struct]
pub struct CanvasRenderingContext2D {
    reflector_: Reflector,
    global: GlobalField,
    renderer: Sender<CanvasMsg>,
    canvas: JS<HTMLCanvasElement>,
    stroke_color: Cell<RGBA>,
    fill_color: Cell<RGBA>,
    transform: Cell<Matrix2D<f32>>,
}

impl CanvasRenderingContext2D {
    fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>)
                     -> CanvasRenderingContext2D {
        let black = RGBA {
            red: 0.0,
            green: 0.0,
            blue: 0.0,
            alpha: 1.0,
        };
        CanvasRenderingContext2D {
            reflector_: Reflector::new(),
            global: GlobalField::from_rooted(&global),
            renderer: CanvasPaintTask::start(size),
            canvas: JS::from_rooted(canvas),
            stroke_color: Cell::new(black),
            fill_color: Cell::new(black),
            transform: Cell::new(Matrix2D::identity()),
        }
    }

    pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>)
               -> Temporary<CanvasRenderingContext2D> {
        reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size),
                           global, CanvasRenderingContext2DBinding::Wrap)
    }

    pub fn recreate(&self, size: Size2D<i32>) {
        self.renderer.send(CanvasMsg::Recreate(size)).unwrap();
    }

    fn update_transform(&self) {
        self.renderer.send(CanvasMsg::SetTransform(self.transform.get())).unwrap()
    }
}

pub trait LayoutCanvasRenderingContext2DHelpers {
    unsafe fn get_renderer(&self) -> Sender<CanvasMsg>;
}

impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D> {
    unsafe fn get_renderer(&self) -> Sender<CanvasMsg> {
        (*self.unsafe_get()).renderer.clone()
    }
}

impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> {
    fn Canvas(self) -> Temporary<HTMLCanvasElement> {
        Temporary::new(self.canvas)
    }

    fn Scale(self, x: f64, y: f64) {
        self.transform.set(self.transform.get().scale(x as f32, y as f32));
        self.update_transform()
    }

    fn Translate(self, x: f64, y: f64) {
        self.transform.set(self.transform.get().translate(x as f32, y as f32));
        self.update_transform()
    }

    fn Transform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
        self.transform.set(self.transform.get().mul(&Matrix2D::new(a as f32,
                                                                   b as f32,
                                                                   c as f32,
                                                                   d as f32,
                                                                   e as f32,
                                                                   f as f32)));
        self.update_transform()
    }

    fn SetTransform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
        self.transform.set(Matrix2D::new(a as f32,
                                         b as f32,
                                         c as f32,
                                         d as f32,
                                         e as f32,
                                         f as f32));
        self.update_transform()
    }

    fn FillRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::FillRect(rect)).unwrap();
    }

    fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::ClearRect(rect)).unwrap();
    }

    fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) {
        let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
        self.renderer.send(CanvasMsg::StrokeRect(rect)).unwrap();
    }

    fn BeginPath(self) {
        self.renderer.send(CanvasMsg::BeginPath).unwrap();
    }

    fn ClosePath(self) {
        self.renderer.send(CanvasMsg::ClosePath).unwrap();
    }

    fn Fill(self, _: CanvasWindingRule) {
        self.renderer.send(CanvasMsg::Fill).unwrap();
    }

    fn MoveTo(self, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::MoveTo(Point2D(x as f32, y as f32))).unwrap();
    }

    fn LineTo(self, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::LineTo(Point2D(x as f32, y as f32))).unwrap();
    }

    fn BezierCurveTo(self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
        self.renderer.send(CanvasMsg::BezierCurveTo(Point2D(cp1x as f32, cp1y as f32),
                                                    Point2D(cp2x as f32, cp2y as f32),
                                                    Point2D(x as f32, y as f32))).unwrap();
    }

    fn StrokeStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
        // FIXME(pcwalton, #4761): This is not spec-compliant. See:
        //
        // https://html.spec.whatwg.org/multipage/scripting.html#serialisation-of-a-colour
        let mut result = String::new();
        self.stroke_color.get().to_css(&mut result).unwrap();
        StringOrCanvasGradientOrCanvasPattern::eString(result)
    }

    fn SetStrokeStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
        match value {
            StringOrCanvasGradientOrCanvasPattern::eString(string) => {
                match parse_color(string.as_slice()) {
                    Ok(rgba) => {
                        self.stroke_color.set(rgba);
                        self.renderer
                            .send(CanvasMsg::SetStrokeStyle(FillOrStrokeStyle::Color(rgba)))
                            .unwrap();
                    }
                    _ => {}
                }
            }
            _ => {
                // TODO(pcwalton)
            }
        }
    }

    fn FillStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
        // FIXME(pcwalton, #4761): This is not spec-compliant. See:
        //
        // https://html.spec.whatwg.org/multipage/scripting.html#serialisation-of-a-colour
        let mut result = String::new();
        self.stroke_color.get().to_css(&mut result).unwrap();
        StringOrCanvasGradientOrCanvasPattern::eString(result)
    }

    fn SetFillStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
        match value {
            StringOrCanvasGradientOrCanvasPattern::eString(string) => {
                match parse_color(string.as_slice()) {
                    Ok(rgba) => {
                        self.fill_color.set(rgba);
                        self.renderer
                            .send(CanvasMsg::SetFillStyle(FillOrStrokeStyle::Color(rgba)))
                            .unwrap()
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> {
        if sw == 0.0 || sh == 0.0 {
            return Err(IndexSize)
        }

        Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), None))
    }

    fn CreateImageData_(self, imagedata: JSRef<ImageData>) -> Fallible<Temporary<ImageData>> {
        Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None))
    }

    fn GetImageData(self, sx: f64, sy: f64, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> {
        if sw == 0.0 || sh == 0.0 {
            return Err(IndexSize)
        }

        let (sender, receiver) = channel::<Vec<u8>>();
        let dest_rect = Rect(Point2D(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D(sw.to_i32().unwrap(), sh.to_i32().unwrap()));
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::GetImageData(dest_rect, canvas_size, sender)).unwrap();
        let data = receiver.recv().unwrap();
        Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), Some(data)))
    }

    fn PutImageData(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64) {
        let data = imagedata.get_data_array(&self.global.root().r());
        let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()), imagedata.get_size());
        let dirty_rect = None;
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap()
    }

    fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64,
                     dirtyX: f64, dirtyY: f64, dirtyWidth: f64, dirtyHeight: f64) {
        let data = imagedata.get_data_array(&self.global.root().r());
        let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()),
                                   Size2D(imagedata.Width().to_i32().unwrap(),
                                          imagedata.Height().to_i32().unwrap()));
        let dirty_rect = Some(Rect(Point2D(dirtyX.to_i32().unwrap(), dirtyY.to_i32().unwrap()),
                                   Size2D(dirtyWidth.to_i32().unwrap(),
                                          dirtyHeight.to_i32().unwrap())));
        let canvas_size = self.canvas.root().r().get_size();
        self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap()
    }
}

#[unsafe_destructor]
impl Drop for CanvasRenderingContext2D {
    fn drop(&mut self) {
        self.renderer.send(CanvasMsg::Close).unwrap();
    }
}

pub fn parse_color(string: &str) -> Result<RGBA,()> {
    match CSSColor::parse(&mut Parser::new(string.as_slice())) {
        Ok(CSSColor::RGBA(rgba)) => Ok(rgba),
        _ => Err(()),
    }
}

<|endoftext|>


<commit_before>// Copyright 2013-2015 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.

//! Dynamic library facilities.
//!
//! A simple wrapper over the platform's dynamic library facilities

#![unstable(feature = "dynamic_lib",
            reason = "API has not been scrutinized and is highly likely to \
                      either disappear or change",
            issue = "27810")]
#![rustc_deprecated(since = "1.5.0", reason = "replaced with crates.io 'libloading'")]
#![allow(missing_docs)]
#![allow(deprecated)]

use prelude::v1::*;

use env;
use ffi::{CString, OsString};
use path::{Path, PathBuf};

pub struct DynamicLibrary {
    handle: *mut u8
}

impl Drop for DynamicLibrary {
    fn drop(&mut self) {
        match dl::check_for_errors_in(|| {
            unsafe {
                dl::close(self.handle)
            }
        }) {
            Ok(()) => {},
            Err(str) => panic!("{}", str)
        }
    }
}

impl DynamicLibrary {
    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
        let maybe_library = dl::open(filename.map(|path| path.as_os_str()));

        // The dynamic library must not be constructed if there is
        // an error opening the library so the destructor does not
        // run.
        match maybe_library {
            Err(err) => Err(err),
            Ok(handle) => Ok(DynamicLibrary { handle: handle })
        }
    }

    /// Prepends a path to this process's search path for dynamic libraries
    pub fn prepend_search_path(path: &Path) {
        let mut search_path = DynamicLibrary::search_path();
        search_path.insert(0, path.to_path_buf());
        env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path));
    }

    /// From a slice of paths, create a new vector which is suitable to be an
    /// environment variable for this platforms dylib search path.
    pub fn create_path(path: &[PathBuf]) -> OsString {
        let mut newvar = OsString::new();
        for (i, path) in path.iter().enumerate() {
            if i > 0 { newvar.push(DynamicLibrary::separator()); }
            newvar.push(path);
        }
        return newvar;
    }

    /// Returns the environment variable for this process's dynamic library
    /// search path
    pub fn envvar() -> &'static str {
        if cfg!(windows) {
            "PATH"
        } else if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        }
    }

    fn separator() -> &'static str {
        if cfg!(windows) { ";" } else { ":" }
    }

    /// Returns the current search path for dynamic libraries being used by this
    /// process
    pub fn search_path() -> Vec<PathBuf> {
        match env::var_os(DynamicLibrary::envvar()) {
            Some(var) => env::split_paths(&var).collect(),
            None => Vec::new(),
        }
    }

    /// Accesses the value at the symbol of the dynamic library.
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
        // This function should have a lifetime constraint of 'a on
        // T but that feature is still unimplemented

        let raw_string = CString::new(symbol).unwrap();
        let maybe_symbol_value = dl::check_for_errors_in(|| {
            dl::symbol(self.handle, raw_string.as_ptr())
        });

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(symbol_value as *mut T)
        }
    }
}

#[cfg(all(test, not(target_os = "ios"), not(target_os = "nacl")))]
mod tests {
    use super::*;
    use prelude::v1::*;
    use libc;
    use mem;
    use path::Path;

    #[test]
    #[cfg_attr(any(windows,
                   target_os = "android",  // FIXME #10379
                   target_env = "musl"), ignore)]
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let libm = match DynamicLibrary::open(None) {
            Err(error) => panic!("Could not load self as module: {}", error),
            Ok(libm) => libm
        };

        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => panic!("Could not load function cos: {}", error),
                Ok(cosine) => mem::transmute::<*mut u8, _>(cosine)
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            panic!("cos({}) != {} but equaled {} instead", argument,
                   expected_result, result)
        }
    }

    #[test]
    #[cfg(any(target_os = "linux",
              target_os = "macos",
              target_os = "freebsd",
              target_os = "dragonfly",
              target_os = "bitrig",
              target_os = "netbsd",
              target_os = "openbsd"))]
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = Path::new("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => panic!("Successfully opened the empty library.")
        }
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd",
          target_os = "openbsd"))]
mod dl {
    use prelude::v1::*;

    use ffi::{CStr, OsStr};
    use str;
    use libc;
    use ptr;

    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
        check_for_errors_in(|| {
            unsafe {
                match filename {
                    Some(filename) => open_external(filename),
                    None => open_internal(),
                }
            }
        })
    }

    const LAZY: libc::c_int = 1;

    unsafe fn open_external(filename: &OsStr) -> *mut u8 {
        let s = filename.to_cstring().unwrap();
        libc::dlopen(s.as_ptr(), LAZY) as *mut u8
    }

    unsafe fn open_internal() -> *mut u8 {
        libc::dlopen(ptr::null(), LAZY) as *mut u8
    }

    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
        F: FnOnce() -> T,
    {
        use sync::StaticMutex;
        static LOCK: StaticMutex = StaticMutex::new();
        unsafe {
            // dlerror isn't thread safe, so we need to lock around this entire
            // sequence
            let _guard = LOCK.lock();
            let _old_error = libc::dlerror();

            let result = f();

            let last_error = libc::dlerror() as *const _;
            let ret = if ptr::null() == last_error {
                Ok(result)
            } else {
                let s = CStr::from_ptr(last_error).to_bytes();
                Err(str::from_utf8(s).unwrap().to_owned())
            };

            ret
        }
    }

    pub unsafe fn symbol(handle: *mut u8,
                         symbol: *const libc::c_char) -> *mut u8 {
        libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
    }
    pub unsafe fn close(handle: *mut u8) {
        libc::dlclose(handle as *mut libc::c_void); ()
    }
}

#[cfg(target_os = "windows")]
mod dl {
    use prelude::v1::*;

    use ffi::OsStr;
    use libc;
    use os::windows::prelude::*;
    use ptr;
    use sys::c;
    use sys::os;

    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
        // disable "dll load failed" error dialog.
        let mut use_thread_mode = true;
        let prev_error_mode = unsafe {
            // SEM_FAILCRITICALERRORS 0x01
            let new_error_mode = 1;
            let mut prev_error_mode = 0;
            // Windows >= 7 supports thread error mode.
            let result = c::SetThreadErrorMode(new_error_mode,
                                               &mut prev_error_mode);
            if result == 0 {
                let err = os::errno();
                if err == c::ERROR_CALL_NOT_IMPLEMENTED as i32 {
                    use_thread_mode = false;
                    // SetThreadErrorMode not found. use fallback solution:
                    // SetErrorMode() Note that SetErrorMode is process-wide so
                    // this can cause race condition!  However, since even
                    // Windows APIs do not care of such problem (#20650), we
                    // just assume SetErrorMode race is not a great deal.
                    prev_error_mode = c::SetErrorMode(new_error_mode);
                }
            }
            prev_error_mode
        };

        unsafe {
            c::SetLastError(0);
        }

        let result = match filename {
            Some(filename) => {
                let filename_str: Vec<_> =
                    filename.encode_wide().chain(Some(0)).collect();
                let result = unsafe {
                    c::LoadLibraryW(filename_str.as_ptr())
                };
                // beware: Vec/String may change errno during drop!
                // so we get error here.
                if result == ptr::null_mut() {
                    let errno = os::errno();
                    Err(os::error_string(errno))
                } else {
                    Ok(result as *mut u8)
                }
            }
            None => {
                let mut handle = ptr::null_mut();
                let succeeded = unsafe {
                    c::GetModuleHandleExW(0 as c::DWORD, ptr::null(),
                                          &mut handle)
                };
                if succeeded == c::FALSE {
                    let errno = os::errno();
                    Err(os::error_string(errno))
                } else {
                    Ok(handle as *mut u8)
                }
            }
        };

        unsafe {
            if use_thread_mode {
                c::SetThreadErrorMode(prev_error_mode, ptr::null_mut());
            } else {
                c::SetErrorMode(prev_error_mode);
            }
        }

        result
    }

    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
        F: FnOnce() -> T,
    {
        unsafe {
            c::SetLastError(0);

            let result = f();

            let error = os::errno();
            if 0 == error {
                Ok(result)
            } else {
                Err(format!("Error code {}", error))
            }
        }
    }

    pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 {
        c::GetProcAddress(handle as c::HMODULE, symbol) as *mut u8
    }
    pub unsafe fn close(handle: *mut u8) {
        c::FreeLibrary(handle as c::HMODULE);
    }
}

#[cfg(target_os = "nacl")]
pub mod dl {
    use ffi::OsStr;
    use ptr;
    use result::Result;
    use result::Result::Err;
    use libc;
    use string::String;
    use ops::FnOnce;
    use option::Option;

    pub fn open(_filename: Option<&OsStr>) -> Result<*mut u8, String> {
        Err(format!("NaCl + Newlib doesn't impl loading shared objects"))
    }

    pub fn check_for_errors_in<T, F>(_f: F) -> Result<T, String>
        where F: FnOnce() -> T,
    {
        Err(format!("NaCl doesn't support shared objects"))
    }

    pub unsafe fn symbol(_handle: *mut u8, _symbol: *const libc::c_char) -> *mut u8 {
        ptr::null_mut()
    }
    pub unsafe fn close(_handle: *mut u8) { }
}
<commit_msg>Corrected deprecation reference to appropriate crate<commit_after>// Copyright 2013-2015 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.

//! Dynamic library facilities.
//!
//! A simple wrapper over the platform's dynamic library facilities

#![unstable(feature = "dynamic_lib",
            reason = "API has not been scrutinized and is highly likely to \
                      either disappear or change",
            issue = "27810")]
#![rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
#![allow(missing_docs)]
#![allow(deprecated)]

use prelude::v1::*;

use env;
use ffi::{CString, OsString};
use path::{Path, PathBuf};

pub struct DynamicLibrary {
    handle: *mut u8
}

impl Drop for DynamicLibrary {
    fn drop(&mut self) {
        match dl::check_for_errors_in(|| {
            unsafe {
                dl::close(self.handle)
            }
        }) {
            Ok(()) => {},
            Err(str) => panic!("{}", str)
        }
    }
}

impl DynamicLibrary {
    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
        let maybe_library = dl::open(filename.map(|path| path.as_os_str()));

        // The dynamic library must not be constructed if there is
        // an error opening the library so the destructor does not
        // run.
        match maybe_library {
            Err(err) => Err(err),
            Ok(handle) => Ok(DynamicLibrary { handle: handle })
        }
    }

    /// Prepends a path to this process's search path for dynamic libraries
    pub fn prepend_search_path(path: &Path) {
        let mut search_path = DynamicLibrary::search_path();
        search_path.insert(0, path.to_path_buf());
        env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path));
    }

    /// From a slice of paths, create a new vector which is suitable to be an
    /// environment variable for this platforms dylib search path.
    pub fn create_path(path: &[PathBuf]) -> OsString {
        let mut newvar = OsString::new();
        for (i, path) in path.iter().enumerate() {
            if i > 0 { newvar.push(DynamicLibrary::separator()); }
            newvar.push(path);
        }
        return newvar;
    }

    /// Returns the environment variable for this process's dynamic library
    /// search path
    pub fn envvar() -> &'static str {
        if cfg!(windows) {
            "PATH"
        } else if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        }
    }

    fn separator() -> &'static str {
        if cfg!(windows) { ";" } else { ":" }
    }

    /// Returns the current search path for dynamic libraries being used by this
    /// process
    pub fn search_path() -> Vec<PathBuf> {
        match env::var_os(DynamicLibrary::envvar()) {
            Some(var) => env::split_paths(&var).collect(),
            None => Vec::new(),
        }
    }

    /// Accesses the value at the symbol of the dynamic library.
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
        // This function should have a lifetime constraint of 'a on
        // T but that feature is still unimplemented

        let raw_string = CString::new(symbol).unwrap();
        let maybe_symbol_value = dl::check_for_errors_in(|| {
            dl::symbol(self.handle, raw_string.as_ptr())
        });

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(symbol_value as *mut T)
        }
    }
}

#[cfg(all(test, not(target_os = "ios"), not(target_os = "nacl")))]
mod tests {
    use super::*;
    use prelude::v1::*;
    use libc;
    use mem;
    use path::Path;

    #[test]
    #[cfg_attr(any(windows,
                   target_os = "android",  // FIXME #10379
                   target_env = "musl"), ignore)]
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let libm = match DynamicLibrary::open(None) {
            Err(error) => panic!("Could not load self as module: {}", error),
            Ok(libm) => libm
        };

        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => panic!("Could not load function cos: {}", error),
                Ok(cosine) => mem::transmute::<*mut u8, _>(cosine)
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            panic!("cos({}) != {} but equaled {} instead", argument,
                   expected_result, result)
        }
    }

    #[test]
    #[cfg(any(target_os = "linux",
              target_os = "macos",
              target_os = "freebsd",
              target_os = "dragonfly",
              target_os = "bitrig",
              target_os = "netbsd",
              target_os = "openbsd"))]
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = Path::new("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => panic!("Successfully opened the empty library.")
        }
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd",
          target_os = "openbsd"))]
mod dl {
    use prelude::v1::*;

    use ffi::{CStr, OsStr};
    use str;
    use libc;
    use ptr;

    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
        check_for_errors_in(|| {
            unsafe {
                match filename {
                    Some(filename) => open_external(filename),
                    None => open_internal(),
                }
            }
        })
    }

    const LAZY: libc::c_int = 1;

    unsafe fn open_external(filename: &OsStr) -> *mut u8 {
        let s = filename.to_cstring().unwrap();
        libc::dlopen(s.as_ptr(), LAZY) as *mut u8
    }

    unsafe fn open_internal() -> *mut u8 {
        libc::dlopen(ptr::null(), LAZY) as *mut u8
    }

    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
        F: FnOnce() -> T,
    {
        use sync::StaticMutex;
        static LOCK: StaticMutex = StaticMutex::new();
        unsafe {
            // dlerror isn't thread safe, so we need to lock around this entire
            // sequence
            let _guard = LOCK.lock();
            let _old_error = libc::dlerror();

            let result = f();

            let last_error = libc::dlerror() as *const _;
            let ret = if ptr::null() == last_error {
                Ok(result)
            } else {
                let s = CStr::from_ptr(last_error).to_bytes();
                Err(str::from_utf8(s).unwrap().to_owned())
            };

            ret
        }
    }

    pub unsafe fn symbol(handle: *mut u8,
                         symbol: *const libc::c_char) -> *mut u8 {
        libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
    }
    pub unsafe fn close(handle: *mut u8) {
        libc::dlclose(handle as *mut libc::c_void); ()
    }
}

#[cfg(target_os = "windows")]
mod dl {
    use prelude::v1::*;

    use ffi::OsStr;
    use libc;
    use os::windows::prelude::*;
    use ptr;
    use sys::c;
    use sys::os;

    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
        // disable "dll load failed" error dialog.
        let mut use_thread_mode = true;
        let prev_error_mode = unsafe {
            // SEM_FAILCRITICALERRORS 0x01
            let new_error_mode = 1;
            let mut prev_error_mode = 0;
            // Windows >= 7 supports thread error mode.
            let result = c::SetThreadErrorMode(new_error_mode,
                                               &mut prev_error_mode);
            if result == 0 {
                let err = os::errno();
                if err == c::ERROR_CALL_NOT_IMPLEMENTED as i32 {
                    use_thread_mode = false;
                    // SetThreadErrorMode not found. use fallback solution:
                    // SetErrorMode() Note that SetErrorMode is process-wide so
                    // this can cause race condition!  However, since even
                    // Windows APIs do not care of such problem (#20650), we
                    // just assume SetErrorMode race is not a great deal.
                    prev_error_mode = c::SetErrorMode(new_error_mode);
                }
            }
            prev_error_mode
        };

        unsafe {
            c::SetLastError(0);
        }

        let result = match filename {
            Some(filename) => {
                let filename_str: Vec<_> =
                    filename.encode_wide().chain(Some(0)).collect();
                let result = unsafe {
                    c::LoadLibraryW(filename_str.as_ptr())
                };
                // beware: Vec/String may change errno during drop!
                // so we get error here.
                if result == ptr::null_mut() {
                    let errno = os::errno();
                    Err(os::error_string(errno))
                } else {
                    Ok(result as *mut u8)
                }
            }
            None => {
                let mut handle = ptr::null_mut();
                let succeeded = unsafe {
                    c::GetModuleHandleExW(0 as c::DWORD, ptr::null(),
                                          &mut handle)
                };
                if succeeded == c::FALSE {
                    let errno = os::errno();
                    Err(os::error_string(errno))
                } else {
                    Ok(handle as *mut u8)
                }
            }
        };

        unsafe {
            if use_thread_mode {
                c::SetThreadErrorMode(prev_error_mode, ptr::null_mut());
            } else {
                c::SetErrorMode(prev_error_mode);
            }
        }

        result
    }

    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
        F: FnOnce() -> T,
    {
        unsafe {
            c::SetLastError(0);

            let result = f();

            let error = os::errno();
            if 0 == error {
                Ok(result)
            } else {
                Err(format!("Error code {}", error))
            }
        }
    }

    pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 {
        c::GetProcAddress(handle as c::HMODULE, symbol) as *mut u8
    }
    pub unsafe fn close(handle: *mut u8) {
        c::FreeLibrary(handle as c::HMODULE);
    }
}

#[cfg(target_os = "nacl")]
pub mod dl {
    use ffi::OsStr;
    use ptr;
    use result::Result;
    use result::Result::Err;
    use libc;
    use string::String;
    use ops::FnOnce;
    use option::Option;

    pub fn open(_filename: Option<&OsStr>) -> Result<*mut u8, String> {
        Err(format!("NaCl + Newlib doesn't impl loading shared objects"))
    }

    pub fn check_for_errors_in<T, F>(_f: F) -> Result<T, String>
        where F: FnOnce() -> T,
    {
        Err(format!("NaCl doesn't support shared objects"))
    }

    pub unsafe fn symbol(_handle: *mut u8, _symbol: *const libc::c_char) -> *mut u8 {
        ptr::null_mut()
    }
    pub unsafe fn close(_handle: *mut u8) { }
}
<|endoftext|>


<commit_before><commit_msg>Remove unit-let-binding<commit_after><|endoftext|>


<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 eutil::slice_to_str;
use libc::c_int;
use std::collections::BTreeMap;
use std::mem;
use std::string::String;
use string::{cef_string_userfree_utf16_alloc, cef_string_userfree_utf16_free};
use string::{cef_string_utf16_set};
use types::{cef_string_multimap_t,cef_string_t};

//cef_string_multimap

#[no_mangle]
pub extern "C" fn cef_string_multimap_alloc() -> *mut cef_string_multimap_t {
    unsafe {
         let smm: Box<BTreeMap<String, Vec<*mut cef_string_t>>> = box BTreeMap::new();
         mem::transmute(smm)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_size(smm: *mut cef_string_multimap_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        // t1 : collections::btree::map::Values<'_, collections::string::String, collections::vec::Vec<*mut types::cef_string_utf16>>`
        let t1 = (*smm).values();
        // t2 : collections::btree::map::BTreeMap<collections::string::String, collections::vec::Vec<*mut types::cef_string_utf16>>
        let t2 : usize = t1.map(|val| (*val).len()).sum();
        t2 as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_find_count(smm: *mut cef_string_multimap_t, key: *const cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            match (*smm).get(result) {
                Some(s) =>  s.len() as c_int,
                None => 0
            }
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_append(smm: *mut cef_string_multimap_t, key: *const cef_string_t, value: *const cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            let csv = cef_string_userfree_utf16_alloc();
            cef_string_utf16_set((*value).str as *const u16, (*value).length, csv, 1);
            match (*smm).get_mut(result) {
                Some(vc) => (*vc).push(csv),
                None => { (*smm).insert(result.to_owned(), vec!(csv)); }
            }
            1
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_enumerate(smm: *mut cef_string_multimap_t, key: *const cef_string_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            match (*smm).get(result) {
                Some(s) => {
                    if (*s).len() <= index as usize {
                        return 0;
                    }
                    let cs = (*s)[index as usize];
                    cef_string_utf16_set((*cs).str as *const u16, (*cs).length, value, 1)
                }
                None => 0
            }
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_key(smm: *mut cef_string_multimap_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || smm.is_null() { return 0; }
        let mut rem = index as usize;

        for (key, val) in (*smm).iter() {
            if rem < (*val).len() {
                return cef_string_utf16_set((*key).as_bytes().as_ptr() as *const u16,
                                            (*key).len() as u64,
                                            value,
                                            1);
            } else {
                rem -= (*val).len();
            }
        }
    }
    0
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_value(smm: *mut cef_string_multimap_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || smm.is_null() { return 0; }
        let mut rem = index as usize;

        for val in (*smm).values() {
            if rem < (*val).len() {
                let cs = (*val)[rem as usize];
                return cef_string_utf16_set((*cs).str as *const u16, (*cs).length, value, 1);
            } else {
                rem -= (*val).len();
            }
        }
    }
    0
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_clear(smm: *mut cef_string_multimap_t) {
    unsafe {
        if smm.is_null() { return; }
        if (*smm).len() == 0 { return; }
        for (_, val) in (*smm).iter_mut() {
            while (*val).len() != 0 {
                let cs = (*val).pop();
                cef_string_userfree_utf16_free(cs.unwrap());
            }
        }
        (*smm).clear();
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_free(smm: *mut cef_string_multimap_t) {
    unsafe {
        if smm.is_null() { return; }
        let v: Box<BTreeMap<String, Vec<*mut cef_string_t>>> = mem::transmute(smm);
        cef_string_multimap_clear(smm);
        drop(v);
    }
}
<commit_msg>Use the Box/boxed APIs to handle cef_string_multimap_t memory management.<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 eutil::slice_to_str;
use libc::c_int;
use std::boxed;
use std::collections::BTreeMap;
use string::{cef_string_userfree_utf16_alloc, cef_string_userfree_utf16_free};
use string::{cef_string_utf16_set};
use types::{cef_string_multimap_t,cef_string_t};

//cef_string_multimap

#[no_mangle]
pub extern "C" fn cef_string_multimap_alloc() -> *mut cef_string_multimap_t {
    boxed::into_raw(box BTreeMap::new())
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_size(smm: *mut cef_string_multimap_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        // t1 : collections::btree::map::Values<'_, collections::string::String, collections::vec::Vec<*mut types::cef_string_utf16>>`
        let t1 = (*smm).values();
        // t2 : collections::btree::map::BTreeMap<collections::string::String, collections::vec::Vec<*mut types::cef_string_utf16>>
        let t2 : usize = t1.map(|val| (*val).len()).sum();
        t2 as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_find_count(smm: *mut cef_string_multimap_t, key: *const cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            match (*smm).get(result) {
                Some(s) =>  s.len() as c_int,
                None => 0
            }
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_append(smm: *mut cef_string_multimap_t, key: *const cef_string_t, value: *const cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            let csv = cef_string_userfree_utf16_alloc();
            cef_string_utf16_set((*value).str as *const u16, (*value).length, csv, 1);
            match (*smm).get_mut(result) {
                Some(vc) => (*vc).push(csv),
                None => { (*smm).insert(result.to_owned(), vec!(csv)); }
            }
            1
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_enumerate(smm: *mut cef_string_multimap_t, key: *const cef_string_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if smm.is_null() { return 0; }
        slice_to_str((*key).str as *const u8, (*key).length as usize, |result| {
            match (*smm).get(result) {
                Some(s) => {
                    if (*s).len() <= index as usize {
                        return 0;
                    }
                    let cs = (*s)[index as usize];
                    cef_string_utf16_set((*cs).str as *const u16, (*cs).length, value, 1)
                }
                None => 0
            }
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_key(smm: *mut cef_string_multimap_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || smm.is_null() { return 0; }
        let mut rem = index as usize;

        for (key, val) in (*smm).iter() {
            if rem < (*val).len() {
                return cef_string_utf16_set((*key).as_bytes().as_ptr() as *const u16,
                                            (*key).len() as u64,
                                            value,
                                            1);
            } else {
                rem -= (*val).len();
            }
        }
    }
    0
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_value(smm: *mut cef_string_multimap_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || smm.is_null() { return 0; }
        let mut rem = index as usize;

        for val in (*smm).values() {
            if rem < (*val).len() {
                let cs = (*val)[rem as usize];
                return cef_string_utf16_set((*cs).str as *const u16, (*cs).length, value, 1);
            } else {
                rem -= (*val).len();
            }
        }
    }
    0
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_clear(smm: *mut cef_string_multimap_t) {
    unsafe {
        if smm.is_null() { return; }
        if (*smm).len() == 0 { return; }
        for (_, val) in (*smm).iter_mut() {
            while (*val).len() != 0 {
                let cs = (*val).pop();
                cef_string_userfree_utf16_free(cs.unwrap());
            }
        }
        (*smm).clear();
    }
}

#[no_mangle]
pub extern "C" fn cef_string_multimap_free(smm: *mut cef_string_multimap_t) {
    unsafe {
        if smm.is_null() { return; }
        cef_string_multimap_clear(smm);
        drop(Box::from_raw(smm));
    }
}
<|endoftext|>


<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/. */

// Implements a Quadtree data structure to keep track of which tiles have
// been rasterized and which have not.

use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect;

priv enum Quadtype {
    Empty,
    Base,
    Branch,
}

priv enum Quadrant {
    TL = 0,
    TR = 1,
    BL = 2,
    BR = 3,
}

pub struct Quadtree {
    quadtype: Quadtype,
    rect: Rect<uint>,
    quadrants: [Option<~Quadtree>, ..4],
}

impl Quadtree {
    pub fn new(x: uint, y: uint, width: uint, height: uint) -> Quadtree {
        Quadtree {
            quadtype: Empty,
            rect: Rect {
                origin: Point2D(x, y),
                size: Size2D(width, height),
            },

            quadrants: [None, None, None, None],
        }
    }

    /// Determine which child contains a given point
    priv fn get_quadrant(&self, x: uint, y: uint) -> Quadrant {
        let self_width = self.rect.size.width;
        let self_height = self.rect.size.height;
        let self_x = self.rect.origin.x;
        let self_y = self.rect.origin.y;
        match (self_width, self_height) {
            (1, _) => {
                if y < self_y + self_height / 2 {
                    TL
                } else {
                    BR
                }
            }
            (_, 1) => {
                if x < self_x + self_width / 2 {
                    TL
                } else {
                    BR
                }
            }
            _ => {
                if x < self_x + self_width / 2 {
                    if y < self_y + self_height / 2 {
                        TL
                    } else {
                        BL
                    }
                } else if y < self_y + self_height / 2 {
                    TR
                } else {
                    BR
                }
            }
        }
    }

    /// Change a point from Empty to Base
    pub fn add_region(&mut self, x: uint, y: uint) {
        let self_x = self.rect.origin.x;
        let self_y = self.rect.origin.y;
        let self_width = self.rect.size.width;
        let self_height = self.rect.size.height;

        debug!("Quadtree: adding: (%?, %?) w:%?, h:%?", self_x, self_y, self_width, self_height);

        if x >= self_x + self_width || x < self_x
            || y >= self_y + self_height || y < self_y {
            return; // Out of bounds
        }
        match self.quadtype {
            Base => return,
            Empty => {
                if self_width == 1 && self_height == 1 {
                    self.quadtype = Base;
                    return;
                }
                self.quadtype = Branch;

                // Initialize children
                self.quadrants[TL as int] = Some(~Quadtree::new(self_x,
                                                                self_y,
                                                                (self_width / 2).max(&1),
                                                                (self_height / 2).max(&1)));
                if self_width > 1 && self_height > 1 {
                    self.quadrants[TR as int] = Some(~Quadtree::new(self_x + self_width / 2,
                                                                    self_y,
                                                                    self_width - self_width / 2,
                                                                    self_height / 2));
                    self.quadrants[BL as int] = Some(~Quadtree::new(self_x,
                                                                    self_y + self_height / 2,
                                                                    self_width / 2,
                                                                    self_height - self_height / 2));
                }
                self.quadrants[BR as int] = Some(~Quadtree::new(self_x + self_width / 2,
                                                                self_y + self_height / 2,
                                                                self_width - self_width / 2,
                                                                self_height - self_height / 2));
            }
            Branch => {} // Fall through
        }

        // If we've made it this far, we know we are a branch and therefore have children
        let index = self.get_quadrant(x, y) as int;

        match self.quadrants[index] {
            None => fail!("Quadtree: child query failure"),
            Some(ref mut region) => {
                // Recurse if necessary
                match region.quadtype {
                    Empty | Branch => {
                        region.add_region(x, y);
                    }
                    Base => {} // nothing to do
                }
            }
        }

        // FIXME: ideally we could make the assignments in the match,
        // but borrowed pointers prevent that. So here's a flag instead.
        let mut base_flag = 0;

        // If all children are Bases, convert self to Base
        match (&self.quadrants, self_width, self_height) {
            (&[Some(ref tl_q), _, _, Some(ref br_q)], 1, _) |
            (&[Some(ref tl_q), _, _, Some(ref br_q)], _, 1) => {
                match(tl_q.quadtype, br_q.quadtype) {
                    (Base, Base) => {
                        base_flag = 1;
                    }
                    _ => {} // nothing to do
                }
            }
            (&[Some(ref tl_q), Some(ref tr_q), Some(ref bl_q), Some(ref br_q)], _, _) => {
                    match (tl_q.quadtype, tr_q.quadtype, bl_q.quadtype, br_q.quadtype) {
                        (Base, Base, Base, Base) => {
                            base_flag = 2;
                        }
                        _ => {} // nothing to do
                    }
            }
            _ => {} // nothing to do
        }

        match base_flag {
            0 => {}
            1 => {
                self.quadtype = Base;
                self.quadrants[TL as int] = None;
                self.quadrants[BR as int] = None;
            }
            2 => {
                self.quadtype = Base;
                self.quadrants[TL as int] = None;
                self.quadrants[TR as int] = None;
                self.quadrants[BL as int] = None;
                self.quadrants[BR as int] = None;
            }
            _ => fail!("Quadtree: Unknown flag type"),
        }
    }

    /// Check if a point is a Base or Empty.
    pub fn check_region(&self, x: uint, y: uint) -> bool {
        let self_x = self.rect.origin.x;
        let self_y = self.rect.origin.y;
        let self_width = self.rect.size.width;
        let self_height = self.rect.size.height;

        if x >= self_x + self_width || x < self_x
            || y >= self_y + self_height || y < self_y {
            return false; // out of bounds
        }

        match self.quadtype {
            Empty => false,
            Base => true,
            Branch => {
                let index = self.get_quadrant(x,y) as int;
                match self.quadrants[index] {
                    None => fail!("Quadtree: child query failed"),
                    Some(ref region) => region.check_region(x, y)
                }
            }
        }
    }

}

#[test]
fn test_add_region() {
    let mut t = Quadtree::new(50, 50, 3, 4);
    assert!(!t.check_region(50, 50));
    t.add_region(50, 50);
    assert!(t.check_region(50, 50));
    assert!(!t.check_region(51, 50));
    assert!(!t.check_region(50, 51));
    t.add_region(53, 50);
    assert!(!t.check_region(53, 50));

}<commit_msg>Make quadtrees generic<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/. */

// Implements a Quadtree data structure to keep track of which tiles have
// been rasterized and which have not.

use geom::point::Point2D;

pub struct Quadtree<T> {
    tile: Option<T>,
    origin: Point2D<f32>,
    size: f32,
    quadrants: [Option<~Quadtree<T>>, ..4],
    scale: @mut f32,
    max_tile_size: uint,
}

priv enum Quadrant {
    TL = 0,
    TR = 1,
    BL = 2,
    BR = 3,
}

impl<T> Quadtree<T> {
    // Public method to create a new Quadtree
    pub fn new(x: uint, y: uint, width: uint, height: uint, tile_size: uint, scale: @mut f32) -> Quadtree<T> {
        if(*scale != 1.0) {
            println("Warning: Quadtree: Quadtree initialized while zoomed; this action is unsupported.");
            println("Please set zoom to 1.0 before creating the Quadtree.");
        }

        // Spaces must be squares and powers of 2, so expand the space until it is
        let longer = width.max(&height);
        let num_tiles = uint::div_ceil(longer, tile_size);
        let power_of_two = uint::next_power_of_two(num_tiles);
        let size = power_of_two * tile_size;

        Quadtree {
            tile: None,
            origin: Point2D(x as f32, y as f32),
            size: size as f32,
            quadrants: [None, None, None, None],
            scale: scale,
            max_tile_size: tile_size,
        }
    }

    // Private method to create new children
    fn new_child(&self, x: f32, y: f32, size: f32) -> Quadtree<T> {
        Quadtree {
            tile: None,
            origin: Point2D(x, y),
            size: size,
            quadrants: [None, None, None, None],
            scale: self.scale,
            max_tile_size: self.max_tile_size,
        }
    }

    /// Determine which child contains a given point
    fn get_quadrant(&self, x: uint, y: uint) -> Quadrant {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        if x < self_x + self_size / 2 {
            if y < self_y + self_size / 2 {
                TL
            } else {
                BL
            }
        } else if y < self_y + self_size / 2 {
            TR
        } else {
            BR
        }
    }

    /// Get the lowest-level (highest resolution) tile associated with a certain pixel
    pub fn get_tile<'r> (&'r self, x: uint, y: uint) -> &'r Option<T> {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        if x >= self_x + self_size || x < self_x
            || y >= self_y + self_size || y < self_y {
            fail!("Quadtree: Tried to get a tile outside of range");
        }

        let index = self.get_quadrant(x,y) as int;
        match self.quadrants[index] {
            None => &'r self.tile,
            Some(ref child) => child.get_tile(x, y),
        }
    }

    /// Add a tile
    pub fn add_tile(&mut self, x: uint, y: uint, tile: T) {
        let self_x = (self.origin.x * *(self.scale)).ceil() as uint;
        let self_y = (self.origin.y * *(self.scale)).ceil() as uint;
        let self_size = (self.size * *(self.scale)).ceil() as uint;

        debug!("Quadtree: Adding: (%?, %?) size:%?px", self_x, self_y, self_size);

        if x >= self_x + self_size || x < self_x
            || y >= self_y + self_size || y < self_y {
            fail!("Quadtree: Tried to add tile to invalid region");
        }

        if self_size <= self.max_tile_size { // We are the child
            self.tile = Some(tile);
            for vec::each([TL, TR, BL, BR]) |quad| {
                self.quadrants[*quad as int] = None;
            }
        } else { //send tile to children
            let quad = self.get_quadrant(x, y);
            match self.quadrants[quad as int] {
                Some(ref mut child) => child.add_tile(x, y, tile),
                None => { //make new child
                    let new_size = self.size / 2.0;
                    let new_x = match quad {
                        TL | BL => self.origin.x,
                        TR | BR => self.origin.x + new_size,
                    };
                    let new_y = match quad {
                        TL | TR => self.origin.y,
                        BL | BR => self.origin.y + new_size,
                    };
                    let mut c = ~self.new_child(new_x, new_y, new_size);
                    c.add_tile(x, y, tile);
                    self.quadrants[quad as int] = Some(c);

                    // If we have 4 children, we probably shouldn't be hanging onto a tile
                    // Though this isn't always true if we have grandchildren
                    match self.quadrants {
                        [Some(_), Some(_), Some(_), Some(_)] => {
                            self.tile = None;
                        }
                        _ => {}
                    }

                }
            }
        }
    }

}

#[test]
fn test_add_tile() {
    let scale = @mut 1.0;
    let mut t = Quadtree::new(50, 30, 20, 20, 10, scale);
    assert!(t.get_tile(50, 30).is_none());
    t.add_tile(50, 30, 1);
    assert!(t.get_tile(50, 30).get() == 1);
    assert!(t.get_tile(59, 39).get() == 1);
    assert!(t.get_tile(60, 40).is_none());
    *scale = 2.0;
    assert!(t.get_tile(110, 70).get() == 1);
    t.add_tile(100, 60, 2);
    assert!(t.get_tile(109, 69).get() == 2);
    assert!(t.get_tile(110, 70).get() == 1);
}<|endoftext|>


<commit_before><commit_msg>Comment the Vulkan validation layer warnings relating to uninitialised depth buffers for the swapchain<commit_after><|endoftext|>


<commit_before><commit_msg>Shuffle code/refactor a bit<commit_after><|endoftext|>


<commit_before><commit_msg>Update (8 kyu) altERnaTIng cAsE = ALTerNAtiNG CaSe.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Add workaround for doc bug<commit_after><|endoftext|>


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

use lib::llvm::llvm;
use lib::llvm::{TypeRef};
use middle::trans::common::*;
use middle::trans::common;
use middle::trans::expr;
use util::ppaux;

use std::map::HashMap;
use syntax::ast;

export type_of;
export type_of_dtor;
export type_of_explicit_arg;
export type_of_explicit_args;
export type_of_fn_from_ty;
export type_of_fn;
export type_of_glue_fn;
export type_of_non_gc_box;
export type_of_rooted;

fn type_of_explicit_arg(ccx: @crate_ctxt, arg: ty::arg) -> TypeRef {
    let llty = type_of(ccx, arg.ty);
    match ty::resolved_mode(ccx.tcx, arg.mode) {
        ast::by_val => llty,
        ast::by_copy | ast::by_move => {
            if ty::type_is_immediate(arg.ty) {
                llty
            } else {
                T_ptr(llty)
            }
        }
        _ => T_ptr(llty)
    }
}

fn type_of_explicit_args(ccx: @crate_ctxt, inputs: ~[ty::arg]) -> ~[TypeRef] {
    inputs.map(|arg| type_of_explicit_arg(ccx, *arg))
}

fn type_of_fn(cx: @crate_ctxt, inputs: ~[ty::arg],
              output: ty::t) -> TypeRef {
    let mut atys: ~[TypeRef] = ~[];

    // Arg 0: Output pointer.
    atys.push(T_ptr(type_of(cx, output)));

    // Arg 1: Environment
    atys.push(T_opaque_box_ptr(cx));

    // ... then explicit args.
    atys.push_all(type_of_explicit_args(cx, inputs));
    return T_fn(atys, llvm::LLVMVoidType());
}

// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
}

fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    assert !ty::type_needs_infer(t);

    let t_norm = ty::normalize_ty(cx.tcx, t);
    if t != t_norm {
        type_of_non_gc_box(cx, t_norm)
    } else {
        match ty::get(t).sty {
          ty::ty_box(mt) => {
            T_ptr(T_box(cx, type_of(cx, mt.ty)))
          }
          ty::ty_uniq(mt) => {
            T_ptr(T_unique(cx, type_of(cx, mt.ty)))
          }
          _ => {
            cx.sess.bug(~"non-box in type_of_non_gc_box");
          }
        }
    }
}

fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    debug!("type_of %?: %?", t, ty::get(t));

    // Check the cache.
    if cx.lltypes.contains_key(t) { return cx.lltypes.get(t); }

    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `option<{myfield: bool}>` would be a different
    // type than `option<myrec>`.
    let t_norm = ty::normalize_ty(cx.tcx, t);

    if t != t_norm {
        let llty = type_of(cx, t_norm);
        cx.lltypes.insert(t, llty);
        return llty;
    }

    let llty = match ty::get(t).sty {
      ty::ty_nil | ty::ty_bot => T_nil(),
      ty::ty_bool => T_bool(),
      ty::ty_int(t) => T_int_ty(cx, t),
      ty::ty_uint(t) => T_uint_ty(cx, t),
      ty::ty_float(t) => T_float_ty(cx, t),
      ty::ty_estr(ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
      }
      ty::ty_enum(did, ref substs) => {
        // Only create the named struct, but don't fill it in. We
        // fill it in *after* placing it into the type cache. This
        // avoids creating more than one copy of the enum when one
        // of the enum's variants refers to the enum itself.

        common::T_named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
      }
      ty::ty_estr(ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
      }
      ty::ty_evec(mt, ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_box(mt) => T_box_ptr(T_box(cx, type_of(cx, mt.ty))),
      ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
      ty::ty_uniq(mt) => T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))),
      ty::ty_evec(mt, ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_unboxed_vec(mt) => {
        T_vec(cx, type_of(cx, mt.ty))
      }
      ty::ty_ptr(mt) => T_ptr(type_of(cx, mt.ty)),
      ty::ty_rptr(_, mt) => T_ptr(type_of(cx, mt.ty)),

      ty::ty_evec(mt, ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(type_of(cx, mt.ty)),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(T_i8()),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_fixed(n)) => {
        T_array(T_i8(), n + 1u /* +1 for trailing null */)
      }

      ty::ty_evec(mt, ty::vstore_fixed(n)) => {
        T_array(type_of(cx, mt.ty), n)
      }

      ty::ty_rec(fields) => {
        let mut tys: ~[TypeRef] = ~[];
        for vec::each(fields) |f| {
            let mt_ty = f.mt.ty;
            tys.push(type_of(cx, mt_ty));
        }

        // n.b.: introduce an extra layer of indirection to match
        // structs
        T_struct(~[T_struct(tys)])
      }
      ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
      ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
      ty::ty_type => T_ptr(cx.tydesc_type),
      ty::ty_tup(elts) => {
        let mut tys = ~[];
        for vec::each(elts) |elt| {
            tys.push(type_of(cx, *elt));
        }
        T_struct(tys)
      }
      ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
      ty::ty_struct(did, ref substs) => {
        // Only create the named struct, but don't fill it in. We fill it
        // in *after* placing it into the type cache. This prevents
        // infinite recursion with recursive struct types.

        common::T_named_struct(llvm_type_name(cx, a_struct, did, substs.tps))
      }
      ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
      ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"),
      ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
      ty::ty_err(*) => cx.tcx.sess.bug(~"type_of with ty_err")
    };

    cx.lltypes.insert(t, llty);

    // If this was an enum or struct, fill in the type now.
    match ty::get(t).sty {
      ty::ty_enum(did, _) => {
        fill_type_of_enum(cx, did, t, llty);
      }
      ty::ty_struct(did, ref substs) => {
        // Only instance vars are record fields at runtime.
        let fields = ty::lookup_struct_fields(cx.tcx, did);
        let mut tys = do vec::map(fields) |f| {
            let t = ty::lookup_field_type(cx.tcx, did, f.id, substs);
            type_of(cx, t)
        };

        // include a byte flag if there is a dtor so that we know when we've
        // been dropped
        if ty::ty_dtor(cx.tcx, did).is_present() {
            common::set_struct_body(llty, ~[T_struct(tys), T_i8()]);
        } else {
            common::set_struct_body(llty, ~[T_struct(tys)]);
        }
      }
      _ => ()
    }

    return llty;
}

fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
                     llty: TypeRef) {

    debug!("type_of_enum %?: %?", t, ty::get(t));

    let lltys = {
        let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
        let size = shape::static_size_of_enum(cx, t);
        if !degen {
            ~[T_enum_discrim(cx), T_array(T_i8(), size)]
        }
        else if size == 0u {
            ~[T_enum_discrim(cx)]
        }
        else {
            ~[T_array(T_i8(), size)]
        }
    };

    common::set_struct_body(llty, lltys);
}

// Want refinements! (Or case classes, I guess
enum named_ty { a_struct, an_enum }

fn llvm_type_name(cx: @crate_ctxt,
                  what: named_ty,
                  did: ast::def_id,
                  tps: ~[ty::t]
                  ) -> ~str {
    let name = match what {
        a_struct => { "~struct" }
        an_enum => { "~enum" }
    };
    return fmt!(
        "%s %s[#%d]",
          name,
        ppaux::parameterized(
            cx.tcx,
            ty::item_path_str(cx.tcx, did),
            None,
            tps),
        did.crate
    );
}

fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
    T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer
           T_ptr(type_of(ccx, self_ty))],            // self arg
         llvm::LLVMVoidType())
}

fn type_of_rooted(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
    let addrspace = base::get_tydesc(ccx, t).addrspace;
    debug!("type_of_rooted %s in addrspace %u",
           ty_to_str(ccx.tcx, t), addrspace as uint);
    return T_root(type_of(ccx, t), addrspace);
}

fn type_of_glue_fn(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
    let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
    let llty = T_ptr(type_of(ccx, t));
    return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty],
                T_void());
}
<commit_msg>Trivial cleanup: use enum_is_univariant; no functional change intended.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use lib::llvm::llvm;
use lib::llvm::{TypeRef};
use middle::trans::common::*;
use middle::trans::common;
use middle::trans::expr;
use util::ppaux;

use std::map::HashMap;
use syntax::ast;

export type_of;
export type_of_dtor;
export type_of_explicit_arg;
export type_of_explicit_args;
export type_of_fn_from_ty;
export type_of_fn;
export type_of_glue_fn;
export type_of_non_gc_box;
export type_of_rooted;

fn type_of_explicit_arg(ccx: @crate_ctxt, arg: ty::arg) -> TypeRef {
    let llty = type_of(ccx, arg.ty);
    match ty::resolved_mode(ccx.tcx, arg.mode) {
        ast::by_val => llty,
        ast::by_copy | ast::by_move => {
            if ty::type_is_immediate(arg.ty) {
                llty
            } else {
                T_ptr(llty)
            }
        }
        _ => T_ptr(llty)
    }
}

fn type_of_explicit_args(ccx: @crate_ctxt, inputs: ~[ty::arg]) -> ~[TypeRef] {
    inputs.map(|arg| type_of_explicit_arg(ccx, *arg))
}

fn type_of_fn(cx: @crate_ctxt, inputs: ~[ty::arg],
              output: ty::t) -> TypeRef {
    let mut atys: ~[TypeRef] = ~[];

    // Arg 0: Output pointer.
    atys.push(T_ptr(type_of(cx, output)));

    // Arg 1: Environment
    atys.push(T_opaque_box_ptr(cx));

    // ... then explicit args.
    atys.push_all(type_of_explicit_args(cx, inputs));
    return T_fn(atys, llvm::LLVMVoidType());
}

// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
}

fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    assert !ty::type_needs_infer(t);

    let t_norm = ty::normalize_ty(cx.tcx, t);
    if t != t_norm {
        type_of_non_gc_box(cx, t_norm)
    } else {
        match ty::get(t).sty {
          ty::ty_box(mt) => {
            T_ptr(T_box(cx, type_of(cx, mt.ty)))
          }
          ty::ty_uniq(mt) => {
            T_ptr(T_unique(cx, type_of(cx, mt.ty)))
          }
          _ => {
            cx.sess.bug(~"non-box in type_of_non_gc_box");
          }
        }
    }
}

fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    debug!("type_of %?: %?", t, ty::get(t));

    // Check the cache.
    if cx.lltypes.contains_key(t) { return cx.lltypes.get(t); }

    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `option<{myfield: bool}>` would be a different
    // type than `option<myrec>`.
    let t_norm = ty::normalize_ty(cx.tcx, t);

    if t != t_norm {
        let llty = type_of(cx, t_norm);
        cx.lltypes.insert(t, llty);
        return llty;
    }

    let llty = match ty::get(t).sty {
      ty::ty_nil | ty::ty_bot => T_nil(),
      ty::ty_bool => T_bool(),
      ty::ty_int(t) => T_int_ty(cx, t),
      ty::ty_uint(t) => T_uint_ty(cx, t),
      ty::ty_float(t) => T_float_ty(cx, t),
      ty::ty_estr(ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
      }
      ty::ty_enum(did, ref substs) => {
        // Only create the named struct, but don't fill it in. We
        // fill it in *after* placing it into the type cache. This
        // avoids creating more than one copy of the enum when one
        // of the enum's variants refers to the enum itself.

        common::T_named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
      }
      ty::ty_estr(ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
      }
      ty::ty_evec(mt, ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_box(mt) => T_box_ptr(T_box(cx, type_of(cx, mt.ty))),
      ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
      ty::ty_uniq(mt) => T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))),
      ty::ty_evec(mt, ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_unboxed_vec(mt) => {
        T_vec(cx, type_of(cx, mt.ty))
      }
      ty::ty_ptr(mt) => T_ptr(type_of(cx, mt.ty)),
      ty::ty_rptr(_, mt) => T_ptr(type_of(cx, mt.ty)),

      ty::ty_evec(mt, ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(type_of(cx, mt.ty)),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(T_i8()),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_fixed(n)) => {
        T_array(T_i8(), n + 1u /* +1 for trailing null */)
      }

      ty::ty_evec(mt, ty::vstore_fixed(n)) => {
        T_array(type_of(cx, mt.ty), n)
      }

      ty::ty_rec(fields) => {
        let mut tys: ~[TypeRef] = ~[];
        for vec::each(fields) |f| {
            let mt_ty = f.mt.ty;
            tys.push(type_of(cx, mt_ty));
        }

        // n.b.: introduce an extra layer of indirection to match
        // structs
        T_struct(~[T_struct(tys)])
      }
      ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
      ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
      ty::ty_type => T_ptr(cx.tydesc_type),
      ty::ty_tup(elts) => {
        let mut tys = ~[];
        for vec::each(elts) |elt| {
            tys.push(type_of(cx, *elt));
        }
        T_struct(tys)
      }
      ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
      ty::ty_struct(did, ref substs) => {
        // Only create the named struct, but don't fill it in. We fill it
        // in *after* placing it into the type cache. This prevents
        // infinite recursion with recursive struct types.

        common::T_named_struct(llvm_type_name(cx, a_struct, did, substs.tps))
      }
      ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
      ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"),
      ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
      ty::ty_err(*) => cx.tcx.sess.bug(~"type_of with ty_err")
    };

    cx.lltypes.insert(t, llty);

    // If this was an enum or struct, fill in the type now.
    match ty::get(t).sty {
      ty::ty_enum(did, _) => {
        fill_type_of_enum(cx, did, t, llty);
      }
      ty::ty_struct(did, ref substs) => {
        // Only instance vars are record fields at runtime.
        let fields = ty::lookup_struct_fields(cx.tcx, did);
        let mut tys = do vec::map(fields) |f| {
            let t = ty::lookup_field_type(cx.tcx, did, f.id, substs);
            type_of(cx, t)
        };

        // include a byte flag if there is a dtor so that we know when we've
        // been dropped
        if ty::ty_dtor(cx.tcx, did).is_present() {
            common::set_struct_body(llty, ~[T_struct(tys), T_i8()]);
        } else {
            common::set_struct_body(llty, ~[T_struct(tys)]);
        }
      }
      _ => ()
    }

    return llty;
}

fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
                     llty: TypeRef) {

    debug!("type_of_enum %?: %?", t, ty::get(t));

    let lltys = {
        let degen = ty::enum_is_univariant(cx.tcx, did);
        let size = shape::static_size_of_enum(cx, t);
        if !degen {
            ~[T_enum_discrim(cx), T_array(T_i8(), size)]
        }
        else if size == 0u {
            ~[T_enum_discrim(cx)]
        }
        else {
            ~[T_array(T_i8(), size)]
        }
    };

    common::set_struct_body(llty, lltys);
}

// Want refinements! (Or case classes, I guess
enum named_ty { a_struct, an_enum }

fn llvm_type_name(cx: @crate_ctxt,
                  what: named_ty,
                  did: ast::def_id,
                  tps: ~[ty::t]
                  ) -> ~str {
    let name = match what {
        a_struct => { "~struct" }
        an_enum => { "~enum" }
    };
    return fmt!(
        "%s %s[#%d]",
          name,
        ppaux::parameterized(
            cx.tcx,
            ty::item_path_str(cx.tcx, did),
            None,
            tps),
        did.crate
    );
}

fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
    T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer
           T_ptr(type_of(ccx, self_ty))],            // self arg
         llvm::LLVMVoidType())
}

fn type_of_rooted(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
    let addrspace = base::get_tydesc(ccx, t).addrspace;
    debug!("type_of_rooted %s in addrspace %u",
           ty_to_str(ccx.tcx, t), addrspace as uint);
    return T_root(type_of(ccx, t), addrspace);
}

fn type_of_glue_fn(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
    let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
    let llty = T_ptr(type_of(ccx, t));
    return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty],
                T_void());
}
<|endoftext|>


<commit_before><commit_msg>Skeleton for problem 2305<commit_after>// https://leetcode.com/problems/fair-distribution-of-cookies/
pub fn distribute_cookies(cookies: Vec<i32>, k: i32) -> i32 {
    todo!()
}

fn main() {
    println!("{}", distribute_cookies(vec![8, 15, 10, 20, 8], 2)); // 31
    println!("{}", distribute_cookies(vec![6, 1, 3, 2, 2, 4, 1, 3], 2)); // 7
}
<|endoftext|>


<commit_before><commit_msg>Add inline const macro test<commit_after>// run-pass

#![allow(incomplete_features)]
#![feature(inline_const)]
macro_rules! do_const_block{
    ($val:block) => { const $val }
}

fn main() {
    let s = do_const_block!({ 22 });
    assert_eq!(s, 22);
}
<|endoftext|>


<commit_before><commit_msg>Add Rust fibonacci<commit_after><|endoftext|>


<commit_before>import driver::session;

import option::{none, some};

import syntax::ast::{crate, expr_, expr_mac, mac_invoc,
                     mac_qq, mac_aq, mac_var};
import syntax::fold::*;
import syntax::visit::*;
import syntax::ext::base::*;
import syntax::ext::build::*;
import syntax::parse::parser::parse_expr_from_source_str;

import syntax::print::*;
import std::io::*;

import codemap::span;

type aq_ctxt = @{lo: uint,
                 mutable gather: [{lo: uint, hi: uint, e: @ast::expr}]};

fn gather_anti_quotes(lo: uint, e: @ast::expr) -> aq_ctxt
{
    let v = @{visit_expr: visit_expr_aq
              with *default_visitor()};
    let cx = @{lo:lo, mutable gather: []};
    visit_expr_aq(e, cx, mk_vt(v));
    ret cx;
}

fn visit_expr_aq(expr: @ast::expr, &&cx: aq_ctxt, v: vt<aq_ctxt>)
{
    alt (expr.node) {
      expr_mac({node: mac_aq(sp, e), _}) {
        cx.gather += [{lo: sp.lo - cx.lo, hi: sp.hi - cx.lo,
                       e: e}];
      }
      _ {visit_expr(expr, cx, v);}
    }
}

fn expand_qquote(ecx: ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
    let str = codemap::span_to_snippet(sp, ecx.session().parse_sess.cm);
    let qcx = gather_anti_quotes(sp.lo, e);
    let cx = qcx;
    let prev = 0u;
    for {lo: lo, _} in cx.gather {
        assert lo > prev;
        prev = lo;
    }
    let str2 = "";
    let active = true;
    let i = 0u, j = 0u;
    let g_len = vec::len(cx.gather);
    str::chars_iter(str) {|ch|
        if (active && j < g_len && i == cx.gather[j].lo) {
            assert ch == '$';
            active = false;
            str2 += #fmt(" $%u ", j);
        }
        if (active) {str::push_char(str2, ch);}
        i += 1u;
        if (!active && j < g_len && i == cx.gather[j].hi) {
            assert ch == ')';
            active = true;
            j += 1u;
        }
    }

    let cx = ecx;
    let session_call = bind mk_call_(cx,sp,
                                     mk_access(cx,sp,["ext_cx"], "session"),
                                     []);
    let pcall = mk_call(cx,sp,
                       ["syntax", "parse", "parser",
                        "parse_expr_from_source_str"],
                       [mk_str(cx,sp, "<anon>"),
                        mk_unary(cx,sp, ast::box(ast::imm),
                                 mk_str(cx,sp, str2)),
                        mk_access_(cx,sp,
                                   mk_access_(cx,sp, session_call(), "opts"),
                                   "cfg"),
                        mk_access_(cx,sp, session_call(), "parse_sess")]
                      );
    let rcall = pcall;
    if (g_len > 0u) {
        rcall = mk_call(cx,sp,
                        ["syntax", "ext", "qquote", "replace"],
                        [pcall,
                         mk_vec_e(cx,sp, vec::map(qcx.gather, {|g| g.e}))]);
    }

    ret rcall;
}

fn replace(e: @ast::expr, repls: [@ast::expr]) -> @ast::expr {
    let aft = default_ast_fold();
    let f_pre = {fold_expr: bind replace_expr(repls, _, _, _,
                                              aft.fold_expr)
                 with *aft};
    let f = make_fold(f_pre);
    ret f.fold_expr(e);
}

fn replace_expr(repls: [@ast::expr],
                e: ast::expr_, s: span, fld: ast_fold,
                orig: fn@(ast::expr_, span, ast_fold)->(ast::expr_, span))
    -> (ast::expr_, span)
{
    alt e {
      expr_mac({node: mac_var(i), _}) {let r = repls[i]; (r.node, r.span)}
      _ {orig(e,s,fld)}
    }
}

fn print_expr(expr: @ast::expr) {
    let stdout = std::io::stdout();
    let pp = pprust::rust_printer(stdout);
    pprust::print_expr(pp, expr);
    pp::eof(pp.s);
    stdout.write_str("\n");
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>When replacing $(...) with $0 preserve spacing for better error messages.<commit_after>import driver::session;

import option::{none, some};

import syntax::ast::{crate, expr_, expr_mac, mac_invoc,
                     mac_qq, mac_aq, mac_var};
import syntax::fold::*;
import syntax::visit::*;
import syntax::ext::base::*;
import syntax::ext::build::*;
import syntax::parse::parser::parse_expr_from_source_str;

import syntax::print::*;
import std::io::*;

import codemap::span;

type aq_ctxt = @{lo: uint,
                 mutable gather: [{lo: uint, hi: uint, e: @ast::expr}]};

fn gather_anti_quotes(lo: uint, e: @ast::expr) -> aq_ctxt
{
    let v = @{visit_expr: visit_expr_aq
              with *default_visitor()};
    let cx = @{lo:lo, mutable gather: []};
    visit_expr_aq(e, cx, mk_vt(v));
    ret cx;
}

fn visit_expr_aq(expr: @ast::expr, &&cx: aq_ctxt, v: vt<aq_ctxt>)
{
    alt (expr.node) {
      expr_mac({node: mac_aq(sp, e), _}) {
        cx.gather += [{lo: sp.lo - cx.lo, hi: sp.hi - cx.lo,
                       e: e}];
      }
      _ {visit_expr(expr, cx, v);}
    }
}

fn is_space(c: char) -> bool {
    syntax::parse::lexer::is_whitespace(c)
}

fn expand_qquote(ecx: ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
    let str = codemap::span_to_snippet(sp, ecx.session().parse_sess.cm);
    let qcx = gather_anti_quotes(sp.lo, e);
    let cx = qcx;
    let prev = 0u;
    for {lo: lo, _} in cx.gather {
        assert lo > prev;
        prev = lo;
    }
    let str2 = "";
    enum state {active, skip(uint), blank};
    let state = active;
    let i = 0u, j = 0u;
    let g_len = vec::len(cx.gather);
    str::chars_iter(str) {|ch|
        if (j < g_len && i == cx.gather[j].lo) {
            assert ch == '$';
            let repl = #fmt("$%u ", j);
            state = skip(str::char_len(repl));
            str2 += repl;
        }
        alt state {
          active {str::push_char(str2, ch);}
          skip(1u) {state = blank;}
          skip(sk) {state = skip (sk-1u);}
          blank if is_space(ch) {str::push_char(str2, ch);}
          blank {str::push_char(str2, ' ');}
        }
        i += 1u;
        if (j < g_len && i == cx.gather[j].hi) {
            assert ch == ')';
            state = active;
            j += 1u;
        }
    }

    let cx = ecx;
    let session_call = bind mk_call_(cx,sp,
                                     mk_access(cx,sp,["ext_cx"], "session"),
                                     []);
    let pcall = mk_call(cx,sp,
                       ["syntax", "parse", "parser",
                        "parse_expr_from_source_str"],
                       [mk_str(cx,sp, "<anon>"),
                        mk_unary(cx,sp, ast::box(ast::imm),
                                 mk_str(cx,sp, str2)),
                        mk_access_(cx,sp,
                                   mk_access_(cx,sp, session_call(), "opts"),
                                   "cfg"),
                        mk_access_(cx,sp, session_call(), "parse_sess")]
                      );
    let rcall = pcall;
    if (g_len > 0u) {
        rcall = mk_call(cx,sp,
                        ["syntax", "ext", "qquote", "replace"],
                        [pcall,
                         mk_vec_e(cx,sp, vec::map(qcx.gather, {|g| g.e}))]);
    }

    ret rcall;
}

fn replace(e: @ast::expr, repls: [@ast::expr]) -> @ast::expr {
    let aft = default_ast_fold();
    let f_pre = {fold_expr: bind replace_expr(repls, _, _, _,
                                              aft.fold_expr)
                 with *aft};
    let f = make_fold(f_pre);
    ret f.fold_expr(e);
}

fn replace_expr(repls: [@ast::expr],
                e: ast::expr_, s: span, fld: ast_fold,
                orig: fn@(ast::expr_, span, ast_fold)->(ast::expr_, span))
    -> (ast::expr_, span)
{
    alt e {
      expr_mac({node: mac_var(i), _}) {let r = repls[i]; (r.node, r.span)}
      _ {orig(e,s,fld)}
    }
}

fn print_expr(expr: @ast::expr) {
    let stdout = std::io::stdout();
    let pp = pprust::rust_printer(stdout);
    pprust::print_expr(pp, expr);
    pp::eof(pp.s);
    stdout.write_str("\n");
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before><commit_msg>Add test case for issue #11681<commit_after>// Copyright 2014 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.

// This tests verifies that unary structs and enum variants
// are treated as rvalues and their lifetime is not bounded to
// the static scope.

struct Test;

impl Drop for Test {
    fn drop (&mut self) {}
}

fn createTest() -> &Test {
  let testValue = &Test; //~ ERROR borrowed value does not live long enough
  return testValue;
}

pub fn main() {
    createTest();
}
<|endoftext|>