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

use bsdf::{BSDF, BxDF, Fresnel, TrowbridgeReitzDistribution, MicrofacetReflection};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use spectrum::Spectrum;
use texture::{Texture, ConstantTexture};

pub struct Metal {
    eta: Box<Texture<Spectrum> + Send + Sync>,
    k: Box<Texture<Spectrum> + Send + Sync>,
    rough: Box<Texture<f32> + Send + Sync>,
    // urough: Box<Texture<f32>>,
    // vrough: Box<Texture<f32>>,
    remap_roughness: bool,
}

impl Metal {
    pub fn new() -> Self {
        Metal {
            eta: Box::new(ConstantTexture::new(Spectrum::from_sampled(&COPPER_WAVELENGTHS[..],
                                                                      &COPPER_N[..],
                                                                      COPPER_SAMPLES))),
            k: Box::new(ConstantTexture::new(Spectrum::from_sampled(&COPPER_WAVELENGTHS[..],
                                                                    &COPPER_K[..],
                                                                    COPPER_SAMPLES))),
            rough: Box::new(ConstantTexture::new(0.01)),
            // urough: Box::new(ConstantTexture::new(...)),
            // vrough: Box::new(ConstantTexture::new(...)),
            remap_roughness: true,
        }
    }
}

impl Material for Metal {
    fn compute_scattering_functions(&self,
                                    si: &mut SurfaceInteraction,
                                    mode: TransportMode,
                                    allow_multiple_lobes: bool) {
        let mut bxdfs: Vec<Box<BxDF + Send + Sync>> = Vec::new();
        let mut rough = self.rough.evaluate(si);
        if self.remap_roughness {
            rough = TrowbridgeReitzDistribution::roughness_to_alpha(rough);
        }
        let fresnel = Box::new(Fresnel::conductor(Spectrum::white(),
                                                  self.eta.evaluate(si),
                                                  self.k.evaluate(si)));
        let distrib = Box::new(TrowbridgeReitzDistribution::new(rough, rough));
        bxdfs.push(Box::new(MicrofacetReflection::new(Spectrum::white(), distrib, fresnel)));

        let bsdf = BSDF::new(si, 1.0, bxdfs);
        si.bsdf = Some(Arc::new(bsdf));
    }
}

const COPPER_SAMPLES: usize = 56;
const COPPER_WAVELENGTHS: [f32; COPPER_SAMPLES] = [298.7570554,
                                                   302.4004341,
                                                   306.1337728,
                                                   309.960445,
                                                   313.8839949,
                                                   317.9081487,
                                                   322.036826,
                                                   326.2741526,
                                                   330.6244747,
                                                   335.092373,
                                                   339.6826795,
                                                   344.4004944,
                                                   349.2512056,
                                                   354.2405086,
                                                   359.374429,
                                                   364.6593471,
                                                   370.1020239,
                                                   375.7096303,
                                                   381.4897785,
                                                   387.4505563,
                                                   393.6005651,
                                                   399.9489613,
                                                   406.5055016,
                                                   413.2805933,
                                                   420.2853492,
                                                   427.5316483,
                                                   435.0322035,
                                                   442.8006357,
                                                   450.8515564,
                                                   459.2006593,
                                                   467.8648226,
                                                   476.8622231,
                                                   486.2124627,
                                                   495.936712,
                                                   506.0578694,
                                                   516.6007417,
                                                   527.5922468,
                                                   539.0616435,
                                                   551.0407911,
                                                   563.5644455,
                                                   576.6705953,
                                                   590.4008476,
                                                   604.8008683,
                                                   619.92089,
                                                   635.8162974,
                                                   652.5483053,
                                                   670.1847459,
                                                   688.8009889,
                                                   708.4810171,
                                                   729.3186941,
                                                   751.4192606,
                                                   774.9011125,
                                                   799.8979226,
                                                   826.5611867,
                                                   855.0632966,
                                                   885.6012714];

const COPPER_N: [f32; COPPER_SAMPLES] =
    [1.400313, 1.38, 1.358438, 1.34, 1.329063, 1.325, 1.3325, 1.34, 1.334375, 1.325, 1.317812,
     1.31, 1.300313, 1.29, 1.281563, 1.27, 1.249062, 1.225, 1.2, 1.18, 1.174375, 1.175, 1.1775,
     1.18, 1.178125, 1.175, 1.172812, 1.17, 1.165312, 1.16, 1.155312, 1.15, 1.142812, 1.135,
     1.131562, 1.12, 1.092437, 1.04, 0.950375, 0.826, 0.645875, 0.468, 0.35125, 0.272, 0.230813,
     0.214, 0.20925, 0.213, 0.21625, 0.223, 0.2365, 0.25, 0.254188, 0.26, 0.28, 0.3];

const COPPER_K: [f32; COPPER_SAMPLES] =
    [1.662125, 1.687, 1.703313, 1.72, 1.744563, 1.77, 1.791625, 1.81, 1.822125, 1.834, 1.85175,
     1.872, 1.89425, 1.916, 1.931688, 1.95, 1.972438, 2.015, 2.121562, 2.21, 2.177188, 2.13,
     2.160063, 2.21, 2.249938, 2.289, 2.326, 2.362, 2.397625, 2.433, 2.469187, 2.504, 2.535875,
     2.564, 2.589625, 2.605, 2.595562, 2.583, 2.5765, 2.599, 2.678062, 2.809, 3.01075, 3.24,
     3.458187, 3.67, 3.863125, 4.05, 4.239563, 4.43, 4.619563, 4.817, 5.034125, 5.26, 5.485625,
     5.717];
<commit_msg>Add SPD for gold until reading from file is supported<commit_after>use std::sync::Arc;

use bsdf::{BSDF, BxDF, Fresnel, TrowbridgeReitzDistribution, MicrofacetReflection};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use spectrum::Spectrum;
use texture::{Texture, ConstantTexture};

pub struct Metal {
    eta: Box<Texture<Spectrum> + Send + Sync>,
    k: Box<Texture<Spectrum> + Send + Sync>,
    rough: Box<Texture<f32> + Send + Sync>,
    // urough: Box<Texture<f32>>,
    // vrough: Box<Texture<f32>>,
    remap_roughness: bool,
}

impl Metal {
    pub fn new() -> Self {
        Metal {
            eta: Box::new(ConstantTexture::new(Spectrum::from_sampled(&COPPER_WAVELENGTHS[..],
                                                                      &COPPER_N[..],
                                                                      COPPER_SAMPLES))),
            k: Box::new(ConstantTexture::new(Spectrum::from_sampled(&COPPER_WAVELENGTHS[..],
                                                                    &COPPER_K[..],
                                                                    COPPER_SAMPLES))),
            rough: Box::new(ConstantTexture::new(0.01)),
            // urough: Box::new(ConstantTexture::new(...)),
            // vrough: Box::new(ConstantTexture::new(...)),
            remap_roughness: true,
        }
    }

    pub fn gold() -> Self {
        Metal {
            eta: Box::new(ConstantTexture::new(Spectrum::from_sampled(&AU_WAVELENGTHS[..],
                                                                      &AU_N[..],
                                                                      AU_SAMPLES))),
            k: Box::new(ConstantTexture::new(Spectrum::from_sampled(&AU_WAVELENGTHS[..],
                                                                    &AU_K[..],
                                                                    AU_SAMPLES))),
            rough: Box::new(ConstantTexture::new(0.01)),
            // urough: Box::new(ConstantTexture::new(...)),
            // vrough: Box::new(ConstantTexture::new(...)),
            remap_roughness: true,
        }
    }
}

impl Material for Metal {
    fn compute_scattering_functions(&self,
                                    si: &mut SurfaceInteraction,
                                    mode: TransportMode,
                                    allow_multiple_lobes: bool) {
        let mut bxdfs: Vec<Box<BxDF + Send + Sync>> = Vec::new();
        let mut rough = self.rough.evaluate(si);
        if self.remap_roughness {
            rough = TrowbridgeReitzDistribution::roughness_to_alpha(rough);
        }
        let fresnel = Box::new(Fresnel::conductor(Spectrum::white(),
                                                  self.eta.evaluate(si),
                                                  self.k.evaluate(si)));
        let distrib = Box::new(TrowbridgeReitzDistribution::new(rough, rough));
        bxdfs.push(Box::new(MicrofacetReflection::new(Spectrum::white(), distrib, fresnel)));

        let bsdf = BSDF::new(si, 1.0, bxdfs);
        si.bsdf = Some(Arc::new(bsdf));
    }
}

const COPPER_SAMPLES: usize = 56;
const COPPER_WAVELENGTHS: [f32; COPPER_SAMPLES] = [298.7570554,
                                                   302.4004341,
                                                   306.1337728,
                                                   309.960445,
                                                   313.8839949,
                                                   317.9081487,
                                                   322.036826,
                                                   326.2741526,
                                                   330.6244747,
                                                   335.092373,
                                                   339.6826795,
                                                   344.4004944,
                                                   349.2512056,
                                                   354.2405086,
                                                   359.374429,
                                                   364.6593471,
                                                   370.1020239,
                                                   375.7096303,
                                                   381.4897785,
                                                   387.4505563,
                                                   393.6005651,
                                                   399.9489613,
                                                   406.5055016,
                                                   413.2805933,
                                                   420.2853492,
                                                   427.5316483,
                                                   435.0322035,
                                                   442.8006357,
                                                   450.8515564,
                                                   459.2006593,
                                                   467.8648226,
                                                   476.8622231,
                                                   486.2124627,
                                                   495.936712,
                                                   506.0578694,
                                                   516.6007417,
                                                   527.5922468,
                                                   539.0616435,
                                                   551.0407911,
                                                   563.5644455,
                                                   576.6705953,
                                                   590.4008476,
                                                   604.8008683,
                                                   619.92089,
                                                   635.8162974,
                                                   652.5483053,
                                                   670.1847459,
                                                   688.8009889,
                                                   708.4810171,
                                                   729.3186941,
                                                   751.4192606,
                                                   774.9011125,
                                                   799.8979226,
                                                   826.5611867,
                                                   855.0632966,
                                                   885.6012714];

const COPPER_N: [f32; COPPER_SAMPLES] =
    [1.400313, 1.38, 1.358438, 1.34, 1.329063, 1.325, 1.3325, 1.34, 1.334375, 1.325, 1.317812,
     1.31, 1.300313, 1.29, 1.281563, 1.27, 1.249062, 1.225, 1.2, 1.18, 1.174375, 1.175, 1.1775,
     1.18, 1.178125, 1.175, 1.172812, 1.17, 1.165312, 1.16, 1.155312, 1.15, 1.142812, 1.135,
     1.131562, 1.12, 1.092437, 1.04, 0.950375, 0.826, 0.645875, 0.468, 0.35125, 0.272, 0.230813,
     0.214, 0.20925, 0.213, 0.21625, 0.223, 0.2365, 0.25, 0.254188, 0.26, 0.28, 0.3];

const COPPER_K: [f32; COPPER_SAMPLES] =
    [1.662125, 1.687, 1.703313, 1.72, 1.744563, 1.77, 1.791625, 1.81, 1.822125, 1.834, 1.85175,
     1.872, 1.89425, 1.916, 1.931688, 1.95, 1.972438, 2.015, 2.121562, 2.21, 2.177188, 2.13,
     2.160063, 2.21, 2.249938, 2.289, 2.326, 2.362, 2.397625, 2.433, 2.469187, 2.504, 2.535875,
     2.564, 2.589625, 2.605, 2.595562, 2.583, 2.5765, 2.599, 2.678062, 2.809, 3.01075, 3.24,
     3.458187, 3.67, 3.863125, 4.05, 4.239563, 4.43, 4.619563, 4.817, 5.034125, 5.26, 5.485625,
     5.717];

const AU_SAMPLES: usize = 56;
const AU_WAVELENGTHS: [f32; AU_SAMPLES] =
    [298.757050, 302.400421, 306.133759, 309.960449, 313.884003, 317.908142, 322.036835,
     326.274139, 330.624481, 335.092377, 339.682678, 344.400482, 349.251221, 354.240509,
     359.374420, 364.659332, 370.102020, 375.709625, 381.489777, 387.450562, 393.600555,
     399.948975, 406.505493, 413.280579, 420.285339, 427.531647, 435.032196, 442.800629,
     450.851562, 459.200653, 467.864838, 476.862213, 486.212463, 495.936707, 506.057861,
     516.600769, 527.592224, 539.061646, 551.040771, 563.564453, 576.670593, 590.400818,
     604.800842, 619.920898, 635.816284, 652.548279, 670.184753, 688.800964, 708.481018,
     729.318665, 751.419250, 774.901123, 799.897949, 826.561157, 855.063293, 885.601257];

const AU_N: [f32; AU_SAMPLES] =
    [1.795000, 1.812000, 1.822625, 1.830000, 1.837125, 1.840000, 1.834250, 1.824000, 1.812000,
     1.798000, 1.782000, 1.766000, 1.752500, 1.740000, 1.727625, 1.716000, 1.705875, 1.696000,
     1.684750, 1.674000, 1.666000, 1.658000, 1.647250, 1.636000, 1.628000, 1.616000, 1.596250,
     1.562000, 1.502125, 1.426000, 1.345875, 1.242000, 1.086750, 0.916000, 0.754500, 0.608000,
     0.491750, 0.402000, 0.345500, 0.306000, 0.267625, 0.236000, 0.212375, 0.194000, 0.177750,
     0.166000, 0.161000, 0.160000, 0.160875, 0.164000, 0.169500, 0.176000, 0.181375, 0.188000,
     0.198125, 0.210000];

const AU_K: [f32; AU_SAMPLES] =
    [1.920375, 1.920000, 1.918875, 1.916000, 1.911375, 1.904000, 1.891375, 1.878000, 1.868250,
     1.860000, 1.851750, 1.846000, 1.845250, 1.848000, 1.852375, 1.862000, 1.883000, 1.906000,
     1.922500, 1.936000, 1.947750, 1.956000, 1.959375, 1.958000, 1.951375, 1.940000, 1.924500,
     1.904000, 1.875875, 1.846000, 1.814625, 1.796000, 1.797375, 1.840000, 1.956500, 2.120000,
     2.326250, 2.540000, 2.730625, 2.880000, 2.940625, 2.970000, 3.015000, 3.060000, 3.070000,
     3.150000, 3.445812, 3.800000, 4.087687, 4.357000, 4.610188, 4.860000, 5.125813, 5.390000,
     5.631250, 5.880000];
<|endoftext|>


<commit_before>/**
 * Low-level GLFW library bindings and base types.
 */

use core::libc::*;

// Include OS X Frameworks
#[nolink]
#[cfg(target_os = "macos")]
#[link_args="-framework Cocoa -framework OpenGL -framework IOKit -framework CoreFoundation"]
extern mod osx_frameworks {}

// GLFW Linking
#[link_name = "glfw"]
extern mod linkhack {}

/* Function pointer types */
// Will have to be changed once we can do external C callbacks nicely
pub type GLFWerrorfun           = *u8;  // typedef void (* GLFWerrorfun)(int,const char*);
pub type GLFWwindowposfun       = *u8;  // typedef void (* GLFWwindowposfun)(*GLFWwindow,int,int);
pub type GLFWwindowsizefun      = *u8;  // typedef void (* GLFWwindowsizefun)(*GLFWwindow,int,int);
pub type GLFWwindowclosefun     = *u8;  // typedef void (* GLFWwindowclosefun)(*GLFWwindow);
pub type GLFWwindowrefreshfun   = *u8;  // typedef void (* GLFWwindowrefreshfun)(*GLFWwindow);
pub type GLFWwindowfocusfun     = *u8;  // typedef void (* GLFWwindowfocusfun)(*GLFWwindow,int);
pub type GLFWwindowiconifyfun   = *u8;  // typedef void (* GLFWwindowiconifyfun)(*GLFWwindow,int);
pub type GLFWmousebuttonfun     = *u8;  // typedef void (* GLFWmousebuttonfun)(*GLFWwindow,int,int);
pub type GLFWcursorposfun       = *u8;  // typedef void (* GLFWcursorposfun)(*GLFWwindow,int,int);
pub type GLFWcursorenterfun     = *u8;  // typedef void (* GLFWcursorenterfun)(*GLFWwindow,int);
pub type GLFWscrollfun          = *u8;  // typedef void (* GLFWscrollfun)(*GLFWwindow,double,double);
pub type GLFWkeyfun             = *u8;  // typedef void (* GLFWkeyfun)(*GLFWwindow,int,int);
pub type GLFWcharfun            = *u8;  // typedef void (* GLFWcharfun)(*GLFWwindow,unsigned int);
pub type GLFWmonitorfun         = *u8;  // typedef void (* GLFWmonitorfun)(*GLFWmonitor,int);

/* Monitor handle type */
pub struct GLFWmonitor {}

/* Window handle type */
pub struct GLFWwindow {}

pub type GLFWgammaramp = ::GammaRamp;
pub type GLFWvidmode = ::VidMode;
pub type GLFWglproc = ::GLProc;

pub extern "C" {
    /* GLFW initialization, termination and version querying */
    pub fn glfwInit() -> c_int;
    pub fn glfwTerminate();
    pub fn glfwGetVersion(major: *c_int, minor: *c_int, rev: *c_int);
    pub fn glfwGetVersionString() -> *c_char;

    /* Error handling */
    pub fn glfwSetErrorCallback(cbfun: GLFWerrorfun);

    /* Monitor functions */
    pub fn glfwGetMonitors(count: *c_int) -> **GLFWmonitor;
    pub fn glfwGetPrimaryMonitor() -> *GLFWmonitor;
    pub fn glfwGetMonitorPos(monitor: *GLFWmonitor, xpos: *c_int, ypos: *c_int);
    pub fn glfwGetMonitorPhysicalSize(monitor: *GLFWmonitor, width: *c_int, height: *c_int);
    pub fn glfwGetMonitorName(monitor: *GLFWmonitor) -> *c_char;
    pub fn glfwSetMonitorCallback(cbfun: GLFWmonitorfun);
    pub fn glfwGetVideoModes(monitor: *GLFWmonitor, count: *c_int) -> *GLFWvidmode;
    pub fn glfwGetVideoMode(monitor: *GLFWmonitor) -> GLFWvidmode;
    pub fn glfwSetGamma(monitor: *GLFWmonitor, gamma: c_float);
    pub fn glfwGetGammaRamp(monitor: *GLFWmonitor, ramp: *GLFWgammaramp);
    pub fn glfwSetGammaRamp(monitor: *GLFWmonitor, ramp: *GLFWgammaramp);

    /* Window handling */
    pub fn glfwDefaultWindowHints();
    pub fn glfwWindowHint(target: c_int, hint: c_int);
    pub fn glfwCreateWindow(width: c_int, height: c_int, title: *c_char, monitor: *GLFWmonitor, share: *GLFWwindow) -> *GLFWwindow;
    pub fn glfwDestroyWindow(window: *GLFWwindow);
    pub fn glfwWindowShouldClose(window: *GLFWwindow) -> c_int;
    pub fn glfwSetWindowShouldClose(window: *GLFWwindow, value: c_int);
    pub fn glfwSetWindowTitle(window: *GLFWwindow, title: *c_char);
    pub fn glfwGetWindowPos(window: *GLFWwindow, xpos: *c_int, ypos: *c_int);
    pub fn glfwSetWindowPos(window: *GLFWwindow, xpos: c_int, ypos: c_int);
    pub fn glfwGetWindowSize(window: *GLFWwindow, width: *c_int, height: *c_int);
    pub fn glfwSetWindowSize(window: *GLFWwindow, width: c_int, height: c_int);
    pub fn glfwIconifyWindow(window: *GLFWwindow);
    pub fn glfwRestoreWindow(window: *GLFWwindow);
    pub fn glfwShowWindow(window: *GLFWwindow);
    pub fn glfwHideWindow(window: *GLFWwindow);
    pub fn glfwGetWindowMonitor(window: *GLFWwindow) -> *GLFWmonitor;
    pub fn glfwGetWindowParam(window: *GLFWwindow, param: c_int) -> c_int;
    pub fn glfwSetWindowUserPointer(window: *GLFWwindow, pointer: *c_void);
    pub fn glfwGetWindowUserPointer(window: *GLFWwindow) -> *c_void;
    pub fn glfwSetWindowPosCallback(window: *GLFWwindow, cbfun: GLFWwindowposfun);
    pub fn glfwSetWindowSizeCallback(window: *GLFWwindow, cbfun: GLFWwindowsizefun);
    pub fn glfwSetWindowCloseCallback(window: *GLFWwindow, cbfun: GLFWwindowclosefun);
    pub fn glfwSetWindowRefreshCallback(window: *GLFWwindow, cbfun: GLFWwindowrefreshfun);
    pub fn glfwSetWindowFocusCallback(window: *GLFWwindow, cbfun: GLFWwindowfocusfun);
    pub fn glfwSetWindowIconifyCallback(window: *GLFWwindow, cbfun: GLFWwindowiconifyfun);

    /* Event handling */
    pub fn glfwPollEvents();
    pub fn glfwWaitEvents();

    /* Input handling */
    pub fn glfwGetInputMode(window: *GLFWwindow, mode: c_int) -> c_int;
    pub fn glfwSetInputMode(window: *GLFWwindow, mode: c_int, value: c_int);
    pub fn glfwGetKey(window: *GLFWwindow, key: c_int) -> c_int;
    pub fn glfwGetMouseButton(window: *GLFWwindow, button: c_int) -> c_int;
    pub fn glfwGetCursorPos(window: *GLFWwindow, xpos: *c_int, ypos: *c_int);
    pub fn glfwSetCursorPos(window: *GLFWwindow, xpos: c_int, ypos: c_int);
    pub fn glfwSetKeyCallback(window: *GLFWwindow, cbfun: GLFWkeyfun);
    pub fn glfwSetCharCallback(window: *GLFWwindow, cbfun: GLFWcharfun);
    pub fn glfwSetMouseButtonCallback(window: *GLFWwindow, cbfun: GLFWmousebuttonfun);
    pub fn glfwSetCursorPosCallback(window: *GLFWwindow, cbfun: GLFWcursorposfun);
    pub fn glfwSetCursorEnterCallback(window: *GLFWwindow, cbfun: GLFWcursorenterfun);
    pub fn glfwSetScrollCallback(window: *GLFWwindow, cbfun: GLFWscrollfun);

    /* Joystick input */
    pub fn glfwGetJoystickParam(joy: c_int, param: c_int) -> c_int;
    pub fn glfwGetJoystickAxes(joy: c_int, axes: *c_float, numaxes: c_int) -> c_int;
    pub fn glfwGetJoystickButtons(joy: c_int, buttons: *c_uchar, numbuttons: c_int) -> c_int;
    pub fn glfwGetJoystickName(joy: c_int) -> *c_char;

    /* Clipboard */
    pub fn glfwSetClipboardString(window: *GLFWwindow, string: *c_char);
    pub fn glfwGetClipboardString(window: *GLFWwindow) -> *c_char;

    /* Time */
    pub fn glfwGetTime() -> c_double;
    pub fn glfwSetTime(time: c_double);

    /* OpenGL support */
    pub fn glfwMakeContextCurrent(window: *GLFWwindow);
    pub fn glfwGetCurrentContext() -> *GLFWwindow;
    pub fn glfwSwapBuffers(window: *GLFWwindow);
    pub fn glfwSwapInterval(interval: c_int);
    pub fn glfwExtensionSupported(extension: *c_char) -> c_int;
    pub fn glfwGetProcAddress(procname: *c_char) -> GLFWglproc;
}<commit_msg>Fixed errors with Unit-like structs<commit_after>/**
 * Low-level GLFW library bindings and base types.
 */

use core::libc::*;

// Include OS X Frameworks
#[nolink]
#[cfg(target_os = "macos")]
#[link_args="-framework Cocoa -framework OpenGL -framework IOKit -framework CoreFoundation"]
extern mod osx_frameworks {}

// GLFW Linking
#[link_name = "glfw"]
extern mod linkhack {}

/* Function pointer types */
// Will have to be changed once we can do external C callbacks nicely
pub type GLFWerrorfun           = *u8;  // typedef void (* GLFWerrorfun)(int,const char*);
pub type GLFWwindowposfun       = *u8;  // typedef void (* GLFWwindowposfun)(*GLFWwindow,int,int);
pub type GLFWwindowsizefun      = *u8;  // typedef void (* GLFWwindowsizefun)(*GLFWwindow,int,int);
pub type GLFWwindowclosefun     = *u8;  // typedef void (* GLFWwindowclosefun)(*GLFWwindow);
pub type GLFWwindowrefreshfun   = *u8;  // typedef void (* GLFWwindowrefreshfun)(*GLFWwindow);
pub type GLFWwindowfocusfun     = *u8;  // typedef void (* GLFWwindowfocusfun)(*GLFWwindow,int);
pub type GLFWwindowiconifyfun   = *u8;  // typedef void (* GLFWwindowiconifyfun)(*GLFWwindow,int);
pub type GLFWmousebuttonfun     = *u8;  // typedef void (* GLFWmousebuttonfun)(*GLFWwindow,int,int);
pub type GLFWcursorposfun       = *u8;  // typedef void (* GLFWcursorposfun)(*GLFWwindow,int,int);
pub type GLFWcursorenterfun     = *u8;  // typedef void (* GLFWcursorenterfun)(*GLFWwindow,int);
pub type GLFWscrollfun          = *u8;  // typedef void (* GLFWscrollfun)(*GLFWwindow,double,double);
pub type GLFWkeyfun             = *u8;  // typedef void (* GLFWkeyfun)(*GLFWwindow,int,int);
pub type GLFWcharfun            = *u8;  // typedef void (* GLFWcharfun)(*GLFWwindow,unsigned int);
pub type GLFWmonitorfun         = *u8;  // typedef void (* GLFWmonitorfun)(*GLFWmonitor,int);

/* Monitor handle type */
pub struct GLFWmonitor;

/* Window handle type */
pub struct GLFWwindow;

pub type GLFWgammaramp = ::GammaRamp;
pub type GLFWvidmode = ::VidMode;
pub type GLFWglproc = ::GLProc;

pub extern "C" {
    /* GLFW initialization, termination and version querying */
    pub fn glfwInit() -> c_int;
    pub fn glfwTerminate();
    pub fn glfwGetVersion(major: *c_int, minor: *c_int, rev: *c_int);
    pub fn glfwGetVersionString() -> *c_char;

    /* Error handling */
    pub fn glfwSetErrorCallback(cbfun: GLFWerrorfun);

    /* Monitor functions */
    pub fn glfwGetMonitors(count: *c_int) -> **GLFWmonitor;
    pub fn glfwGetPrimaryMonitor() -> *GLFWmonitor;
    pub fn glfwGetMonitorPos(monitor: *GLFWmonitor, xpos: *c_int, ypos: *c_int);
    pub fn glfwGetMonitorPhysicalSize(monitor: *GLFWmonitor, width: *c_int, height: *c_int);
    pub fn glfwGetMonitorName(monitor: *GLFWmonitor) -> *c_char;
    pub fn glfwSetMonitorCallback(cbfun: GLFWmonitorfun);
    pub fn glfwGetVideoModes(monitor: *GLFWmonitor, count: *c_int) -> *GLFWvidmode;
    pub fn glfwGetVideoMode(monitor: *GLFWmonitor) -> GLFWvidmode;
    pub fn glfwSetGamma(monitor: *GLFWmonitor, gamma: c_float);
    pub fn glfwGetGammaRamp(monitor: *GLFWmonitor, ramp: *GLFWgammaramp);
    pub fn glfwSetGammaRamp(monitor: *GLFWmonitor, ramp: *GLFWgammaramp);

    /* Window handling */
    pub fn glfwDefaultWindowHints();
    pub fn glfwWindowHint(target: c_int, hint: c_int);
    pub fn glfwCreateWindow(width: c_int, height: c_int, title: *c_char, monitor: *GLFWmonitor, share: *GLFWwindow) -> *GLFWwindow;
    pub fn glfwDestroyWindow(window: *GLFWwindow);
    pub fn glfwWindowShouldClose(window: *GLFWwindow) -> c_int;
    pub fn glfwSetWindowShouldClose(window: *GLFWwindow, value: c_int);
    pub fn glfwSetWindowTitle(window: *GLFWwindow, title: *c_char);
    pub fn glfwGetWindowPos(window: *GLFWwindow, xpos: *c_int, ypos: *c_int);
    pub fn glfwSetWindowPos(window: *GLFWwindow, xpos: c_int, ypos: c_int);
    pub fn glfwGetWindowSize(window: *GLFWwindow, width: *c_int, height: *c_int);
    pub fn glfwSetWindowSize(window: *GLFWwindow, width: c_int, height: c_int);
    pub fn glfwIconifyWindow(window: *GLFWwindow);
    pub fn glfwRestoreWindow(window: *GLFWwindow);
    pub fn glfwShowWindow(window: *GLFWwindow);
    pub fn glfwHideWindow(window: *GLFWwindow);
    pub fn glfwGetWindowMonitor(window: *GLFWwindow) -> *GLFWmonitor;
    pub fn glfwGetWindowParam(window: *GLFWwindow, param: c_int) -> c_int;
    pub fn glfwSetWindowUserPointer(window: *GLFWwindow, pointer: *c_void);
    pub fn glfwGetWindowUserPointer(window: *GLFWwindow) -> *c_void;
    pub fn glfwSetWindowPosCallback(window: *GLFWwindow, cbfun: GLFWwindowposfun);
    pub fn glfwSetWindowSizeCallback(window: *GLFWwindow, cbfun: GLFWwindowsizefun);
    pub fn glfwSetWindowCloseCallback(window: *GLFWwindow, cbfun: GLFWwindowclosefun);
    pub fn glfwSetWindowRefreshCallback(window: *GLFWwindow, cbfun: GLFWwindowrefreshfun);
    pub fn glfwSetWindowFocusCallback(window: *GLFWwindow, cbfun: GLFWwindowfocusfun);
    pub fn glfwSetWindowIconifyCallback(window: *GLFWwindow, cbfun: GLFWwindowiconifyfun);

    /* Event handling */
    pub fn glfwPollEvents();
    pub fn glfwWaitEvents();

    /* Input handling */
    pub fn glfwGetInputMode(window: *GLFWwindow, mode: c_int) -> c_int;
    pub fn glfwSetInputMode(window: *GLFWwindow, mode: c_int, value: c_int);
    pub fn glfwGetKey(window: *GLFWwindow, key: c_int) -> c_int;
    pub fn glfwGetMouseButton(window: *GLFWwindow, button: c_int) -> c_int;
    pub fn glfwGetCursorPos(window: *GLFWwindow, xpos: *c_int, ypos: *c_int);
    pub fn glfwSetCursorPos(window: *GLFWwindow, xpos: c_int, ypos: c_int);
    pub fn glfwSetKeyCallback(window: *GLFWwindow, cbfun: GLFWkeyfun);
    pub fn glfwSetCharCallback(window: *GLFWwindow, cbfun: GLFWcharfun);
    pub fn glfwSetMouseButtonCallback(window: *GLFWwindow, cbfun: GLFWmousebuttonfun);
    pub fn glfwSetCursorPosCallback(window: *GLFWwindow, cbfun: GLFWcursorposfun);
    pub fn glfwSetCursorEnterCallback(window: *GLFWwindow, cbfun: GLFWcursorenterfun);
    pub fn glfwSetScrollCallback(window: *GLFWwindow, cbfun: GLFWscrollfun);

    /* Joystick input */
    pub fn glfwGetJoystickParam(joy: c_int, param: c_int) -> c_int;
    pub fn glfwGetJoystickAxes(joy: c_int, axes: *c_float, numaxes: c_int) -> c_int;
    pub fn glfwGetJoystickButtons(joy: c_int, buttons: *c_uchar, numbuttons: c_int) -> c_int;
    pub fn glfwGetJoystickName(joy: c_int) -> *c_char;

    /* Clipboard */
    pub fn glfwSetClipboardString(window: *GLFWwindow, string: *c_char);
    pub fn glfwGetClipboardString(window: *GLFWwindow) -> *c_char;

    /* Time */
    pub fn glfwGetTime() -> c_double;
    pub fn glfwSetTime(time: c_double);

    /* OpenGL support */
    pub fn glfwMakeContextCurrent(window: *GLFWwindow);
    pub fn glfwGetCurrentContext() -> *GLFWwindow;
    pub fn glfwSwapBuffers(window: *GLFWwindow);
    pub fn glfwSwapInterval(interval: c_int);
    pub fn glfwExtensionSupported(extension: *c_char) -> c_int;
    pub fn glfwGetProcAddress(procname: *c_char) -> GLFWglproc;
}
<|endoftext|>


<commit_before>//! Defines various Monte Carlo sampling functions for sampling
//! points/directions on objects and computing the corresponding pdfs

use std::f32;

use linalg::{self, Vector};

/// Sample a hemisphere using a cosine distribution to produce cosine weighted samples
/// `samples` should be two random samples in range [0, 1)
/// directions returned will be in the hemisphere around (0, 0, 1)
pub fn cos_sample_hemisphere(u: &(f32, f32)) -> Vector {
    //We use Malley's method here, generate samples on a disk then project
    //them up to the hemisphere
    let d = concentric_sample_disk(u);
    Vector::new(d.0, d.1, f32::sqrt(f32::max(0.0, 1.0 - d.0 * d.0 - d.1 * d.1)))
}
/// Compute the PDF of the cosine weighted hemisphere sampling
pub fn cos_hemisphere_pdf(cos_theta: f32) -> f32 { cos_theta * f32::consts::FRAC_1_PI }
/// Compute concentric sample positions on a unit disk mapping input from range [0, 1)
/// to sample positions on a disk
/// `samples` should be two random samples in range [0, 1)
/// See: [Shirley and Chiu, A Low Distortion Map Between Disk and Square](https://mediatech.aalto.fi/~jaakko/T111-5310/K2013/JGT-97.pdf)
pub fn concentric_sample_disk(u: &(f32, f32)) -> (f32, f32) {
    let s = (2.0 * u.0 - 1.0, 2.0 * u.1 - 1.0);
    let radius;
    let theta;
    if s.0 == 0.0 && s.1 == 0.0 {
        return s;
    }
    if s.0 >= -s.1 {
        if s.0 > s.1 {
            radius = s.0;
            if s.1 > 0.0 {
                theta = s.1 / s.0;
            } else {
                theta = 8.0 + s.1 / s.0;
            }
        }
        else {
            radius = s.1;
            theta = 2.0 - s.0 / s.1;
        }
    }
    else {
        if s.0 <= s.1 {
            radius = -s.0;
            theta = 4.0 + s.1 / s.0;
        }
        else {
            radius = -s.1;
            theta = 6.0 - s.0 / s.1;
        }
    }
    let theta = theta * f32::consts::FRAC_PI_4;
    (radius * f32::cos(theta), radius * f32::sin(theta))
}
/// Power heuristic for multiple importance sampling for two functions being sampled, f & g
/// where beta is hard-coded to be two following PBR & Veach
/// - `n_f`, `n_g` number of samples taken of each
/// - `pdf_f`, `pdf_g` pdf of each function
pub fn power_heuristic(n_f: f32, pdf_f: f32, n_g: f32, pdf_g: f32) -> f32 {
    let f = n_f * pdf_f;
    let g = n_g * pdf_g;
    (f * f) / (f * f + g * g)
}
/// Return the PDF for uniformly sampling a cone with some max solid angle
pub fn uniform_cone_pdf(cos_theta: f32) -> f32 {
    1.0 / (f32::consts::PI * 2.0 * (1.0 - cos_theta))
}
/// Uniformly sample a direction in a cone with max angle `cos_theta_max` where
/// the cone lies along the z-axis
pub fn uniform_sample_cone(samples: &(f32, f32), cos_theta_max: f32) -> Vector {
    let cos_theta = linalg::lerp(samples.0, &cos_theta_max, &1.0);
    let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta);
    let phi = samples.1 * f32::consts::PI * 2.0;
    Vector::new(f32::cos(phi) * sin_theta, f32::sin(phi) * sin_theta, cos_theta)
}
/// Uniformly sample a direction in a cone with max angle `cos_theta_max` where
/// the cone looks down the w_z vector provided, with w_x, w_y forming the rest
/// of the coordinate frame for the cone
pub fn uniform_sample_cone_frame(samples: &(f32, f32), cos_theta_max: f32, w_x: &Vector,
                                 w_y: &Vector, w_z: &Vector) -> Vector {
    let cos_theta = linalg::lerp(samples.0, &cos_theta_max, &1.0);
    let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta);
    let phi = samples.1 * f32::consts::PI * 2.0;
    f32::cos(phi) * sin_theta * *w_z + f32::sin(phi) * sin_theta * *w_y + cos_theta * *w_z
}
/// Uniformly sample a direction on the unit sphere about the origin
pub fn uniform_sample_sphere(samples: &(f32, f32)) -> Vector {
    let z = 1.0 - 2.0 * samples.0;
    let r = f32::sqrt(f32::max(0.0, 1.0 - z * z));
    let phi = f32::consts::PI * 2.0 * samples.1;
    Vector::new(f32::cos(phi) * r, f32::sin(phi) * r, z)
}

<commit_msg>Fix typo of vector in uniform_sample_cone_frame, w_x was not used<commit_after>//! Defines various Monte Carlo sampling functions for sampling
//! points/directions on objects and computing the corresponding pdfs

use std::f32;

use linalg::{self, Vector};

/// Sample a hemisphere using a cosine distribution to produce cosine weighted samples
/// `samples` should be two random samples in range [0, 1)
/// directions returned will be in the hemisphere around (0, 0, 1)
pub fn cos_sample_hemisphere(u: &(f32, f32)) -> Vector {
    //We use Malley's method here, generate samples on a disk then project
    //them up to the hemisphere
    let d = concentric_sample_disk(u);
    Vector::new(d.0, d.1, f32::sqrt(f32::max(0.0, 1.0 - d.0 * d.0 - d.1 * d.1)))
}
/// Compute the PDF of the cosine weighted hemisphere sampling
pub fn cos_hemisphere_pdf(cos_theta: f32) -> f32 { cos_theta * f32::consts::FRAC_1_PI }
/// Compute concentric sample positions on a unit disk mapping input from range [0, 1)
/// to sample positions on a disk
/// `samples` should be two random samples in range [0, 1)
/// See: [Shirley and Chiu, A Low Distortion Map Between Disk and Square](https://mediatech.aalto.fi/~jaakko/T111-5310/K2013/JGT-97.pdf)
pub fn concentric_sample_disk(u: &(f32, f32)) -> (f32, f32) {
    let s = (2.0 * u.0 - 1.0, 2.0 * u.1 - 1.0);
    let radius;
    let theta;
    if s.0 == 0.0 && s.1 == 0.0 {
        return s;
    }
    if s.0 >= -s.1 {
        if s.0 > s.1 {
            radius = s.0;
            if s.1 > 0.0 {
                theta = s.1 / s.0;
            } else {
                theta = 8.0 + s.1 / s.0;
            }
        }
        else {
            radius = s.1;
            theta = 2.0 - s.0 / s.1;
        }
    }
    else {
        if s.0 <= s.1 {
            radius = -s.0;
            theta = 4.0 + s.1 / s.0;
        }
        else {
            radius = -s.1;
            theta = 6.0 - s.0 / s.1;
        }
    }
    let theta = theta * f32::consts::FRAC_PI_4;
    (radius * f32::cos(theta), radius * f32::sin(theta))
}
/// Power heuristic for multiple importance sampling for two functions being sampled, f & g
/// where beta is hard-coded to be two following PBR & Veach
/// - `n_f`, `n_g` number of samples taken of each
/// - `pdf_f`, `pdf_g` pdf of each function
pub fn power_heuristic(n_f: f32, pdf_f: f32, n_g: f32, pdf_g: f32) -> f32 {
    let f = n_f * pdf_f;
    let g = n_g * pdf_g;
    (f * f) / (f * f + g * g)
}
/// Return the PDF for uniformly sampling a cone with some max solid angle
pub fn uniform_cone_pdf(cos_theta: f32) -> f32 {
    1.0 / (f32::consts::PI * 2.0 * (1.0 - cos_theta))
}
/// Uniformly sample a direction in a cone with max angle `cos_theta_max` where
/// the cone lies along the z-axis
pub fn uniform_sample_cone(samples: &(f32, f32), cos_theta_max: f32) -> Vector {
    let cos_theta = linalg::lerp(samples.0, &cos_theta_max, &1.0);
    let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta);
    let phi = samples.1 * f32::consts::PI * 2.0;
    Vector::new(f32::cos(phi) * sin_theta, f32::sin(phi) * sin_theta, cos_theta)
}
/// Uniformly sample a direction in a cone with max angle `cos_theta_max` where
/// the cone looks down the w_z vector provided, with w_x, w_y forming the rest
/// of the coordinate frame for the cone
pub fn uniform_sample_cone_frame(samples: &(f32, f32), cos_theta_max: f32, w_x: &Vector,
                                 w_y: &Vector, w_z: &Vector) -> Vector {
    let cos_theta = linalg::lerp(samples.0, &cos_theta_max, &1.0);
    let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta);
    let phi = samples.1 * f32::consts::PI * 2.0;
    f32::cos(phi) * sin_theta * *w_x + f32::sin(phi) * sin_theta * *w_y + cos_theta * *w_z
}
/// Uniformly sample a direction on the unit sphere about the origin
pub fn uniform_sample_sphere(samples: &(f32, f32)) -> Vector {
    let z = 1.0 - 2.0 * samples.0;
    let r = f32::sqrt(f32::max(0.0, 1.0 - z * z));
    let phi = f32::consts::PI * 2.0 * samples.1;
    Vector::new(f32::cos(phi) * r, f32::sin(phi) * r, z)
}

<|endoftext|>


<commit_before>use std::old_io::IoErrorKind::*;
use std::collections::VecMap;
use unicode::str::*;

use std::str;
use std::old_io;
use std::fmt;

use constants::*;
use util::*;
use types::*;
use ioctl::*;

type Stdr = old_io::stdio::StdReader;
type Stdw = old_io::stdio::StdWriter;

pub struct Controls {
    stdin: Stdr,
    stdout: Stdw,
    stderr: Stdw,
    cursor: Position,
    tsize: WinSize,
    rows: VecMap<usize>,
    roff: isize
}

impl Controls {
    pub fn new() -> Controls {
        Controls {
            stdin: old_io::stdio::stdin_raw(),
            stdout: old_io::stdio::stdout_raw(),
            stderr: old_io::stdio::stderr_raw(),
            cursor: Position::new(),
            tsize: WinSize::new(),
            rows: VecMap::new(),
            roff: 0
        }
    }

    pub fn update_cursor(&mut self, pos:Position) {
        self.cursor = pos;
    }

    pub fn update_size(&mut self, size:WinSize) {
        self.tsize = size;
    }

    pub fn clear_rows(&mut self) {
        self.rows.clear();
        self.roff = 0;
    }

    pub fn get_row(&mut self) -> usize {
        self.cursor.row
    }

    pub fn width(&mut self) -> usize {
        self.tsize.col as usize
    }

    pub fn get_pos(&mut self) -> Position {
        self.cursor
    }

    pub fn row_length(&mut self) -> usize {
        if !self.rows.contains_key(&((self.cursor.row as isize + self.roff) as usize)) {
            return 1;
        } else {
            return self.rows[(self.cursor.row as isize + self.roff) as usize];
        }
    }

    pub fn save_row(&mut self, len:usize) {
        if !self.rows.contains_key(&((self.cursor.row as isize + self.roff) as usize)) {
            self.rows.insert((self.cursor.row as isize + self.roff) as usize, len);
        } else {
            self.rows[(self.cursor.row as isize + self.roff) as usize] = len;
        }
    }

    fn move_right(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.cursor.col += by;
        let mut row_size = self.row_length();
        if self.cursor.col > row_size {
            loop {
                if self.cursor.col > row_size {
                    self.cursor.col -= row_size;
                    self.cursor.row += 1;
                    row_size = self.row_length();
                } else {
                    break;
                }
            }
            if self.cursor.row > self.tsize.row as usize {
                self.roff += self.cursor.row as isize - self.tsize.row as isize;
                self.cursor.row = self.tsize.row as usize;
            }
        }
    }

    fn move_left(&mut self, mut by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        loop {
            if by >= self.cursor.col {
                by -= self.cursor.col;
                if self.cursor.row == 0 {
                    self.roff -= 1;
                } else {
                    self.cursor.row -= 1;
                }
                self.cursor.col = self.row_length();
            } else {
                self.cursor.col -= by;
                break;
            }
        }
    }

    pub fn grow_check(&mut self, len:usize) -> bool {
        self.cursor.col + len > self.tsize.col as usize
    }

    pub fn grow(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.cursor.col += by;
        if self.cursor.col > self.tsize.col as usize {
            let col = self.tsize.col as usize;
            self.save_row(col);
            self.cursor.row += self.cursor.col / self.tsize.col as usize;
            self.cursor.col = self.cursor.col % self.tsize.col as usize;
            if self.cursor.row > self.tsize.row as usize {
                self.roff += self.cursor.row as isize - self.tsize.row as isize;
                self.cursor.row = self.tsize.row as usize;
            }
        }
        let col = self.cursor.col;
        self.save_row(col);
    }

    pub fn shrink(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if by >= self.cursor.col {
            self.rows.remove(&((self.cursor.row as isize + self.roff) as usize));
            let diff = by - self.cursor.col;
            self.cursor.col = self.tsize.col as usize -
                (diff % self.tsize.col as usize);
            let rdiff = (diff / self.tsize.col as usize) + 1;
            if rdiff > self.cursor.row {
                self.cursor.row = 0;
            } else {
                self.cursor.row -= rdiff;
            }
        } else {
            self.cursor.col -= by;
        }
        let col = self.cursor.col;
        self.save_row(col);
    }

    fn new_row(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.row == self.tsize.row as usize {
            self.roff += 1;
        } else {
            self.cursor.row += 1;
        }
        self.cursor.col = 1;
    }

    /* out* and err* functions are assumed to be output
       functions */

    pub fn outc(&mut self, ch:char) {
        self.stdout.write_char(ch).unwrap();
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if ch == NL {
            self.new_row();
        } else {
            if self.grow_check(1) {
                self.stdout.write_char(SPC).unwrap();
                self.stdout.write_char(DEL).unwrap();
            }
            self.grow(1);
        }
    }

    pub fn outs(&mut self, s:&str) {
        if self.tsize.col == 0 || self.tsize.row == 0 {
            self.stdout.write_str(s).unwrap();
            return;
        }
        let mut splits = NL_REGEX.split(s);
        match splits.next() {
            Some(part) => {
                self.stdout.write_str(part).unwrap();
                if self.cursor.col + part.len() - 1 == self.tsize.col as usize {
                    self.stdout.write_char(SPC).unwrap();
                    self.stdout.write_char(DEL).unwrap();
                }
                self.grow(part.len());
                for part in splits {
                    self.new_row();
                    self.stdout.write_char(NL).unwrap();
                    self.stdout.write_str(part).unwrap();
                    if self.cursor.col + part.len() - 1 == self.tsize.col as usize {
                        self.stdout.write_char(SPC).unwrap();
                        self.stdout.write_char(DEL).unwrap();
                    }
                    self.grow(part.len());
                }
            },
            _ => {}
        }
    }

    pub fn outf(&mut self, args:fmt::Arguments) {
        self.outs(fmt::format(args).as_slice());
    }

    pub fn err(&mut self, s:&str) {
        if self.tsize.col == 0 || self.tsize.row == 0 {
            self.stderr.write_str(s).unwrap();
            return;
        }
        self.stderr.write_str(s).unwrap();
        let mut splits = NL_REGEX.split(s);
        match splits.next() {
            Some(part) => {
                self.grow(part.len());
                for part in splits {
                    self.new_row();
                    if self.cursor.col + part.len() == self.tsize.col as usize {
                        self.stdout.write_char(NL).unwrap();
                    }
                    self.grow(part.len());
                }
            },
            _ => {}
        }
    }

    pub fn errf(&mut self, args:fmt::Arguments) {
        self.err(fmt::format(args).as_slice());
    }

    pub fn del(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col > 1 {
            self.stdout.write_char(DEL).unwrap();
            self.shrink(1);
        } else {
            self.shrink(1);
            self.move_to_pointer();
        }
    }

    pub fn read(&mut self) -> old_io::IoResult<char> {
        // Below lifted almost verbatim from rust's read_char.
        // In compliance with MIT, nothing to worry about
        let first_byte = try!(self.stdin.read_byte());
        let width = utf8_char_width(first_byte);
        if width == 1 { return Ok(first_byte as char) }
        if width == 0 { return Err(old_io::standard_error(InvalidInput)) } // not utf8
        let mut buf = [first_byte, 0, 0, 0];
        {
            let mut start = 1;
            while start < width {
                match try!(self.stdin.read(&mut buf[start..width])) {
                    n if n == width - start => break,
                    n if n < width - start => { start += n; }
                    _ => return Err(old_io::standard_error(InvalidInput)),
                }
            }
        }
        match str::from_utf8(&buf[..width]).ok() {
            Some(s) => Ok(s.char_at(0)),
            None => Err(old_io::standard_error(InvalidInput))
        }
    }

    pub fn cursor_left(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col > 1 {
            self.stdout.write_char(DEL).unwrap();
            self.move_left(1);
        } else {
            self.move_left(1);
            self.move_to_pointer();
        }
    }

    pub fn cursor_right(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col < self.row_length() {
            self.stdout.write_str(CRSR_RIGHT).unwrap();
            self.move_right(1);
        } else {
            self.move_right(1);
            self.move_to_pointer();
        }
    }

    pub fn cursors_left(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if by == 0 {
            return;
        } else if by <= 3 && self.cursor.col > by {
            self.stdout.write_str(build_string(DEL, by).as_slice()).unwrap();
            self.move_left(by);
        } else if self.cursor.col > by {
            self.stdout.write_fmt(format_args!("{}{}D", ANSI_BEGIN, by)).unwrap();
            self.move_left(by);
        } else {
            self.move_left(by);
            self.move_to_pointer();
        }
    }

    pub fn cursors_right(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if by == 0 {
            return;
        } else if by + self.cursor.col <= self.row_length() {
            self.stdout.write_fmt(format_args!("{}{}C", ANSI_BEGIN, by)).unwrap();
            self.move_right(by);
        } else {
            self.move_right(by);
            self.move_to_pointer();
        }
    }

    pub fn clear_line(&mut self) {
        self.stdout.write_str(ANSI_BEGIN).unwrap();
        self.stdout.write_char('K').unwrap();
        let col = self.cursor.col;
        self.save_row(col);
    }

    pub fn clear_line_to(&mut self, len:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        let old = self.cursor;
        let mut total = self.cursor.col + len;
        let mut rlen = self.row_length();
        loop {
            self.clear_line();
            if total > rlen {
                total -= rlen;
                self.next_start();
                rlen = self.row_length();
            } else {
                break;
            }
        }
        self.move_to(old);
    }

    pub fn next_start(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.new_row();
        let row = self.cursor.row;
        self.move_to(Position {
            col: 1,
            row: row
        });
    }

    pub fn flush(&mut self) {
        self.stdout.flush().unwrap();
        self.stderr.flush().unwrap();
    }

    pub fn query_cursor(&mut self) {
        self.stdout.write_str(CRSR_POS).unwrap();
    }

    fn move_to_pointer(&mut self) {
        let (row, col) = (self.cursor.row, self.cursor.col);
        self.stdout.write_fmt(format_args!("{}{};{}f", ANSI_BEGIN, row, col)).unwrap();
    }

    pub fn move_to(&mut self, pos:Position) {
        self.cursor = pos;
        self.move_to_pointer();
    }

    pub fn bell(&mut self) {
        self.stdout.write_char(BEL).unwrap();
    }
}

<commit_msg>Fix bug with shrink removing wrong row<commit_after>use std::old_io::IoErrorKind::*;
use std::collections::VecMap;
use unicode::str::*;

use std::str;
use std::old_io;
use std::fmt;

use constants::*;
use util::*;
use types::*;
use ioctl::*;

type Stdr = old_io::stdio::StdReader;
type Stdw = old_io::stdio::StdWriter;

pub struct Controls {
    stdin: Stdr,
    stdout: Stdw,
    stderr: Stdw,
    cursor: Position,
    tsize: WinSize,
    rows: VecMap<usize>,
    lines: VecMap<usize>,
    line: usize,
    linecol: usize,
    roff: isize
}

impl Controls {
    pub fn new() -> Controls {
        Controls {
            stdin: old_io::stdio::stdin_raw(),
            stdout: old_io::stdio::stdout_raw(),
            stderr: old_io::stdio::stderr_raw(),
            cursor: Position::new(),
            tsize: WinSize::new(),
            rows: VecMap::new(),
            lines: VecMap::new(),
            line: 0,
            linecol: 0,
            roff: 0
        }
    }

    pub fn update_cursor(&mut self, pos:Position) {
        self.cursor = pos;
    }

    pub fn update_size(&mut self, size:WinSize) {
        self.tsize = size;
    }

    pub fn clear_rows(&mut self) {
        self.rows.clear();
        self.roff = 0;
    }

    pub fn get_row(&mut self) -> usize {
        self.cursor.row
    }

    pub fn width(&mut self) -> usize {
        self.tsize.col as usize
    }

    pub fn get_pos(&mut self) -> Position {
        self.cursor
    }

    pub fn row_length(&mut self) -> usize {
        if !self.rows.contains_key(&((self.cursor.row as isize + self.roff) as usize)) {
            return 1;
        } else {
            return self.rows[(self.cursor.row as isize + self.roff) as usize];
        }
    }

    pub fn save_row(&mut self, len:usize) {
        if !self.rows.contains_key(&((self.cursor.row as isize + self.roff) as usize)) {
            self.rows.insert((self.cursor.row as isize + self.roff) as usize, len);
        } else {
            self.rows[(self.cursor.row as isize + self.roff) as usize] = len;
        }
    }

    fn move_right(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.cursor.col += by;
        let mut row_size = self.row_length();
        if self.cursor.col > row_size {
            loop {
                if self.cursor.col > row_size {
                    self.cursor.col -= row_size;
                    self.cursor.row += 1;
                    row_size = self.row_length();
                } else {
                    break;
                }
            }
            if self.cursor.row > self.tsize.row as usize {
                self.roff += self.cursor.row as isize - self.tsize.row as isize;
                self.cursor.row = self.tsize.row as usize;
            }
        }
    }

    fn move_left(&mut self, mut by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        loop {
            if by >= self.cursor.col {
                by -= self.cursor.col;
                if self.cursor.row == 0 {
                    self.roff -= 1;
                } else {
                    self.cursor.row -= 1;
                }
                self.cursor.col = self.row_length();
            } else {
                self.cursor.col -= by;
                break;
            }
        }
    }

    pub fn grow_check(&mut self, len:usize) -> bool {
        self.cursor.col + len > self.tsize.col as usize
    }

    pub fn grow(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.cursor.col += by;
        self.linecol += by;
        if self.lines.contains_key(&self.line) {
            self.lines[self.line] += by;
        } else {
            self.lines.insert(self.line, self.linecol);
        }
        if self.cursor.col > self.tsize.col as usize {
            let col = self.tsize.col as usize;
            self.save_row(col);
            self.cursor.row += self.cursor.col / self.tsize.col as usize;
            self.cursor.col = self.cursor.col % self.tsize.col as usize;
            if self.cursor.row > self.tsize.row as usize {
                self.roff += self.cursor.row as isize - self.tsize.row as isize;
                self.cursor.row = self.tsize.row as usize;
            }
        }
        let col = self.cursor.col;
        self.save_row(col);
    }

    pub fn shrink(&mut self, mut by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        let mut lby = by;
        loop {
            if lby > self.linecol {
                if self.line == 0 {
                    self.linecol = 0;
                    self.lines[0] = 0;
                    break;
                } else {
                    self.lines[self.line] -= self.linecol;
                    lby -= self.linecol;
                    self.line -= 1;
                    self.linecol = {
                        if self.lines.contains_key(&self.line) {
                            self.lines[self.line]
                        } else {
                            0
                        }
                    };
                }
            } else {
                self.linecol -= lby;
                self.lines[self.line] -= lby;
                break;
            }
        }
        loop {
            if by >= self.cursor.col {
                by -= self.cursor.col;
                self.rows.remove(&((self.cursor.row as isize + self.roff) as usize));
                if self.cursor.row == 0 {
                    self.roff -= 1;
                } else {
                    self.cursor.row -= 1;
                }
                self.cursor.col = self.row_length();
            } else {
                self.cursor.col -= by;
                break;
            }
        }
        let col = self.cursor.col;
        self.save_row(col);
    }

    fn new_row(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.row == self.tsize.row as usize {
            self.roff += 1;
        } else {
            self.cursor.row += 1;
        }
        self.cursor.col = 1;
    }

    fn new_line(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.new_row();
        self.line += 1;
        self.linecol = 0;
        if self.lines.contains_key(&self.line) {
            self.lines[self.line] = self.linecol;
        } else {
            self.lines.insert(self.line, self.linecol);
        }
    }

    /* out* and err* functions are assumed to be output
       functions */

    pub fn outc(&mut self, ch:char) {
        self.stdout.write_char(ch).unwrap();
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if ch == NL {
            self.new_line();
        } else {
            if self.grow_check(1) {
                self.stdout.write_char(SPC).unwrap();
                self.stdout.write_char(DEL).unwrap();
            }
            self.grow(1);
        }
    }

    pub fn outs(&mut self, s:&str) {
        if self.tsize.col == 0 || self.tsize.row == 0 {
            self.stdout.write_str(s).unwrap();
            return;
        }
        let mut splits = NL_REGEX.split(s);
        match splits.next() {
            Some(part) => {
                self.stdout.write_str(part).unwrap();
                if self.cursor.col + part.len() - 1 == self.tsize.col as usize {
                    self.stdout.write_char(SPC).unwrap();
                    self.stdout.write_char(DEL).unwrap();
                }
                self.grow(part.len());
                for part in splits {
                    self.new_line();
                    self.stdout.write_char(NL).unwrap();
                    self.stdout.write_str(part).unwrap();
                    if self.cursor.col + part.len() - 1 == self.tsize.col as usize {
                        self.stdout.write_char(SPC).unwrap();
                        self.stdout.write_char(DEL).unwrap();
                    }
                    self.grow(part.len());
                }
            },
            _ => {}
        }
    }

    pub fn outf(&mut self, args:fmt::Arguments) {
        self.outs(fmt::format(args).as_slice());
    }

    pub fn err(&mut self, s:&str) {
        if self.tsize.col == 0 || self.tsize.row == 0 {
            self.stderr.write_str(s).unwrap();
            return;
        }
        self.stderr.write_str(s).unwrap();
        let mut splits = NL_REGEX.split(s);
        match splits.next() {
            Some(part) => {
                self.grow(part.len());
                for part in splits {
                    self.new_row();
                    if self.cursor.col + part.len() == self.tsize.col as usize {
                        self.stdout.write_char(NL).unwrap();
                    }
                    self.grow(part.len());
                }
            },
            _ => {}
        }
    }

    pub fn errf(&mut self, args:fmt::Arguments) {
        self.err(fmt::format(args).as_slice());
    }

    pub fn del(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col > 1 {
            self.stdout.write_char(DEL).unwrap();
            self.shrink(1);
        } else {
            self.shrink(1);
            self.move_to_pointer();
        }
    }

    pub fn read(&mut self) -> old_io::IoResult<char> {
        // Below lifted almost verbatim from rust's read_char.
        // In compliance with MIT, nothing to worry about
        let first_byte = try!(self.stdin.read_byte());
        let width = utf8_char_width(first_byte);
        if width == 1 { return Ok(first_byte as char) }
        if width == 0 { return Err(old_io::standard_error(InvalidInput)) } // not utf8
        let mut buf = [first_byte, 0, 0, 0];
        {
            let mut start = 1;
            while start < width {
                match try!(self.stdin.read(&mut buf[start..width])) {
                    n if n == width - start => break,
                    n if n < width - start => { start += n; }
                    _ => return Err(old_io::standard_error(InvalidInput)),
                }
            }
        }
        match str::from_utf8(&buf[..width]).ok() {
            Some(s) => Ok(s.char_at(0)),
            None => Err(old_io::standard_error(InvalidInput))
        }
    }

    pub fn cursor_left(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col > 1 {
            self.stdout.write_char(DEL).unwrap();
            self.move_left(1);
        } else {
            self.move_left(1);
            self.move_to_pointer();
        }
    }

    pub fn cursor_right(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if self.cursor.col < self.row_length() {
            self.stdout.write_str(CRSR_RIGHT).unwrap();
            self.move_right(1);
        } else {
            self.move_right(1);
            self.move_to_pointer();
        }
    }

    pub fn cursors_left(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if by == 0 {
            return;
        } else if by <= 3 && self.cursor.col > by {
            self.stdout.write_str(build_string(DEL, by).as_slice()).unwrap();
            self.move_left(by);
        } else if self.cursor.col > by {
            self.stdout.write_fmt(format_args!("{}{}D", ANSI_BEGIN, by)).unwrap();
            self.move_left(by);
        } else {
            self.move_left(by);
            self.move_to_pointer();
        }
    }

    pub fn cursors_right(&mut self, by:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        if by == 0 {
            return;
        } else if by + self.cursor.col <= self.row_length() {
            self.stdout.write_fmt(format_args!("{}{}C", ANSI_BEGIN, by)).unwrap();
            self.move_right(by);
        } else {
            self.move_right(by);
            self.move_to_pointer();
        }
    }

    pub fn clear_line(&mut self) {
        self.stdout.write_str(ANSI_BEGIN).unwrap();
        self.stdout.write_char('K').unwrap();
        let col = self.cursor.col;
        self.save_row(col);
    }

    pub fn clear_line_to(&mut self, len:usize) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        let old = self.cursor;
        let mut total = self.cursor.col + len;
        let mut rlen = self.row_length();
        loop {
            self.clear_line();
            if total > rlen {
                total -= rlen;
                self.next_start();
                rlen = self.row_length();
            } else {
                break;
            }
        }
        self.move_to(old);
    }

    pub fn next_start(&mut self) {
        if self.tsize.col == 0 || self.tsize.row == 0 {return}
        self.new_row();
        let row = self.cursor.row;
        self.move_to(Position {
            col: 1,
            row: row
        });
    }

    pub fn flush(&mut self) {
        self.stdout.flush().unwrap();
        self.stderr.flush().unwrap();
    }

    pub fn query_cursor(&mut self) {
        self.stdout.write_str(CRSR_POS).unwrap();
    }

    fn move_to_pointer(&mut self) {
        let (row, col) = (self.cursor.row, self.cursor.col);
        self.stdout.write_fmt(format_args!("{}{};{}f", ANSI_BEGIN, row, col)).unwrap();
    }

    pub fn move_to(&mut self, pos:Position) {
        self.cursor = pos;
        self.move_to_pointer();
    }

    pub fn bell(&mut self) {
        self.stdout.write_char(BEL).unwrap();
    }
}

<|endoftext|>


<commit_before>extern crate cc;
extern crate pkg_config;

use std::{env, fs, io::Write, path::Path, process::Command};

use wayland_scanner::{generate_code, Side};

fn main() {
    dump_git_version();
    build_wayland_glib_interface();
    generate_custom_protocols();
}

/// Writes the current git hash to a file that is read by Way Cooler
///
/// If this is a release build, the file will be empty.
fn dump_git_version() {
    let out_dir = env::var("OUT_DIR").expect("Could not find out directory!");
    let dest_path = Path::new(&out_dir).join("git-version.txt");
    let mut f = fs::File::create(&dest_path)
        .expect("Could not write git version to out directory");
    if let Some(git_version) = git_version() {
        f.write_all(git_version.as_ref())
            .expect("Could not write to git version file");
    }
}

/// Gets the current hash of HEAD. Returns None if for some reason
/// that could not be retrieved (e.g not in a git repository)
fn git_version() -> Option<String> {
    if !in_release_commit() {
        Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .ok()
            .map(|output| output.stdout)
            .map(|hash| String::from_utf8_lossy(&hash).trim().into())
    } else {
        None
    }
}

/// Determines if the current HEAD is tagged with a release
fn in_release_commit() -> bool {
    let result = Command::new("git")
        .arg("describe")
        .arg("--exact-match")
        .arg("--tags")
        .arg("HEAD")
        .output()
        .unwrap();
    result.status.success()
}

/// Build the wayland-glib interface as a static library
fn build_wayland_glib_interface() {
    let glib = pkg_config::probe_library("glib-2.0").unwrap();
    let dbus = pkg_config::probe_library("dbus-1").unwrap();
    let wayland = pkg_config::probe_library("wayland-client").unwrap();

    let mut builder = cc::Build::new();

    let include_paths = glib
        .include_paths
        .iter()
        .chain(dbus.include_paths.iter())
        .chain(wayland.include_paths.iter());

    for path in include_paths {
        builder.include(path);
    }

    builder
        .file("src/wayland_glib_interface.c")
        .compile("wayland_glib_interface");
    println!("cargo:rustc-flags=-l wayland-client");
}

fn generate_custom_protocols() {
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    let protocol = "../protocols/way-cooler-mousegrabber-unstable-v1.xml";

    generate_code(protocol, out_dir.join("mouse_grabber_api.rs"), Side::Client);

    println!("cargo:rerun-if-changed={}", protocol);
}
<commit_msg>Generate all protocols in ../protocols<commit_after>extern crate cc;
extern crate pkg_config;

use std::{env, fs, io::Write, path::Path, process::Command};

use wayland_scanner::{generate_code, Side};

const PROTOCOL_DIR: &str = "../protocols";

fn main() {
    dump_git_version();
    build_wayland_glib_interface();
    generate_custom_protocols();
}

/// Writes the current git hash to a file that is read by Way Cooler
///
/// If this is a release build, the file will be empty.
fn dump_git_version() {
    let out_dir = env::var("OUT_DIR").expect("Could not find out directory!");
    let dest_path = Path::new(&out_dir).join("git-version.txt");
    let mut f = fs::File::create(&dest_path)
        .expect("Could not write git version to out directory");
    if let Some(git_version) = git_version() {
        f.write_all(git_version.as_ref())
            .expect("Could not write to git version file");
    }
}

/// Gets the current hash of HEAD. Returns None if for some reason
/// that could not be retrieved (e.g not in a git repository)
fn git_version() -> Option<String> {
    if !in_release_commit() {
        Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .ok()
            .map(|output| output.stdout)
            .map(|hash| String::from_utf8_lossy(&hash).trim().into())
    } else {
        None
    }
}

/// Determines if the current HEAD is tagged with a release
fn in_release_commit() -> bool {
    let result = Command::new("git")
        .arg("describe")
        .arg("--exact-match")
        .arg("--tags")
        .arg("HEAD")
        .output()
        .unwrap();
    result.status.success()
}

/// Build the wayland-glib interface as a static library
fn build_wayland_glib_interface() {
    let glib = pkg_config::probe_library("glib-2.0").unwrap();
    let dbus = pkg_config::probe_library("dbus-1").unwrap();
    let wayland = pkg_config::probe_library("wayland-client").unwrap();

    let mut builder = cc::Build::new();

    let include_paths = glib
        .include_paths
        .iter()
        .chain(dbus.include_paths.iter())
        .chain(wayland.include_paths.iter());

    for path in include_paths {
        builder.include(path);
    }

    builder
        .file("src/wayland_glib_interface.c")
        .compile("wayland_glib_interface");
    println!("cargo:rustc-flags=-l wayland-client");
}

fn generate_custom_protocols() {
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    let protocols =
        fs::read_dir(PROTOCOL_DIR).expect("../protocols does not exist");
    for protocol in protocols {
        let protocol = protocol.expect("Could not read protocol");
        let path = protocol.path();

        let is_xml = path
            .extension()
            .map(|extension| extension == "xml")
            .unwrap_or(false);
        if protocol.file_type().unwrap().is_dir() || !is_xml {
            continue;
        }

        generate_code(path, out_dir.join("mouse_grabber_api.rs"), Side::Client);
    }

    println!("cargo:rerun-if-changed={}", PROTOCOL_DIR);
}
<|endoftext|>


<commit_before>//! A set of builders used to make using methods on certain structs simpler to
//! use.
//!
//! These are used when not all parameters are required, all parameters are
//! optional, and/or sane default values for required parameters can be applied
//! by a builder.

mod create_channel;
mod create_embed;

#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod create_interaction;

mod create_allowed_mentions;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(feature = "unstable_discord_api"))]
mod create_interaction_response;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(feature = "unstable_discord_api"))]
mod create_interaction_response_followup;
mod create_invite;
mod create_message;
mod edit_channel;
mod edit_guild;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(feature = "unstable_discord_api"))]
mod edit_interaction_response;
mod edit_member;
mod edit_message;
mod edit_profile;
mod edit_role;
mod execute_webhook;
mod get_messages;

pub use self::{
    create_allowed_mentions::CreateAllowedMentions,
    create_allowed_mentions::ParseValue,
    create_channel::CreateChannel,
    create_embed::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, Timestamp},
    create_invite::CreateInvite,
    create_message::CreateMessage,
    edit_channel::EditChannel,
    edit_guild::EditGuild,
    edit_member::EditMember,
    edit_message::EditMessage,
    edit_profile::EditProfile,
    edit_role::EditRole,
    execute_webhook::ExecuteWebhook,
    get_messages::GetMessages,
};
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
pub use self::{
    create_interaction::{CreateInteraction, CreateInteractionOption},
    create_interaction_response::{CreateInteractionResponse, CreateInteractionResponseData},
    create_interaction_response_followup::CreateInteractionResponseFollowup,
    edit_interaction_response::EditInteractionResponse,
};
<commit_msg>Fix invalid usage of `#[doc(cfg)]` (#1250)<commit_after>//! A set of builders used to make using methods on certain structs simpler to
//! use.
//!
//! These are used when not all parameters are required, all parameters are
//! optional, and/or sane default values for required parameters can be applied
//! by a builder.

mod create_channel;
mod create_embed;

#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod create_interaction;

mod create_allowed_mentions;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod create_interaction_response;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod create_interaction_response_followup;
mod create_invite;
mod create_message;
mod edit_channel;
mod edit_guild;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod edit_interaction_response;
mod edit_member;
mod edit_message;
mod edit_profile;
mod edit_role;
mod execute_webhook;
mod get_messages;

pub use self::{
    create_allowed_mentions::CreateAllowedMentions,
    create_allowed_mentions::ParseValue,
    create_channel::CreateChannel,
    create_embed::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, Timestamp},
    create_invite::CreateInvite,
    create_message::CreateMessage,
    edit_channel::EditChannel,
    edit_guild::EditGuild,
    edit_member::EditMember,
    edit_message::EditMessage,
    edit_profile::EditProfile,
    edit_role::EditRole,
    execute_webhook::ExecuteWebhook,
    get_messages::GetMessages,
};
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
pub use self::{
    create_interaction::{CreateInteraction, CreateInteractionOption},
    create_interaction_response::{CreateInteractionResponse, CreateInteractionResponseData},
    create_interaction_response_followup::CreateInteractionResponseFollowup,
    edit_interaction_response::EditInteractionResponse,
};
<|endoftext|>


<commit_before>extern crate arguments;
extern crate hiredis;
extern crate mcpat;
extern crate sql;
extern crate sqlite;

#[macro_use]
extern crate log;

/// Raise an error.
#[macro_export]
macro_rules! raise(
    ($message:expr) => (return Err($crate::Error::new($message)));
);

/// Unwrap a result or raise an error.
#[macro_export]
macro_rules! ok(
    ($result:expr) => (
        match $result {
            Ok(result) => result,
            Err(error) => raise!(error),
        }
    );
);

mod result;
mod system;

pub mod database;
pub mod server;

pub use result::{Error, Result};
pub use system::System;
<commit_msg>Add a description to the library<commit_after>//! Recording of workload patterns.

extern crate arguments;
extern crate hiredis;
extern crate mcpat;
extern crate sql;
extern crate sqlite;

#[macro_use]
extern crate log;

/// Raise an error.
#[macro_export]
macro_rules! raise(
    ($message:expr) => (return Err($crate::Error::new($message)));
);

/// Unwrap a result or raise an error.
#[macro_export]
macro_rules! ok(
    ($result:expr) => (
        match $result {
            Ok(result) => result,
            Err(error) => raise!(error),
        }
    );
);

mod result;
mod system;

pub mod database;
pub mod server;

pub use result::{Error, Result};
pub use system::System;
<|endoftext|>


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

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn(&[~str])),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static COMMANDS: &'static [Command<'static>] = &'static [
    Command {
        cmd: "build",
        action: CallMain("rustc", rustc::main_args),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command {
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command {
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~\"\n\nUsage:\trust test <filename>"
        )
    },
    Command {
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main_args),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command {
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main_args),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command {
        cmd: "sketch",
        action: CallMain("rusti", rusti::main_args),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command {
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find |command| {
        command.cmd == command_string
    }.map_move(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename] => {
            let p = Path(*filename);
            let test_exec = p.filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main_args);
            let exit_code = run::process_status(~"./" + test_exec, []);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let p = Path(*filename);
            let exec = p.filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main_args);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    f(osargs);
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for command in COMMANDS.iter() {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    #[fixed_stack_segment]; #[inline(never)];

    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for command in r.iter() {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<commit_msg>auto merge of #9213 : dcrewi/rust/rust-test-arguments, r=catamorphism<commit_after>// Copyright 2013 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.

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn(&[~str])),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static COMMANDS: &'static [Command<'static>] = &'static [
    Command {
        cmd: "build",
        action: CallMain("rustc", rustc::main_args),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command {
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command {
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~ [<arguments>...]\"\
            \n\nUsage:\trust test <filename> [<arguments>...]"
        )
    },
    Command {
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main_args),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command {
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main_args),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command {
        cmd: "sketch",
        action: CallMain("rusti", rusti::main_args),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command {
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find |command| {
        command.cmd == command_string
    }.map_move(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let p = Path(*filename);
            let test_exec = p.filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main_args);
            let exit_code = run::process_status(~"./" + test_exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let p = Path(*filename);
            let exec = p.filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main_args);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    f(osargs);
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for command in COMMANDS.iter() {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    #[fixed_stack_segment]; #[inline(never)];

    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for command in r.iter() {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<|endoftext|>