<commit_before>#[macro_use]
extern crate glium;

use glium::{index, Surface};
use glium::index::PrimitiveType;
use glium::program::ShaderStage;
use glium::backend::Facade;
use glium::CapabilitiesSource;
use glium::DrawError;

mod support;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

implement_vertex!(Vertex, position);

#[test]
fn subroutine_bindings_simple() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = program!(&display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require

                out vec4 fragColor;
                subroutine vec4 color_t();

                subroutine uniform color_t Color;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                void main()
                {
                    fragColor = Color();
                }
            "
        },
    ).unwrap();
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (255, 0, 0, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));

    display.assert_no_error(None);
}

#[test]
fn subroutine_bindings_explicit_location() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = program!(&display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require
                #extension GL_ARB_explicit_uniform_location : require

                out vec4 fragColor;
                subroutine vec4 color_t();

                layout(location = 5) subroutine uniform color_t Color;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                void main()
                {
                    fragColor = Color();
                }
            "
        },
    ).unwrap();
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (255, 0, 0, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));

    display.assert_no_error(None);
}

// Start of more complex tests with multiple uniforms and such.
// Unfortunately, mesa has a bug which produces a segfault when compiling this fragment shader.
// https://bugs.freedesktop.org/show_bug.cgi?id=93722

fn build_program_complex(display: &glium::Display) -> glium::Program {
    let program = program!(display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require

                out vec4 fragColor;
                subroutine vec4 color_t();
                subroutine vec4 modify_t(vec4 color);

                subroutine uniform color_t Color;
                subroutine uniform modify_t Modify;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                subroutine(modify_t)
                vec4 SwapRB(vec4 color)
                {
                  return vec4(color.b, color.g, color.r, color.a);
                }

                subroutine(modify_t)
                vec4 DeleteR(vec4 color)
                {
                  return vec4(0, color.g, color.b, color.a);
                }

                void main()
                {
                    vec4 color = Color();
                    fragColor = Modify(color);
                }
            "
        },
    ).unwrap();
    program
}

#[test]
fn subroutine_bindings_multi() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        Modify: ("DeleteR", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
        Modify: ("SwapRB", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);
}

#[test]
fn not_all_uniforms_set() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        // Not setting Modify on purpose
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()) {
                                  Err(DrawError::SubroutineUniformMissing{ .. }) => (),
                                  _ => panic!("Drawing should have errored")
                              }

    display.assert_no_error(None);
}

#[test]
fn mismatched_subroutines() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        Modify: ("ColorBlue", ShaderStage::Fragment)
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()) {
                                  Err(DrawError::SubroutineNotFound{ .. }) => (),
                                  _ => panic!("Drawing should have errored")
                              }

    display.assert_no_error(None);
}
<commit_msg>Ignore tests that fail due to mesa bugs<commit_after>#[macro_use]
extern crate glium;

use glium::{index, Surface};
use glium::index::PrimitiveType;
use glium::program::ShaderStage;
use glium::backend::Facade;
use glium::CapabilitiesSource;
use glium::DrawError;

mod support;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

implement_vertex!(Vertex, position);

#[test]
fn subroutine_bindings_simple() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = program!(&display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require

                out vec4 fragColor;
                subroutine vec4 color_t();

                subroutine uniform color_t Color;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                void main()
                {
                    fragColor = Color();
                }
            "
        },
    ).unwrap();
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (255, 0, 0, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));

    display.assert_no_error(None);
}

#[test]
#[ignore] // This seems to be buggy in almost every implementation, so ignore.
fn subroutine_bindings_explicit_location() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = program!(&display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require
                #extension GL_ARB_explicit_uniform_location : require

                out vec4 fragColor;
                subroutine vec4 color_t();

                layout(location = 5) subroutine uniform color_t Color;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                void main()
                {
                    fragColor = Color();
                }
            "
        },
    ).unwrap();
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (255, 0, 0, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));

    display.assert_no_error(None);
}

// Start of more complex tests with multiple uniforms and such.
// Unfortunately, mesa has a bug which produces a segfault when compiling this fragment shader.
// See https://bugs.freedesktop.org/show_bug.cgi?id=93722
// On non-mesa OpenGL implementations, the tests pass just fine.

fn build_program_complex(display: &glium::Display) -> glium::Program {
    let program = program!(display,
        330 => {
            vertex: "
                #version 330

                in vec2 position;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0);
                }
            ",

            fragment: "
                #version 330
                #extension GL_ARB_shader_subroutine : require

                out vec4 fragColor;
                subroutine vec4 color_t();
                subroutine vec4 modify_t(vec4 color);

                subroutine uniform color_t Color;
                subroutine uniform modify_t Modify;

                subroutine(color_t)
                vec4 ColorRed()
                {
                  return vec4(1, 0, 0, 1);
                }

                subroutine(color_t)
                vec4 ColorBlue()
                {
                  return vec4(0, 0, 1, 1);
                }

                subroutine(modify_t)
                vec4 SwapRB(vec4 color)
                {
                  return vec4(color.b, color.g, color.r, color.a);
                }

                subroutine(modify_t)
                vec4 DeleteR(vec4 color)
                {
                  return vec4(0, color.g, color.b, color.a);
                }

                void main()
                {
                    vec4 color = Color();
                    fragColor = Modify(color);
                }
            "
        },
    ).unwrap();
    program
}

#[test]
#[ignore]
fn subroutine_bindings_multi() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        Modify: ("DeleteR", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);

    let uniforms = uniform!(
        Color: ("ColorRed", ShaderStage::Fragment),
        Modify: ("SwapRB", ShaderStage::Fragment),
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();

    assert_eq!(data[0][0], (0, 0, 255, 255));
    assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));

    display.assert_no_error(None);
}

#[test]
#[ignore]
fn not_all_uniforms_set() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        // Not setting Modify on purpose
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()) {
                                  Err(DrawError::SubroutineUniformMissing{ .. }) => (),
                                  _ => panic!("Drawing should have errored")
                              }

    display.assert_no_error(None);
}

#[test]
#[ignore]
fn mismatched_subroutines() {
    let display = support::build_display();
    if !display.get_context().get_extensions().gl_arb_shader_subroutine {
        println!("Backend does not support subroutines");
        return
    };

    let program = build_program_complex(&display);
    let vb = glium::VertexBuffer::new(&display, &[
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]).unwrap();

    let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                          &[0u16, 1, 2, 2, 1, 3]).unwrap();

    let texture = support::build_renderable_texture(&display);

    let uniforms = uniform!(
        Color: ("ColorBlue", ShaderStage::Fragment),
        Modify: ("ColorBlue", ShaderStage::Fragment)
    );
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
                              &Default::default()) {
                                  Err(DrawError::SubroutineNotFound{ .. }) => (),
                                  _ => panic!("Drawing should have errored")
                              }

    display.assert_no_error(None);
}
<|endoftext|>


<commit_before>#![allow(unused)]

use std::{
    collections::VecDeque,
    env,
    io::{self, BufRead, Write},
    marker::Unpin,
    str,
    sync::{
        mpsc::{sync_channel, Receiver, SyncSender, TryRecvError},
        Arc,
    },
};

use {
    futures::{compat::*, prelude::*},
    jsonrpc_core::{
        id::Id,
        params::Params,
        request::{Call, MethodCall, Notification},
        response::{Output, Response},
        version::Version,
    },
    lsp_types::*,
    serde::{de::DeserializeOwned, Serialize},
    serde_json::{from_str, from_value, ser::Serializer, to_value, Value},
    tokio::io::{AsyncBufRead, AsyncWrite, AsyncWriteExt, BufReader},
    tokio_util::codec::{Decoder, FramedRead},
    url::Url,
};

use gluon::ThreadExt;
use gluon_language_server::rpc::LanguageServerDecoder;

pub fn test_url(uri: &str) -> Url {
    Url::from_file_path(&env::current_dir().unwrap().join(uri)).unwrap()
}

pub async fn write_message<W, V>(writer: &mut W, value: V) -> io::Result<()>
where
    W: ?Sized + AsyncWrite + Unpin,
    V: Serialize,
{
    let mut vec = Vec::new();
    value.serialize(&mut Serializer::new(&mut vec)).unwrap();
    writer
        .write_all(
            format!(
                "Content-Length: {}\r\n\r\n{}",
                vec.len(),
                str::from_utf8(&vec).unwrap()
            )
            .as_bytes(),
        )
        .await
}

pub fn method_call<T>(method: &str, id: u64, value: T) -> Call
where
    T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Ok(Value::Object(map)) => Params::Map(map),
        Ok(Value::Null) => Params::None,
        _ => panic!("Expected map"),
    };
    Call::MethodCall(MethodCall {
        jsonrpc: Some(Version::V2),
        method: method.into(),
        id: Id::Num(id),
        params,
    })
}

pub fn notification<T>(method: &str, value: T) -> Call
where
    T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Ok(Value::Object(map)) => Params::Map(map),
        Ok(Value::Null) => Params::None,
        _ => panic!("Expected map or null"),
    };
    Call::Notification(Notification {
        jsonrpc: Some(Version::V2),
        method: method.into(),
        params,
    })
}

pub async fn did_open_uri<W: ?Sized>(stdin: &mut W, uri: Url, text: &str)
where
    W: AsyncWrite + Unpin,
{
    let did_open = notification(
        "textDocument/didOpen",
        DidOpenTextDocumentParams {
            text_document: TextDocumentItem {
                uri: uri,
                language_id: "gluon".into(),
                text: text.into(),
                version: 1,
            },
        },
    );

    write_message(stdin, did_open).await.unwrap();
}

pub async fn did_open<W: ?Sized>(stdin: &mut W, uri: &str, text: &str)
where
    W: AsyncWrite + Unpin,
{
    did_open_uri(stdin, test_url(uri), text).await
}

pub async fn did_change<W: ?Sized>(stdin: &mut W, uri: &str, version: i64, range: Range, text: &str)
where
    W: AsyncWrite + Unpin,
{
    did_change_event(
        stdin,
        uri,
        version,
        vec![TextDocumentContentChangeEvent {
            range: Some(range),
            range_length: None,
            text: text.to_string(),
        }],
    )
    .await
}

pub async fn did_change_event<W: ?Sized>(
    stdin: &mut W,
    uri: &str,
    version: i64,
    content_changes: Vec<TextDocumentContentChangeEvent>,
) where
    W: AsyncWrite + Unpin,
{
    let hover = notification(
        "textDocument/didChange",
        DidChangeTextDocumentParams {
            text_document: VersionedTextDocumentIdentifier {
                uri: test_url(uri),
                version: Some(version),
            },
            content_changes,
        },
    );

    write_message(stdin, hover).await.unwrap();
}

async fn read_until<T>(
    output: impl AsyncBufRead + Unpin,
    mut f: impl FnMut(String) -> Option<T>,
) -> T {
    let stream = FramedRead::new(output, LanguageServerDecoder::new()).try_filter_map(|s| {
        let x = f(s);
        async { Ok(x) }
    });
    futures::pin_mut!(stream);
    stream
        .next()
        .await
        .expect("Expected a response")
        .expect("Success")
}

pub async fn expect_response<R, T>(output: R) -> T
where
    T: DeserializeOwned,
    R: AsyncBufRead + Unpin,
{
    read_until(output, |json| {
        // Skip all notifications
        if let Ok(Notification { .. }) = from_str(&json) {
            None
        } else if let Ok(Response::Single(Output::Success(response))) = from_str(&json) {
            Some(from_value(response.result).unwrap_or_else(|err| panic!("{}\n{}", err, json)))
        } else {
            panic!("Expected response, got `{}`", json)
        }
    })
    .await
}

pub async fn hover<W: ?Sized>(stdin: &mut W, id: u64, uri: &str, position: Position)
where
    W: AsyncWrite + Unpin,
{
    let hover = method_call(
        "textDocument/hover",
        id,
        TextDocumentPositionParams {
            text_document: TextDocumentIdentifier { uri: test_url(uri) },
            position: position,
        },
    );

    write_message(stdin, hover).await.unwrap();
}

pub async fn expect_notification<R, T>(output: R) -> T
where
    T: DeserializeOwned,
    R: AsyncBufRead + Unpin,
{
    read_until(output, |json| {
        Some(match from_str(&json) {
            Ok(Notification { params, .. }) => {
                let json_value = match params {
                    Params::Map(map) => Value::Object(map),
                    Params::Array(array) => Value::Array(array),
                    Params::None => Value::Null,
                };
                return from_value(json_value).unwrap();
            }
            Ok(_) => panic!("Expected notification\n{}", json),
            Err(err) => panic!("Expected notification, got `{}`\n{}", err, json),
        })
    })
    .await
}

pub fn run_no_panic_catch<F>(fut: F)
where
    F: Future<Output = ()> + Send + 'static,
{
    tokio::runtime::Runtime::new().unwrap().block_on(fut)
}

struct ServerHandle {
    stdin: Box<dyn AsyncWrite + Send + Unpin>,
    stdout: Box<dyn AsyncBufRead + Send + Unpin>,
}

fn start_local() -> ServerHandle {
    let (mut stdin_write, stdin_read) = async_pipe::pipe();
    let (stdout_write, stdout_read) = async_pipe::pipe();
    let stdout_read = BufReader::new(stdout_read);

    tokio::spawn(async move {
        let thread = gluon::new_vm_async().await;
        thread.get_database_mut().set_implicit_prelude(false);
        if let Err(err) =
            ::gluon_language_server::Server::start(thread, stdin_read, stdout_write).await
        {
            panic!("{}", err)
        }
    });
    ServerHandle {
        stdin: Box::new(stdin_write),
        stdout: Box::new(stdout_read),
    }
}

fn start_remote() -> ServerHandle {
    use std::process::Stdio;
    use tokio::process::Command;

    let mut child = Command::new("target/debug/gluon_language-server")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    ServerHandle {
        stdin: Box::new(child.stdin.expect("stdin")),
        stdout: Box::new(BufReader::new(child.stdout.expect("stdout"))),
    }
}

pub fn send_rpc<F>(f: F)
where
    F: for<'a> FnOnce(
            &'a mut (dyn AsyncWrite + Send + Unpin),
            &'a mut (dyn AsyncBufRead + Send + Unpin),
        ) -> futures::future::BoxFuture<'a, ()>
        + Send
        + ::std::panic::UnwindSafe
        + 'static,
{
    run_no_panic_catch(async move {
        let ServerHandle {
            mut stdin,
            mut stdout,
        } = if env::var("GLUON_TEST_LOCAL_SERVER").is_ok() {
            // FIXME Local  testing may deadlock atm
            start_local()
        } else {
            start_remote()
        };

        {
            f(&mut stdin, &mut stdout).await;

            write_message(&mut stdin, method_call("shutdown", 1_000_000, ()))
                .await
                .unwrap();

            let () = expect_response(&mut stdout).await;

            let exit = Call::Notification(Notification {
                jsonrpc: Some(Version::V2),
                method: "exit".into(),
                params: Params::None,
            });
            write_message(&mut stdin, exit).await.unwrap();
            drop(stdin);
        }
    })
}
<commit_msg>Only run with one thread per test<commit_after>#![allow(unused)]

use std::{
    collections::VecDeque,
    env,
    io::{self, BufRead, Write},
    marker::Unpin,
    str,
    sync::{
        mpsc::{sync_channel, Receiver, SyncSender, TryRecvError},
        Arc,
    },
};

use {
    futures::{compat::*, prelude::*},
    jsonrpc_core::{
        id::Id,
        params::Params,
        request::{Call, MethodCall, Notification},
        response::{Output, Response},
        version::Version,
    },
    lsp_types::*,
    serde::{de::DeserializeOwned, Serialize},
    serde_json::{from_str, from_value, ser::Serializer, to_value, Value},
    tokio::io::{AsyncBufRead, AsyncWrite, AsyncWriteExt, BufReader},
    tokio_util::codec::{Decoder, FramedRead},
    url::Url,
};

use gluon::ThreadExt;
use gluon_language_server::rpc::LanguageServerDecoder;

pub fn test_url(uri: &str) -> Url {
    Url::from_file_path(&env::current_dir().unwrap().join(uri)).unwrap()
}

pub async fn write_message<W, V>(writer: &mut W, value: V) -> io::Result<()>
where
    W: ?Sized + AsyncWrite + Unpin,
    V: Serialize,
{
    let mut vec = Vec::new();
    value.serialize(&mut Serializer::new(&mut vec)).unwrap();
    writer
        .write_all(
            format!(
                "Content-Length: {}\r\n\r\n{}",
                vec.len(),
                str::from_utf8(&vec).unwrap()
            )
            .as_bytes(),
        )
        .await
}

pub fn method_call<T>(method: &str, id: u64, value: T) -> Call
where
    T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Ok(Value::Object(map)) => Params::Map(map),
        Ok(Value::Null) => Params::None,
        _ => panic!("Expected map"),
    };
    Call::MethodCall(MethodCall {
        jsonrpc: Some(Version::V2),
        method: method.into(),
        id: Id::Num(id),
        params,
    })
}

pub fn notification<T>(method: &str, value: T) -> Call
where
    T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Ok(Value::Object(map)) => Params::Map(map),
        Ok(Value::Null) => Params::None,
        _ => panic!("Expected map or null"),
    };
    Call::Notification(Notification {
        jsonrpc: Some(Version::V2),
        method: method.into(),
        params,
    })
}

pub async fn did_open_uri<W: ?Sized>(stdin: &mut W, uri: Url, text: &str)
where
    W: AsyncWrite + Unpin,
{
    let did_open = notification(
        "textDocument/didOpen",
        DidOpenTextDocumentParams {
            text_document: TextDocumentItem {
                uri: uri,
                language_id: "gluon".into(),
                text: text.into(),
                version: 1,
            },
        },
    );

    write_message(stdin, did_open).await.unwrap();
}

pub async fn did_open<W: ?Sized>(stdin: &mut W, uri: &str, text: &str)
where
    W: AsyncWrite + Unpin,
{
    did_open_uri(stdin, test_url(uri), text).await
}

pub async fn did_change<W: ?Sized>(stdin: &mut W, uri: &str, version: i64, range: Range, text: &str)
where
    W: AsyncWrite + Unpin,
{
    did_change_event(
        stdin,
        uri,
        version,
        vec![TextDocumentContentChangeEvent {
            range: Some(range),
            range_length: None,
            text: text.to_string(),
        }],
    )
    .await
}

pub async fn did_change_event<W: ?Sized>(
    stdin: &mut W,
    uri: &str,
    version: i64,
    content_changes: Vec<TextDocumentContentChangeEvent>,
) where
    W: AsyncWrite + Unpin,
{
    let hover = notification(
        "textDocument/didChange",
        DidChangeTextDocumentParams {
            text_document: VersionedTextDocumentIdentifier {
                uri: test_url(uri),
                version: Some(version),
            },
            content_changes,
        },
    );

    write_message(stdin, hover).await.unwrap();
}

async fn read_until<T>(
    output: impl AsyncBufRead + Unpin,
    mut f: impl FnMut(String) -> Option<T>,
) -> T {
    let stream = FramedRead::new(output, LanguageServerDecoder::new()).try_filter_map(|s| {
        let x = f(s);
        async { Ok(x) }
    });
    futures::pin_mut!(stream);
    stream
        .next()
        .await
        .expect("Expected a response")
        .expect("Success")
}

pub async fn expect_response<R, T>(output: R) -> T
where
    T: DeserializeOwned,
    R: AsyncBufRead + Unpin,
{
    read_until(output, |json| {
        // Skip all notifications
        if let Ok(Notification { .. }) = from_str(&json) {
            None
        } else if let Ok(Response::Single(Output::Success(response))) = from_str(&json) {
            Some(from_value(response.result).unwrap_or_else(|err| panic!("{}\n{}", err, json)))
        } else {
            panic!("Expected response, got `{}`", json)
        }
    })
    .await
}

pub async fn hover<W: ?Sized>(stdin: &mut W, id: u64, uri: &str, position: Position)
where
    W: AsyncWrite + Unpin,
{
    let hover = method_call(
        "textDocument/hover",
        id,
        TextDocumentPositionParams {
            text_document: TextDocumentIdentifier { uri: test_url(uri) },
            position: position,
        },
    );

    write_message(stdin, hover).await.unwrap();
}

pub async fn expect_notification<R, T>(output: R) -> T
where
    T: DeserializeOwned,
    R: AsyncBufRead + Unpin,
{
    read_until(output, |json| {
        Some(match from_str(&json) {
            Ok(Notification { params, .. }) => {
                let json_value = match params {
                    Params::Map(map) => Value::Object(map),
                    Params::Array(array) => Value::Array(array),
                    Params::None => Value::Null,
                };
                return from_value(json_value).unwrap();
            }
            Ok(_) => panic!("Expected notification\n{}", json),
            Err(err) => panic!("Expected notification, got `{}`\n{}", err, json),
        })
    })
    .await
}

pub fn run_no_panic_catch<F>(fut: F)
where
    F: Future<Output = ()> + Send + 'static,
{
    tokio::runtime::Builder::new()
        .enable_all()
        .core_threads(1)
        .basic_scheduler()
        .build()
        .unwrap()
        .block_on(fut)
}

struct ServerHandle {
    stdin: Box<dyn AsyncWrite + Send + Unpin>,
    stdout: Box<dyn AsyncBufRead + Send + Unpin>,
}

fn start_local() -> ServerHandle {
    let (mut stdin_write, stdin_read) = async_pipe::pipe();
    let (stdout_write, stdout_read) = async_pipe::pipe();
    let stdout_read = BufReader::new(stdout_read);

    tokio::spawn(async move {
        let thread = gluon::new_vm_async().await;
        thread.get_database_mut().set_implicit_prelude(false);
        if let Err(err) =
            ::gluon_language_server::Server::start(thread, stdin_read, stdout_write).await
        {
            panic!("{}", err)
        }
    });
    ServerHandle {
        stdin: Box::new(stdin_write),
        stdout: Box::new(stdout_read),
    }
}

fn start_remote() -> ServerHandle {
    use std::process::Stdio;
    use tokio::process::Command;

    let mut child = Command::new("target/debug/gluon_language-server")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    ServerHandle {
        stdin: Box::new(child.stdin.expect("stdin")),
        stdout: Box::new(BufReader::new(child.stdout.expect("stdout"))),
    }
}

pub fn send_rpc<F>(f: F)
where
    F: for<'a> FnOnce(
            &'a mut (dyn AsyncWrite + Send + Unpin),
            &'a mut (dyn AsyncBufRead + Send + Unpin),
        ) -> futures::future::BoxFuture<'a, ()>
        + Send
        + ::std::panic::UnwindSafe
        + 'static,
{
    run_no_panic_catch(async move {
        let ServerHandle {
            mut stdin,
            mut stdout,
        } = if env::var("GLUON_TEST_LOCAL_SERVER").is_ok() {
            start_local()
        } else {
            start_remote()
        };

        {
            f(&mut stdin, &mut stdout).await;

            write_message(&mut stdin, method_call("shutdown", 1_000_000, ()))
                .await
                .unwrap();

            let () = expect_response(&mut stdout).await;

            let exit = Call::Notification(Notification {
                jsonrpc: Some(Version::V2),
                method: "exit".into(),
                params: Params::None,
            });
            write_message(&mut stdin, exit).await.unwrap();
            drop(stdin);
        }
    })
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ShellGame {
    vec: Vec<usize>,
    cur: usize,
}
impl ShellGame {
    pub fn new(init: &[usize], max: usize) -> ShellGame {
        let mut vec = Vec::with_capacity(max+1);
        vec.resize(init.len()+1, 0);
        let first = init[0];
        let mut last = first;
        for i in 1..init.len() {
            vec[last] = init[i];
            last = init[i];
        }
        if max > init.len() {
            vec[last] = init.len()+1;
            for i in init.len()+2..=max {
                vec.push(i)
            }
            vec.push(first);
        }
        else {
            vec[last] = first;
        }
        ShellGame { vec, cur: first }
    }

    pub fn shuffle(&mut self) {
        let old = self.cur;
        let a = self.vec[old];
        let b = self.vec[a];
        let c = self.vec[b];
        let mut insert = old;
        loop {
            insert = if insert == 1 { self.vec.len()-1 } else { insert - 1 };
            if insert != a && insert != b && insert != c { break; }
        }
        self.cur = self.vec[c];
        self.vec[c] = self.vec[insert];
        self.vec[insert] = a;
        self.vec[old] = self.cur;
    }

    pub fn ident(&self) -> String {
        let mut rv = String::with_capacity(8);
        let mut idx = 1;
        for _ in 1..9 {
            idx = self.vec[idx];
            rv.push(std::char::from_digit(idx as u32, 36).unwrap());
        }
        return rv;
    }

    pub fn hash(&self) -> usize { self.vec[1] * self.vec[self.vec[1]] }
}

impl std::fmt::Display for ShellGame {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut idx = self.cur;
        for _ in 1..self.vec.len() {
            write!(f, "{},", idx)?;
            idx = self.vec[idx];
        }
        Ok(())
    }
}

fn main() {
    let mut game = ShellGame::new(&[3,8,9,5,4,7,6,1,2], 9);
    for _ in 1..=100 {
        game.shuffle();
    }
    println!("Part 1: identifier {}", game.ident());

    let mut game = ShellGame::new(&[3,8,9,5,4,7,6,1,2], 1_000_000);
    for _ in 1..=10_000_000 {
        game.shuffle();
    }
    println!("Part 2: hash {}", game.hash());
}
<commit_msg>Day 23: half the ram == about half the time<commit_after>// SPDX-License-Identifier: MIT

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ShellGame {
    vec: Vec<u32>,
    cur: usize,
}
impl ShellGame {
    pub fn new(init: &[u32], max: usize) -> ShellGame {
        let mut vec = Vec::with_capacity(max+1);
        vec.resize(init.len()+1, 0);
        let first = init[0];
        let mut last = first;
        for i in 1..init.len() {
            vec[last as usize] = init[i];
            last = init[i];
        }
        if max > init.len() {
            vec[last as usize] = (init.len()+1) as u32;
            for i in init.len()+2..=max {
                vec.push(i as u32)
            }
            vec.push(first);
        }
        else {
            vec[last as usize] = first;
        }
        ShellGame { vec, cur: first as usize }
    }

    pub fn shuffle(&mut self) {
        let old = self.cur;
        let a = self.vec[old] as usize;
        let b = self.vec[a] as usize;
        let c = self.vec[b] as usize;
        let mut insert = old;
        loop {
            insert = if insert == 1 { self.vec.len()-1 } else { insert - 1 };
            if insert != a && insert != b && insert != c { break; }
        }
        self.cur = self.vec[c] as usize;
        self.vec[c] = self.vec[insert];
        self.vec[insert] = a as u32;
        self.vec[old] = self.cur as u32;
    }

    pub fn ident(&self) -> String {
        let mut rv = String::with_capacity(8);
        let mut idx = 1 as usize;
        for _ in 1..9 {
            idx = self.vec[idx] as usize;
            rv.push(std::char::from_digit(idx as u32, 36).unwrap());
        }
        return rv;
    }

    pub fn hash(&self) -> u64 { (self.vec[1] as u64) * (self.vec[self.vec[1] as usize] as u64) }
}

impl std::fmt::Display for ShellGame {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut idx = self.cur;
        for _ in 1..self.vec.len() {
            write!(f, "{},", idx)?;
            idx = self.vec[idx] as usize;
        }
        Ok(())
    }
}

fn main() {
    let mut game = ShellGame::new(&[3,8,9,5,4,7,6,1,2], 9);
    for _ in 1..=100 {
        game.shuffle();
    }
    println!("Part 1: identifier {}", game.ident());

    let mut game = ShellGame::new(&[3,8,9,5,4,7,6,1,2], 1_000_000);
    for _ in 1..=10_000_000 {
        game.shuffle();
    }
    println!("Part 2: hash {}", game.hash());
}
<|endoftext|>


<commit_before>//! Create texture from an alpha channel image in memory.

/// Implemented by textures that can be constructed
/// from an alpha channel image in memory.
pub trait FromMemoryAlpha<D, T> {
    /// Creates texture.
    /// Closure `f` should be called after texture is created.
    fn from_memory_alpha(
        device: &mut D,
        buffer: &[u8], width: u32, height: u32,
        f: |&mut D, T| -> T
    ) -> Option<T>;
}
<commit_msg>Removed second generic parameter<commit_after>//! Create texture from an alpha channel image in memory.

/// Implemented by textures that can be constructed
/// from an alpha channel image in memory.
pub trait FromMemoryAlpha<D> {
    /// Creates texture.
    /// Closure `f` should be called after texture is created.
    fn from_memory_alpha(
        device: &mut D,
        buffer: &[u8], width: u32, height: u32,
        f: |&mut D, Self| -> Self
    ) -> Option<Self>;
}
<|endoftext|>


<commit_before>//! Defines structs and methods that describe a bindings.

use std::collections::HashSet;
use std::fmt;
use std::ops::{Index, IndexMut};
use std::iter::Filter;

use petgraph::graph::NodeIndex;

pub trait RBind {
    type SSARef: fmt::Debug + Clone;
}

/// Trait that describes variable bindings for a function.
pub trait RBindings {
    type BTy: RBind;
    type Idx: Clone + fmt::Debug;

    fn new() -> Self;
    fn insert(&mut self, Self::BTy) -> Self::Idx;

    fn binding(&self, &Self::Idx) -> Option<&Self::BTy>;
    fn binding_mut(&self, &Self::Idx) -> Option<&mut Self::BTy>;

    fn bindings(&self) -> RBinds<Self::BTy>;
    fn bindings_mut(&mut self) -> RBindsMut<Self::BTy>;
}

#[derive(Debug)]
pub struct RBinds<'a, T: 'a + RBind> {
    binds: ::std::slice::Iter<'a, T>,
}

impl<'a, T: 'a + RBind> Iterator for RBinds<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        self.binds.next()
    }
}

#[derive(Debug)]
pub struct RBindsMut<'a, T: 'a + RBind> {
    binds: ::std::slice::IterMut<'a, T>,
}

#[derive(Clone, Debug)]
pub struct RadecoBindings<T: RBind> {
    binds: Vec<T>,
}

impl<BTy: RBind> Index<usize> for RadecoBindings<BTy> {
    type Output = BTy;
    fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
        self.binding(&index).unwrap()
    }
}

impl<BTy: RBind> RBindings for RadecoBindings<BTy> {
    type BTy = BTy;
    type Idx = usize;

    fn new() -> Self {
        unimplemented!()
    }

    fn insert(&mut self, bind: BTy) -> usize {
        unimplemented!()
    }

    fn binding(&self, idx: &usize) -> Option<&BTy> {
        unimplemented!()
    }

    fn binding_mut(&self, idx: &usize) -> Option<&mut BTy> {
        unimplemented!()
    }

    fn bindings(&self) -> RBinds<BTy> {
        unimplemented!()
    }

    fn bindings_mut(&mut self) -> RBindsMut<BTy> {
        unimplemented!()
    }
}

#[derive(Clone, Debug)]
pub struct Binding<T: fmt::Debug + Clone> {
    // Optional name used to represent this binding.
    named: Option<String>,
    // Type of binding.
    vloc: VarLocation,
    dty: VarDataType,
    // Node indices in the function ssa that corresponds to this binding.
    ssa_refs: Vec<T>,
    set: HashSet<VarSet>,
}

impl<'a, T: 'a + RBind> Iterator for RBindsMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        self.binds.next()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum VarLocation {
    Register {
        name: String,
    },
    Memory(MemoryRegion),
    Unknown,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MemoryRegion {
    // Base, offset for function local.
    FunctionLocal {
        base: usize,
        offset: i64,
    },
    Stack,
    Global {
        offset: u64,
    },
    Heap,
    Unknown,
}

// Represents the set to which a variable belongs to in the call summary
// information.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum VarSet {
    Argument,
    Local,
    Modified,
    Preserved,
    Returned,
}

#[derive(Clone, Copy, Debug)]
pub enum VarDataType {
    Unknown(u64),
    Int,
    IntRef,
    Char,
    CharRef,
    Float,
    FloatRef,
    Double,
    DoubleRef,
}

#[derive(Clone, Debug)]
pub struct LocalInfo {
    base: usize,
    offset: i64,
}

impl<T: Clone + fmt::Debug> Default for Binding<T> {
    fn default() -> Binding<T> {
        Binding {
            named: None,
            vloc: VarLocation::Unknown,
            dty: VarDataType::Unknown(64),
            ssa_refs: Vec::new(),
            set: HashSet::new(),
        }
    }
}

impl<T: Clone + fmt::Debug> Binding<T> {
    pub fn is_argument(&self) -> bool {
        self.set.contains(&VarSet::Argument)
    }

    pub fn is_local(&self) -> bool {
        self.set.contains(&VarSet::Local)
    }

    pub fn is_modified(&self) -> bool {
        self.set.contains(&VarSet::Modified)
    }

    pub fn is_preserved(&self) -> bool {
        self.set.contains(&VarSet::Preserved)
    }

    pub fn is_return(&self) -> bool {
        self.set.contains(&VarSet::Returned)
    }

    pub fn mark_argument(&mut self) {
        self.set.insert(VarSet::Argument);
    }

    pub fn mark_local(&mut self) {
        self.set.insert(VarSet::Local);
    }

    pub fn mark_modified(&mut self) {
        self.set.insert(VarSet::Modified);
    }

    pub fn mark_preserved(&mut self) {
        self.set.insert(VarSet::Preserved);
    }

    pub fn mark_return(&mut self) {
        self.set.insert(VarSet::Returned);
    }

    pub fn name(&self) -> String {
        self.named.clone().unwrap_or_else(String::new)
    }

    pub fn is_register(&self) -> bool {
        match self.vloc {
            VarLocation::Register { name: _ } => true,
            _ => false,
        }
    }

    pub fn mark_register(&mut self, name: String) {
        self.vloc = VarLocation::Register { name: name };
    }

    pub fn is_fn_local(&self) -> bool {
        match self.vloc {
            VarLocation::Memory(MemoryRegion::FunctionLocal { base: _, offset: _ }) => true,
            _ => false,
        }
    }

    pub fn mark_fn_local(&mut self, base: usize, offset: i64) {
        self.vloc = VarLocation::Memory(MemoryRegion::FunctionLocal {
            base: base,
            offset: offset,
        });
    }

    pub fn local_info(&self) -> LocalInfo {
        if let VarLocation::Memory(MemoryRegion::FunctionLocal { base, offset }) = self.vloc {
            LocalInfo {
                base: base,
                offset: offset,
            }
        } else {
            panic!()
        }
    }

    pub fn is_stack(&self) -> bool {
        if let VarLocation::Memory(MemoryRegion::Stack) = self.vloc {
            true
        } else {
            false
        }
    }

    pub fn mark_stack(&mut self) {
        self.vloc = VarLocation::Memory(MemoryRegion::Stack);
    }

    pub fn is_global(&self) -> bool {
        match self.vloc {
            VarLocation::Memory(MemoryRegion::Global { offset }) => true,
            _ => false,
        }
    }

    pub fn mark_global(&mut self, offset: u64) {
        self.vloc = VarLocation::Memory(MemoryRegion::Global { offset: offset });
    }

    pub fn global_offset(&self) -> u64 {
        if let VarLocation::Memory(MemoryRegion::Global { offset }) = self.vloc {
            offset
        } else {
            panic!()
        }
    }

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

    pub fn add_refs(&mut self, refs: Vec<T>) {
        self.ssa_refs.extend(refs);
    }

    pub fn refs<'a>(&'a self) -> ::std::slice::Iter<'a, T> {
        self.ssa_refs.iter()
    }
}
<commit_msg>Implements RBind<commit_after>//! Defines structs and methods that describe a bindings.

use std::collections::HashSet;
use std::fmt;
use std::ops::{Index, IndexMut};

pub trait RBind {
    type SSARef: fmt::Debug + Clone;

    fn is_argument(&self) -> bool;
    fn is_local(&self) -> bool;
    fn is_modified(&self) -> bool;
    fn is_preserved(&self) -> bool;
    fn is_return(&self) -> bool;

    fn mark_argument(&mut self);
    fn mark_local(&mut self);
    fn mark_modified(&mut self);
    fn mark_preserved(&mut self);
    fn mark_return(&mut self);

    fn name(&self) -> String;

    fn is_register(&self) -> bool;
    fn mark_register(&mut self, String);

    fn is_fn_local(&self) -> bool;
    fn mark_fn_local(&mut self, usize, i64);
    fn local_info(&self) -> LocalInfo;

    fn is_stack(&self) -> bool;
    fn mark_stack(&mut self);

    fn is_global(&self) -> bool;
    fn mark_global(&mut self, u64);
    fn global_offset(&self) -> u64;

    fn is_unknown(&self) -> bool;

    fn add_refs(&mut self, Vec<Self::SSARef>);
    fn refs<'a>(&'a self) -> ::std::slice::Iter<'a, Self::SSARef>;
}

/// Trait that describes variable bindings for a function.
pub trait RBindings {
    type BTy: RBind;
    type Idx: Clone + fmt::Debug;

    fn new() -> Self;
    fn insert(&mut self, Self::BTy) -> Self::Idx;

    fn binding(&self, &Self::Idx) -> Option<&Self::BTy>;
    fn binding_mut(&mut self, &Self::Idx) -> Option<&mut Self::BTy>;

    fn bindings(&self) -> RBinds<Self::BTy>;
    fn bindings_mut(&mut self) -> RBindsMut<Self::BTy>;
}

#[derive(Debug)]
pub struct RBinds<'a, T: 'a + RBind> {
    binds: ::std::slice::Iter<'a, T>,
}

impl<'a, T: 'a + RBind> Iterator for RBinds<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        self.binds.next()
    }
}

#[derive(Debug)]
pub struct RBindsMut<'a, T: 'a + RBind> {
    binds: ::std::slice::IterMut<'a, T>,
}

#[derive(Clone, Debug)]
pub struct RadecoBindings<T: RBind> {
    binds: Vec<T>,
}

impl<BTy: RBind> Index<usize> for RadecoBindings<BTy> {
    type Output = BTy;
    fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
        self.binding(&index).unwrap()
    }
}

impl<BTy: RBind> RBindings for RadecoBindings<BTy> {
    type BTy = BTy;
    type Idx = usize;

    fn new() -> Self {
        RadecoBindings { binds: Vec::new() }
    }

    fn insert(&mut self, bind: BTy) -> usize {
        self.binds.push(bind);
        self.binds.len() - 1
    }

    fn binding(&self, idx: &usize) -> Option<&BTy> {
        self.binds.get(*idx)
    }

    fn binding_mut(&mut self, idx: &usize) -> Option<&mut BTy> {
        self.binds.get_mut(*idx)
    }

    fn bindings(&self) -> RBinds<BTy> {
        RBinds { binds: self.binds.iter() }
    }

    fn bindings_mut(&mut self) -> RBindsMut<BTy> {
        RBindsMut { binds: self.binds.iter_mut() }
    }
}

#[derive(Clone, Debug)]
pub struct Binding<T: fmt::Debug + Clone> {
    // Optional name used to represent this binding.
    named: Option<String>,
    // Type of binding.
    vloc: VarLocation,
    dty: VarDataType,
    // Node indices in the function ssa that corresponds to this binding.
    ssa_refs: Vec<T>,
    set: HashSet<VarSet>,
}

impl<'a, T: 'a + RBind> Iterator for RBindsMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        self.binds.next()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum VarLocation {
    Register {
        name: String,
    },
    Memory(MemoryRegion),
    Unknown,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MemoryRegion {
    // Base, offset for function local.
    FunctionLocal {
        base: usize,
        offset: i64,
    },
    Stack,
    Global {
        offset: u64,
    },
    Heap,
    Unknown,
}

// Represents the set to which a variable belongs to in the call summary
// information.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum VarSet {
    Argument,
    Local,
    Modified,
    Preserved,
    Returned,
}

#[derive(Clone, Copy, Debug)]
pub enum VarDataType {
    Unknown(u64),
    Int,
    IntRef,
    Char,
    CharRef,
    Float,
    FloatRef,
    Double,
    DoubleRef,
}

#[derive(Clone, Debug)]
pub struct LocalInfo {
    base: usize,
    offset: i64,
}

impl<T: Clone + fmt::Debug> Default for Binding<T> {
    fn default() -> Binding<T> {
        Binding {
            named: None,
            vloc: VarLocation::Unknown,
            dty: VarDataType::Unknown(64),
            ssa_refs: Vec::new(),
            set: HashSet::new(),
        }
    }
}

impl<T: Clone + fmt::Debug> RBind for Binding<T> {
    type SSARef = T;

    fn is_argument(&self) -> bool {
        self.set.contains(&VarSet::Argument)
    }

    fn is_local(&self) -> bool {
        self.set.contains(&VarSet::Local)
    }

    fn is_modified(&self) -> bool {
        self.set.contains(&VarSet::Modified)
    }

    fn is_preserved(&self) -> bool {
        self.set.contains(&VarSet::Preserved)
    }

    fn is_return(&self) -> bool {
        self.set.contains(&VarSet::Returned)
    }

    fn mark_argument(&mut self) {
        self.set.insert(VarSet::Argument);
    }

    fn mark_local(&mut self) {
        self.set.insert(VarSet::Local);
    }

    fn mark_modified(&mut self) {
        self.set.insert(VarSet::Modified);
    }

    fn mark_preserved(&mut self) {
        self.set.insert(VarSet::Preserved);
    }

    fn mark_return(&mut self) {
        self.set.insert(VarSet::Returned);
    }

    fn name(&self) -> String {
        self.named.clone().unwrap_or_else(String::new)
    }

    fn is_register(&self) -> bool {
        match self.vloc {
            VarLocation::Register { name: _ } => true,
            _ => false,
        }
    }

    fn mark_register(&mut self, name: String) {
        self.vloc = VarLocation::Register { name: name };
    }

    fn is_fn_local(&self) -> bool {
        match self.vloc {
            VarLocation::Memory(MemoryRegion::FunctionLocal { base: _, offset: _ }) => true,
            _ => false,
        }
    }

    fn mark_fn_local(&mut self, base: usize, offset: i64) {
        self.vloc = VarLocation::Memory(MemoryRegion::FunctionLocal {
            base: base,
            offset: offset,
        });
    }

    fn local_info(&self) -> LocalInfo {
        if let VarLocation::Memory(MemoryRegion::FunctionLocal { base, offset }) = self.vloc {
            LocalInfo {
                base: base,
                offset: offset,
            }
        } else {
            panic!()
        }
    }

    fn is_stack(&self) -> bool {
        if let VarLocation::Memory(MemoryRegion::Stack) = self.vloc {
            true
        } else {
            false
        }
    }

    fn mark_stack(&mut self) {
        self.vloc = VarLocation::Memory(MemoryRegion::Stack);
    }

    fn is_global(&self) -> bool {
        match self.vloc {
            VarLocation::Memory(MemoryRegion::Global { offset }) => true,
            _ => false,
        }
    }

    fn mark_global(&mut self, offset: u64) {
        self.vloc = VarLocation::Memory(MemoryRegion::Global { offset: offset });
    }

    fn global_offset(&self) -> u64 {
        if let VarLocation::Memory(MemoryRegion::Global { offset }) = self.vloc {
            offset
        } else {
            panic!()
        }
    }

    fn is_unknown(&self) -> bool {
        match self.vloc {
            VarLocation::Unknown => true,
            _ => false,
        }
    }

    fn add_refs(&mut self, refs: Vec<T>) {
        self.ssa_refs.extend(refs);
    }

    fn refs<'a>(&'a self) -> ::std::slice::Iter<'a, T> {
        self.ssa_refs.iter()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::os::getenv;
use std::path::BytesContainer;
use std::str::from_utf8_lossy;
use get_environ = std::os::env;
use std::io::fs::{mkdir, rmdir_recursive, rename, symlink, unlink, readlink};
use std::io::process::{ExitStatus, Command, Ignored, InheritFd};
use std::io::stdio::{stdout, stderr};

use rustc::util::sha2::Sha256;
use rustc::util::sha2::Digest;

use argparse::{ArgumentParser, Store, StoreTrue};

use super::env::{Environ, Container};
use super::options::env_options;
use super::linux::ensure_dir;

fn makedirs(path: &Path) -> Result<(),String> {
    if path.exists() {
        return Ok(());
    }
    try!(makedirs(&path.dir_path()));
    return match mkdir(path, io::UserRWX) {
        Ok(()) => Ok(()),
        Err(e) => Err(format!("Can't mkdir: {}", e)),
    };
}

pub fn build_command(environ: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut force = false;
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut force)
            .add_option(["--force"], box StoreTrue,
                "Force rebuild of container event if it already exists");
        env_options(environ, &mut ap);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut container = try!(environ.get_container(&cname));
    try!(build_container(environ, &mut container, force));
    try!(link_container(environ, &container));

    return Ok(0);
}

pub fn link_container(environ: &Environ, container: &Container)
    -> Result<(), String>
{
    let container_root = container.container_root.as_ref().unwrap();
    let cdir = container_root.filename().unwrap();
    let tmptarget = environ.local_vagga.join(
        (".lnk.".container_into_owned_bytes() + cdir).as_slice());
    if tmptarget.exists() {
        match unlink(&tmptarget) {
            Ok(()) => {}
            Err(x) => return Err(format!("Error removing file: {}", x)),
        }
    }
    let target = environ.local_vagga.join(container.name.as_slice());
    debug!("Linking {} -> {}", container_root.display(), target.display())
    let relative_root = Path::new(".roots").join(cdir);
    match symlink(&relative_root, &tmptarget)
          .and(rename(&tmptarget, &target)) {
        Ok(()) => {}
        Err(x) => return Err(format!("Can't symlink new root: {}", x)),
    }
    if !container.name.eq(&container.fullname) {
        let target = environ.local_vagga.join(container.fullname.as_slice());
        debug!("Linking {} -> {}", container_root.display(), target.display())
        match symlink(&relative_root, &tmptarget)
              .and(rename(&tmptarget, &target)) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't symlink new root: {}", x)),
        }
    }
    return Ok(());
}

pub fn build_container(environ: &Environ, container: &mut Container,
                       force: bool)
    -> Result <bool, String>
{
    info!("Checking {}", container.name);

    let builder = &container.builder;
    let cache_dir = environ.local_vagga.join_many(
        [".cache", builder.as_slice()]);

    // TODO(tailhook) which path should be here?
    let path = getenv("PATH").unwrap_or(
        "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"
        .to_string());

    let mut env: Vec<(&[u8], &[u8])> = Vec::new();
    let mut caller_env: Vec<(String, String)> = Vec::new();
    let mut parameters: Vec<(String, String)> = Vec::new();
    env.push(("HOME".as_bytes(), "/homeless-shelter".as_bytes()));
    env.push(("PATH".as_bytes(), path.as_bytes()));
    env.push(("container_name".as_bytes(), container.name.as_bytes()));
    env.push(("container_fullname".as_bytes(), container.fullname.as_bytes()));
    env.push(("cache_dir".as_bytes(), cache_dir.as_vec()));
    env.push(("project_root".as_bytes(), environ.project_root.as_vec()));
    for (k, v) in get_environ().move_iter() {
        let pk = "CALLER_".to_string() + k;
        let pv = v;
        caller_env.push((pk, pv));
    }
    for (k, v) in container.parameters.iter() {
        parameters.push((builder + "_" + *k, v.clone()));
    }
    for &(ref k, ref v) in caller_env.iter() {
        env.push((k.container_as_bytes(), v.container_as_bytes()));
    }
    for &(ref k, ref v) in parameters.iter() {
        env.push((k.container_as_bytes(), v.container_as_bytes()));
    }

    let version_sh = environ.vagga_path.join_many(
        ["backends", builder.as_slice(), "version.sh"]);
    let mut digest = Sha256::new();
    if version_sh.exists() {
        digest.input_str(builder.as_slice());
        digest.input_str(":");
        match Command::new(&version_sh).env(env.as_slice())
            .stdin(Ignored).stderr(InheritFd(2)).output() {
            Ok(out) => match out.status {
                ExitStatus(0) => {
                    debug!("Version data ```{}```",
                           from_utf8_lossy(out.output.as_slice()));
                    digest.input(out.output.as_slice());
                }
                e => {
                    return Err(format!("Error running {}: {}",
                        version_sh.display(), e));
                }
            },
            Err(e) => {
                return Err(format!("Error running {}: {}",
                    version_sh.display(), e));
            }
        }
    } else {
        warn!("This backend has no versioning. Using primitive one.");
        digest.input_str(builder.as_slice());
        digest.input_str(":");
        for (k, v) in container.parameters.iter() {
            digest.input_str(k.as_slice());
            digest.input_str("=");
            digest.input_str(v.as_slice());
            digest.input_str(";");
        }
    }
    let fullhash = digest.result_str();
    let hash = fullhash.as_slice().slice_to(7);

    let build_sh = environ.vagga_path.join_many(
        ["backends", builder.as_slice(), "build.sh"]);
    if !build_sh.exists() {
        return Err(format!("Builder {} does not exist", builder));
    }

    let cdir = format!("{}.{}", container.fullname, hash);
    let container_root = environ.local_vagga.join_many(
        [".roots", cdir.as_slice()]);

    if container_root.exists() && !force {
        info!("Container {} already built as {}",
            container.name, container_root.display());
        container.container_root = Some(container_root);
        return Ok(false);
    }

    let artifacts_dir = environ.local_vagga.join_many(
        [".artifacts", cdir.as_slice()]);
    let container_tmp = environ.local_vagga.join_many(
        [".roots", (cdir + ".tmp").as_slice()]);

    info!("Building {} by {}", container_root.display(), build_sh.display());

    if container_tmp.exists() {
        match rmdir_recursive(&container_tmp) {
            Ok(()) => {}
            Err(x) => {
                // TODO(tailhook) join container and rm, because may have
                // files of different owners (subuid's)
                return Err(format!("Can't clean temporary root: {}", x));
            }
        }
    }
    try!(makedirs(&container_tmp));

    env.push(("artifacts_dir".as_bytes(), artifacts_dir.as_vec()));
    env.push(("container_hash".as_bytes(), hash.as_bytes()));
    env.push(("container_root".as_bytes(), container_tmp.as_vec()));
    match Command::new(build_sh).env(env.as_slice())
        .stdin(InheritFd(0)).stdout(InheritFd(1)).stderr(InheritFd(2))
        .status() {
        Ok(ExitStatus(0)) => {}
        Ok(x) => return Err(format!("Builder exited with status {}", x)),
        Err(x) => return Err(format!("Can't spawn: {}", x)),
    }

    for dir in ["proc", "sys", "dev", "work", "tmp"].iter() {
        try!(ensure_dir(&container_tmp.join(*dir)));
    }

    let container_old = environ.local_vagga.join_many(
        [".roots", (cdir + ".old").as_slice()]);
    if container_root.exists() {
        if container_old.exists() {
            match rmdir_recursive(&container_old) {
                Ok(()) => {}
                Err(x) => return Err(format!("Can't remove old root: {}", x)),
            }
        }
        match rename(&container_root, &container_old) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't rename old root: {}", x)),
        }
    }

    match rename(&container_tmp, &container_root) {
        Ok(()) => {}
        Err(x) => return Err(format!("Can't rename root: {}", x)),
    }

    if container_old.exists() {
        match rmdir_recursive(&container_old) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't remove old root: {}", x)),
        }
    }
    info!("Done building {} as {}",
        container.name, container_root.display());

    container.container_root = Some(container_root);

    return Ok(true);
}

pub fn ensure_container(env: &Environ, container: &mut Container)
    -> Result<(), String>
{
    if env.settings.version_check {
        try!(build_container(env, container, false));
        try!(link_container(env, container));
    } else {
        let lnk = env.local_vagga.join(container.fullname.as_slice());
        container.container_root = match readlink(&lnk) {
            Ok(path) => Some(lnk.dir_path().join(path)),
            Err(e) => return Err(format!("Container {} not found: {}",
                                         container.fullname, e)),
        };
    };
    return Ok(());
}
<commit_msg>Fix cwd of backend scripts<commit_after>use std::io;
use std::os::getenv;
use std::path::BytesContainer;
use std::str::from_utf8_lossy;
use get_environ = std::os::env;
use std::io::fs::{mkdir, rmdir_recursive, rename, symlink, unlink, readlink};
use std::io::process::{ExitStatus, Command, Ignored, InheritFd};
use std::io::stdio::{stdout, stderr};

use rustc::util::sha2::Sha256;
use rustc::util::sha2::Digest;

use argparse::{ArgumentParser, Store, StoreTrue};

use super::env::{Environ, Container};
use super::options::env_options;
use super::linux::ensure_dir;

fn makedirs(path: &Path) -> Result<(),String> {
    if path.exists() {
        return Ok(());
    }
    try!(makedirs(&path.dir_path()));
    return match mkdir(path, io::UserRWX) {
        Ok(()) => Ok(()),
        Err(e) => Err(format!("Can't mkdir: {}", e)),
    };
}

pub fn build_command(environ: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut force = false;
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut force)
            .add_option(["--force"], box StoreTrue,
                "Force rebuild of container event if it already exists");
        env_options(environ, &mut ap);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut container = try!(environ.get_container(&cname));
    try!(build_container(environ, &mut container, force));
    try!(link_container(environ, &container));

    return Ok(0);
}

pub fn link_container(environ: &Environ, container: &Container)
    -> Result<(), String>
{
    let container_root = container.container_root.as_ref().unwrap();
    let cdir = container_root.filename().unwrap();
    let tmptarget = environ.local_vagga.join(
        (".lnk.".container_into_owned_bytes() + cdir).as_slice());
    if tmptarget.exists() {
        match unlink(&tmptarget) {
            Ok(()) => {}
            Err(x) => return Err(format!("Error removing file: {}", x)),
        }
    }
    let target = environ.local_vagga.join(container.name.as_slice());
    debug!("Linking {} -> {}", container_root.display(), target.display())
    let relative_root = Path::new(".roots").join(cdir);
    match symlink(&relative_root, &tmptarget)
          .and(rename(&tmptarget, &target)) {
        Ok(()) => {}
        Err(x) => return Err(format!("Can't symlink new root: {}", x)),
    }
    if !container.name.eq(&container.fullname) {
        let target = environ.local_vagga.join(container.fullname.as_slice());
        debug!("Linking {} -> {}", container_root.display(), target.display())
        match symlink(&relative_root, &tmptarget)
              .and(rename(&tmptarget, &target)) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't symlink new root: {}", x)),
        }
    }
    return Ok(());
}

pub fn build_container(environ: &Environ, container: &mut Container,
                       force: bool)
    -> Result <bool, String>
{
    info!("Checking {}", container.name);

    let builder = &container.builder;
    let cache_dir = environ.local_vagga.join_many(
        [".cache", builder.as_slice()]);

    // TODO(tailhook) which path should be here?
    let path = getenv("PATH").unwrap_or(
        "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"
        .to_string());

    let mut env: Vec<(&[u8], &[u8])> = Vec::new();
    let mut caller_env: Vec<(String, String)> = Vec::new();
    let mut parameters: Vec<(String, String)> = Vec::new();
    env.push(("HOME".as_bytes(), "/homeless-shelter".as_bytes()));
    env.push(("PATH".as_bytes(), path.as_bytes()));
    env.push(("container_name".as_bytes(), container.name.as_bytes()));
    env.push(("container_fullname".as_bytes(), container.fullname.as_bytes()));
    env.push(("cache_dir".as_bytes(), cache_dir.as_vec()));
    env.push(("project_root".as_bytes(), environ.project_root.as_vec()));
    for (k, v) in get_environ().move_iter() {
        let pk = "CALLER_".to_string() + k;
        let pv = v;
        caller_env.push((pk, pv));
    }
    for (k, v) in container.parameters.iter() {
        parameters.push((builder + "_" + *k, v.clone()));
    }
    for &(ref k, ref v) in caller_env.iter() {
        env.push((k.container_as_bytes(), v.container_as_bytes()));
    }
    for &(ref k, ref v) in parameters.iter() {
        env.push((k.container_as_bytes(), v.container_as_bytes()));
    }

    let version_sh = environ.vagga_path.join_many(
        ["backends", builder.as_slice(), "version.sh"]);
    let mut digest = Sha256::new();
    if version_sh.exists() {
        digest.input_str(builder.as_slice());
        digest.input_str(":");
        match Command::new(&version_sh).env(env.as_slice())
            .cwd(&environ.project_root)
            .stdin(Ignored).stderr(InheritFd(2)).output() {
            Ok(out) => match out.status {
                ExitStatus(0) => {
                    debug!("Version data ```{}```",
                           from_utf8_lossy(out.output.as_slice()));
                    digest.input(out.output.as_slice());
                }
                e => {
                    return Err(format!("Error running {}: {}",
                        version_sh.display(), e));
                }
            },
            Err(e) => {
                return Err(format!("Error running {}: {}",
                    version_sh.display(), e));
            }
        }
    } else {
        warn!("This backend has no versioning. Using primitive one.");
        digest.input_str(builder.as_slice());
        digest.input_str(":");
        for (k, v) in container.parameters.iter() {
            digest.input_str(k.as_slice());
            digest.input_str("=");
            digest.input_str(v.as_slice());
            digest.input_str(";");
        }
    }
    let fullhash = digest.result_str();
    let hash = fullhash.as_slice().slice_to(7);

    let build_sh = environ.vagga_path.join_many(
        ["backends", builder.as_slice(), "build.sh"]);
    if !build_sh.exists() {
        return Err(format!("Builder {} does not exist", builder));
    }

    let cdir = format!("{}.{}", container.fullname, hash);
    let container_root = environ.local_vagga.join_many(
        [".roots", cdir.as_slice()]);

    if container_root.exists() && !force {
        info!("Container {} already built as {}",
            container.name, container_root.display());
        container.container_root = Some(container_root);
        return Ok(false);
    }

    let artifacts_dir = environ.local_vagga.join_many(
        [".artifacts", cdir.as_slice()]);
    let container_tmp = environ.local_vagga.join_many(
        [".roots", (cdir + ".tmp").as_slice()]);

    info!("Building {} by {}", container_root.display(), build_sh.display());

    if container_tmp.exists() {
        match rmdir_recursive(&container_tmp) {
            Ok(()) => {}
            Err(x) => {
                // TODO(tailhook) join container and rm, because may have
                // files of different owners (subuid's)
                return Err(format!("Can't clean temporary root: {}", x));
            }
        }
    }
    try!(makedirs(&container_tmp));

    env.push(("artifacts_dir".as_bytes(), artifacts_dir.as_vec()));
    env.push(("container_hash".as_bytes(), hash.as_bytes()));
    env.push(("container_root".as_bytes(), container_tmp.as_vec()));
    match Command::new(build_sh).env(env.as_slice())
        .cwd(&environ.project_root)
        .stdin(InheritFd(0)).stdout(InheritFd(1)).stderr(InheritFd(2))
        .status() {
        Ok(ExitStatus(0)) => {}
        Ok(x) => return Err(format!("Builder exited with status {}", x)),
        Err(x) => return Err(format!("Can't spawn: {}", x)),
    }

    for dir in ["proc", "sys", "dev", "work", "tmp"].iter() {
        try!(ensure_dir(&container_tmp.join(*dir)));
    }

    let container_old = environ.local_vagga.join_many(
        [".roots", (cdir + ".old").as_slice()]);
    if container_root.exists() {
        if container_old.exists() {
            match rmdir_recursive(&container_old) {
                Ok(()) => {}
                Err(x) => return Err(format!("Can't remove old root: {}", x)),
            }
        }
        match rename(&container_root, &container_old) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't rename old root: {}", x)),
        }
    }

    match rename(&container_tmp, &container_root) {
        Ok(()) => {}
        Err(x) => return Err(format!("Can't rename root: {}", x)),
    }

    if container_old.exists() {
        match rmdir_recursive(&container_old) {
            Ok(()) => {}
            Err(x) => return Err(format!("Can't remove old root: {}", x)),
        }
    }
    info!("Done building {} as {}",
        container.name, container_root.display());

    container.container_root = Some(container_root);

    return Ok(true);
}

pub fn ensure_container(env: &Environ, container: &mut Container)
    -> Result<(), String>
{
    if env.settings.version_check {
        try!(build_container(env, container, false));
        try!(link_container(env, container));
    } else {
        let lnk = env.local_vagga.join(container.fullname.as_slice());
        container.container_root = match readlink(&lnk) {
            Ok(path) => Some(lnk.dir_path().join(path)),
            Err(e) => return Err(format!("Container {} not found: {}",
                                         container.fullname, e)),
        };
    };
    return Ok(());
}
<|endoftext|>


<commit_before>use std::cmp::{PartialEq, Eq};
use std::ops::{Add, Mul, Div};

#[derive(Copy, Clone, Debug)]
pub struct RGBColor {
    pub r: f64,
    pub g: f64,
    pub b: f64,
}

impl RGBColor {
    pub fn new(_r: f64, _g: f64, _b: f64) -> RGBColor {
        assert!(0.0 <= _r && _r <= 1.0);
        assert!(0.0 <= _g && _g <= 1.0);
        assert!(0.0 <= _b && _b <= 1.0);
        RGBColor { r: _r, g: _g, b: _b }
    }
}

fn clamp(value: f64, min: f64, max: f64) -> f64 {
    if value < min {
        return min
    }
    if value > max {
        return max
    }
    value
}

impl Add for RGBColor {
    type Output = RGBColor;

    fn add(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: clamp(self.r + other.r, 0.0, 1.0),
            g: clamp(self.g + other.g, 0.0, 1.0),
            b: clamp(self.b + other.b, 0.0, 1.0)
        }
    }
}

impl Mul<f64> for RGBColor {
    type Output = RGBColor;

    fn mul(self, other: f64) -> RGBColor {
        RGBColor {
            r: clamp(self.r * other, 0.0, 1.0),
            g: clamp(self.g * other, 0.0, 1.0),
            b: clamp(self.b * other, 0.0, 1.0)
        }
    }
}

impl Mul<RGBColor> for f64 {
    type Output = RGBColor;

    fn mul(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: clamp(self * other.r, 0.0, 1.0),
            g: clamp(self * other.g, 0.0, 1.0),
            b: clamp(self * other.b, 0.0, 1.0)
        }
    }
}

impl Mul for RGBColor {
    type Output = RGBColor;

    fn mul(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: self.r * other.r,
            g: self.g * other.g,
            b: self.b * other.b
        }
    }
}

impl PartialEq for RGBColor {
    fn eq(&self, other: &RGBColor) -> bool {
        self.r == other.r && self.g == other.g && self.b == self.b
    }
}

impl Eq for RGBColor { }

#[cfg(test)]
mod test {
    use super::clamp;
    use super::RGBColor;

    #[test]
    fn test_clamp() {
        assert_eq!(clamp(2.0, 1.0, 3.0), 2.0);
        assert_eq!(clamp(0.0, 1.0, 3.0), 1.0);
        assert_eq!(clamp(4.0, 1.0, 3.0), 3.0);
    }

    #[test]
    fn test_add() {
        let c1 = RGBColor::new(0.0, 0.0, 0.0);
        let c2 = RGBColor::new(0.5, 0.5, 0.5);
        let c3 = RGBColor::new(0.6, 0.7, 0.8);

        assert_eq!(c1 + c2, c2);
        assert_eq!(c1 + c3, c3);
        assert_eq!(c2 + c3, RGBColor::new(1.0, 1.0, 1.0));
    }

    #[test]
    fn test_mul() {
        let c1 = RGBColor::new(0.0, 0.0, 0.0);
        let c2 = RGBColor::new(0.5, 0.5, 0.5);
        let c3 = RGBColor::new(0.6, 0.7, 0.8);
        let c4 = RGBColor::new(1.0, 1.0, 1.0);
        let c5 = RGBColor::new(0.25, 0.25, 0.25);

        assert_eq!(c1 * c2, c1);
        assert_eq!(c2 * c4, c2);
        assert_eq!(c2 * c3, RGBColor::new(0.3, 0.35, 0.4));
        assert_eq!(c3 * c4, c3);

        assert_eq!(c1 * 2.0, c1);
        assert_eq!(2.0 * c1, c1);

        assert_eq!(c2 * 2.0, c4);
        assert_eq!(2.0 * c2, c4);

        assert_eq!(c2 * 0.5, c5);
        assert_eq!(0.5 * c2, c5);

        assert_eq!(c3 * 2.0, c4);
        assert_eq!(2.0 * c3, c4);
    }
}
<commit_msg>module color<commit_after>use std::cmp::{PartialEq, Eq};
use std::ops::{Add, Mul, Div};

#[derive(Copy, Clone, Debug)]
pub struct RGBColor {
    r: f64,
    g: f64,
    b: f64,
}

impl RGBColor {
    pub fn new(_r: f64, _g: f64, _b: f64) -> RGBColor {
        assert!(0.0 <= _r && _r <= 1.0);
        assert!(0.0 <= _g && _g <= 1.0);
        assert!(0.0 <= _b && _b <= 1.0);
        RGBColor { r: _r, g: _g, b: _b }
    }

    pub fn power(&self, p: f64) -> RGBColor {
        RGBColor {
            r: clamp(self.r.powf(p), 0.0, 1.0),
            g: clamp(self.g.powf(p), 0.0, 1.0),
            b: clamp(self.b.powf(p), 0.0, 1.0)
        }
    }

    pub fn r(&self) -> f64 {
        self.r
    }

    pub fn g(&self) -> f64 {
        self.b
    }

    pub fn b(&self) -> f64 {
        self.b
    }
}

fn clamp(value: f64, min: f64, max: f64) -> f64 {
    if value < min {
        return min
    }
    if value > max {
        return max
    }
    value
}

impl Add for RGBColor {
    type Output = RGBColor;

    fn add(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: clamp(self.r + other.r, 0.0, 1.0),
            g: clamp(self.g + other.g, 0.0, 1.0),
            b: clamp(self.b + other.b, 0.0, 1.0)
        }
    }
}

impl Mul<f64> for RGBColor {
    type Output = RGBColor;

    fn mul(self, other: f64) -> RGBColor {
        RGBColor {
            r: clamp(self.r * other, 0.0, 1.0),
            g: clamp(self.g * other, 0.0, 1.0),
            b: clamp(self.b * other, 0.0, 1.0)
        }
    }
}

impl Mul<RGBColor> for f64 {
    type Output = RGBColor;

    fn mul(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: clamp(self * other.r, 0.0, 1.0),
            g: clamp(self * other.g, 0.0, 1.0),
            b: clamp(self * other.b, 0.0, 1.0)
        }
    }
}

impl Mul for RGBColor {
    type Output = RGBColor;

    fn mul(self, other: RGBColor) -> RGBColor {
        RGBColor {
            r: self.r * other.r,
            g: self.g * other.g,
            b: self.b * other.b
        }
    }
}

impl Div<f64> for RGBColor {
    type Output = RGBColor;

    fn div(self, other: f64) -> RGBColor {
        RGBColor {
            r: clamp(self.r / other, 0.0, 1.0),
            g: clamp(self.g / other, 0.0, 1.0),
            b: clamp(self.b / other, 0.0, 1.0)
        }
    }
}

impl PartialEq for RGBColor {
    fn eq(&self, other: &RGBColor) -> bool {
        self.r == other.r && self.g == other.g && self.b == self.b
    }
}

impl Eq for RGBColor { }

#[cfg(test)]
mod test {
    use super::clamp;
    use super::RGBColor;

    #[test]
    fn test_clamp() {
        assert_eq!(clamp(2.0, 1.0, 3.0), 2.0);
        assert_eq!(clamp(0.0, 1.0, 3.0), 1.0);
        assert_eq!(clamp(4.0, 1.0, 3.0), 3.0);
    }

    #[test]
    fn test_add() {
        let c1 = RGBColor::new(0.0, 0.0, 0.0);
        let c2 = RGBColor::new(0.5, 0.5, 0.5);
        let c3 = RGBColor::new(0.6, 0.7, 0.8);

        assert_eq!(c1 + c2, c2);
        assert_eq!(c1 + c3, c3);
        assert_eq!(c2 + c3, RGBColor::new(1.0, 1.0, 1.0));
    }

    #[test]
    fn test_mul() {
        let c1 = RGBColor::new(0.0, 0.0, 0.0);
        let c2 = RGBColor::new(0.5, 0.5, 0.5);
        let c3 = RGBColor::new(0.6, 0.7, 0.8);
        let c4 = RGBColor::new(1.0, 1.0, 1.0);
        let c5 = RGBColor::new(0.25, 0.25, 0.25);

        assert_eq!(c1 * c2, c1);
        assert_eq!(c2 * c4, c2);
        assert_eq!(c2 * c3, RGBColor::new(0.3, 0.35, 0.4));
        assert_eq!(c3 * c4, c3);

        assert_eq!(c1 * 2.0, c1);
        assert_eq!(2.0 * c1, c1);

        assert_eq!(c2 * 2.0, c4);
        assert_eq!(2.0 * c2, c4);

        assert_eq!(c2 * 0.5, c5);
        assert_eq!(0.5 * c2, c5);

        assert_eq!(c3 * 2.0, c4);
        assert_eq!(2.0 * c3, c4);
    }

    #[test]
    fn test_div() {
        let c = RGBColor::new(0.5, 0.5, 0.5);
        assert_eq!(c / 2.0, RGBColor::new(0.25, 0.25, 0.25));
        assert_eq!(c / 0.001, RGBColor::new(1.0, 1.0, 1.0));
    }

    #[test]
    fn test_power() {
        let c = RGBColor::new(0.5, 0.6, 0.7);
        assert_eq!(c.power(2.0), RGBColor::new(0.25, 0.36, 0.49));
    }
}
<|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/. */

#![allow(non_camel_case_types, dead_code)]

macro_rules! VG_USERREQ_TOOL_BASE ( ($a:expr, $b:expr) => (
    ((($a as int) & 0xff) << 24)
  | ((($b as int) & 0xff) << 16)))

#[repr(C)]
pub enum Vg_ClientRequest {
    VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
    VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
    VG_USERREQ__CLIENT_CALL0 = 0x1101,
    VG_USERREQ__CLIENT_CALL1 = 0x1102,
    VG_USERREQ__CLIENT_CALL2 = 0x1103,
    VG_USERREQ__CLIENT_CALL3 = 0x1104,
    VG_USERREQ__COUNT_ERRORS = 0x1201,
    VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
    VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
    VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
    VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
    VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
    VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
    VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
    VG_USERREQ__MEMPOOL_FREE     = 0x1306,
    VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
    VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
    VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
    VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
    VG_USERREQ__PRINTF           = 0x1401,
    VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
    VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
    VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
    VG_USERREQ__STACK_REGISTER   = 0x1501,
    VG_USERREQ__STACK_DEREGISTER = 0x1502,
    VG_USERREQ__STACK_CHANGE     = 0x1503,
    VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
    VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
    VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
}

#[repr(C)]
pub enum Vg_MemCheckClientRequest {
    VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE!('M','C'),
    VG_USERREQ__MAKE_MEM_UNDEFINED,
    VG_USERREQ__MAKE_MEM_DEFINED,
    VG_USERREQ__DISCARD,
    VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
    VG_USERREQ__CHECK_MEM_IS_DEFINED,
    VG_USERREQ__DO_LEAK_CHECK,
    VG_USERREQ__COUNT_LEAKS,
    VG_USERREQ__GET_VBITS,
    VG_USERREQ__SET_VBITS,
    VG_USERREQ__CREATE_BLOCK,
    VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
    VG_USERREQ__COUNT_LEAK_BLOCKS,
}

#[repr(C)]
pub enum Vg_CallgrindClientRequest {
    VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE!('C','T'),
    VG_USERREQ__ZERO_STATS,
    VG_USERREQ__TOGGLE_COLLECT,
    VG_USERREQ__DUMP_STATS_AT,
    VG_USERREQ__START_INSTRUMENTATION,
    VG_USERREQ__STOP_INSTRUMENTATION,
}

#[repr(C)]
pub enum Vg_TCheckClientRequest {
    VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),
    _Vg_TCheckClientRequest_dummy, // suppress error about univariant enum repr
}

#[repr(C)]
pub enum Vg_DRDClientRequest {
   // Binary compatible with the similar Helgrind request above
   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),

   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE!('D','R'),
   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
   VG_USERREQ__DRD_START_SUPPRESSION,
   VG_USERREQ__DRD_FINISH_SUPPRESSION,
   VG_USERREQ__DRD_START_TRACE_ADDR,
   VG_USERREQ__DRD_STOP_TRACE_ADDR,
   VG_USERREQ__DRD_RECORD_LOADS,
   VG_USERREQ__DRD_RECORD_STORES,
   VG_USERREQ__DRD_SET_THREAD_NAME,
}
<commit_msg>Upgrade to rustc 0.13.0-dev (395901393 2014-11-24 00:46:30 +0000)<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/. */

#![allow(non_camel_case_types, dead_code)]

pub use self::Vg_ClientRequest::*;
pub use self::Vg_MemCheckClientRequest::*;
pub use self::Vg_CallgrindClientRequest::*;
pub use self::Vg_TCheckClientRequest::*;
pub use self::Vg_DRDClientRequest::*;

macro_rules! VG_USERREQ_TOOL_BASE ( ($a:expr, $b:expr) => (
    ((($a as int) & 0xff) << 24)
  | ((($b as int) & 0xff) << 16)))

#[repr(C)]
pub enum Vg_ClientRequest {
    VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
    VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
    VG_USERREQ__CLIENT_CALL0 = 0x1101,
    VG_USERREQ__CLIENT_CALL1 = 0x1102,
    VG_USERREQ__CLIENT_CALL2 = 0x1103,
    VG_USERREQ__CLIENT_CALL3 = 0x1104,
    VG_USERREQ__COUNT_ERRORS = 0x1201,
    VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
    VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
    VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
    VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
    VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
    VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
    VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
    VG_USERREQ__MEMPOOL_FREE     = 0x1306,
    VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
    VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
    VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
    VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
    VG_USERREQ__PRINTF           = 0x1401,
    VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
    VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
    VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
    VG_USERREQ__STACK_REGISTER   = 0x1501,
    VG_USERREQ__STACK_DEREGISTER = 0x1502,
    VG_USERREQ__STACK_CHANGE     = 0x1503,
    VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
    VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
    VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
}

#[repr(C)]
pub enum Vg_MemCheckClientRequest {
    VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE!('M','C'),
    VG_USERREQ__MAKE_MEM_UNDEFINED,
    VG_USERREQ__MAKE_MEM_DEFINED,
    VG_USERREQ__DISCARD,
    VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
    VG_USERREQ__CHECK_MEM_IS_DEFINED,
    VG_USERREQ__DO_LEAK_CHECK,
    VG_USERREQ__COUNT_LEAKS,
    VG_USERREQ__GET_VBITS,
    VG_USERREQ__SET_VBITS,
    VG_USERREQ__CREATE_BLOCK,
    VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
    VG_USERREQ__COUNT_LEAK_BLOCKS,
}

#[repr(C)]
pub enum Vg_CallgrindClientRequest {
    VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE!('C','T'),
    VG_USERREQ__ZERO_STATS,
    VG_USERREQ__TOGGLE_COLLECT,
    VG_USERREQ__DUMP_STATS_AT,
    VG_USERREQ__START_INSTRUMENTATION,
    VG_USERREQ__STOP_INSTRUMENTATION,
}

#[repr(C)]
pub enum Vg_TCheckClientRequest {
    VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),
    _Vg_TCheckClientRequest_dummy, // suppress error about univariant enum repr
}

#[repr(C)]
pub enum Vg_DRDClientRequest {
   // Binary compatible with the similar Helgrind request above
   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE!('H','G'),

   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE!('D','R'),
   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
   VG_USERREQ__DRD_START_SUPPRESSION,
   VG_USERREQ__DRD_FINISH_SUPPRESSION,
   VG_USERREQ__DRD_START_TRACE_ADDR,
   VG_USERREQ__DRD_STOP_TRACE_ADDR,
   VG_USERREQ__DRD_RECORD_LOADS,
   VG_USERREQ__DRD_RECORD_STORES,
   VG_USERREQ__DRD_SET_THREAD_NAME,
}
<|endoftext|>


<commit_before>#![doc="Defines errors related to SciRust library
"]

// std imports

// local imports

/// Enum for errors related to SciRust library
#[deriving(Show)]
pub enum SRError{

    /******************************************************
     *
     *   General matrix operation errors
     *
     *******************************************************/

    /// The matrix is empty
    EmptyMatrix,
    /// The dimensions of two matrices mismatch
    DimensionsMismatch,
    /// The matrix is not a square matrix
    NonSquareMatrix,
    /// The matrix is not a vector
    NotAVector,

    /// The number is not a power of two
    IsNotPowerOfTwo,

    /******************************************************
     *
     *   Errors related to solving a system of linear equations
     *
     *******************************************************/

        /// There is no solution to the system of equations
    NoSolution,
    /// There are infinite solutions to the system of equations.
    InfiniteSolutions

}

impl SRError{

    /// Converts enum values to string representation
    pub fn to_string(&self) -> String {
        match *self{
            EmptyMatrix => format!("Matrix is empty"),
            DimensionsMismatch => format!("Dimensions don't match"),
            NonSquareMatrix => format!("Matrix is not square"),
            NotAVector => format!("Matrix is not a vector"),

            IsNotPowerOfTwo => format!("Number is not power of two"),

            NoSolution => format!("No solution"),
            InfiniteSolutions => format!("Infinite solutions"),
        }
    }
}

<commit_msg>bug fix.<commit_after>#![doc="Defines errors related to SciRust library
"]

// std imports

// local imports

/// Enum for errors related to SciRust library
#[deriving(Show)]
pub enum SRError{

    /******************************************************
     *
     *   General matrix operation errors
     *
     *******************************************************/

    /// The matrix is empty
    EmptyMatrix,
    /// The dimensions of two matrices mismatch
    DimensionsMismatch,
    /// The matrix is not a square matrix
    NonSquareMatrix,
    /// The matrix is not a vector
    NotAVector,
    /// Indicates that a matrix is not full rank
    IsNotFullRankMatrix,
    /// Indicates that the matrix is full rank
    IsFullRankMatrix,
    /// The matrix is singular
    IsSingular,
    /// The matrix is invertible (non-singular)
    IsNonSingular,
    /// The matrix is positive definite
    IsPositiveDefinite,
    /// The matrix is positive semi definite
    IsPositiveSemiDefinite,
    /// The matrix is negative definite
    IsNegativeDefinite,
    /// The matrix is negative semi definite
    IsNegativeSemiDefinite,
    /// The matrix is non-definite
    IsNonDefinite,

    /******************************************************
     *
     *   Errors related to solving a system of linear equations
     *
     *******************************************************/

    /// There is no solution to the system of equations
    NoSolution,
    /// There are infinite solutions to the system of equations.
    InfiniteSolutions,

    /******************************************************
     *
     *   Discrete numbers related stuff
     *
     *******************************************************/

    /// The number is not a power of two
    IsNotPowerOfTwo,

}

impl SRError{

    /// Converts enum values to string representation
    pub fn to_string(&self) -> String {
        match *self{
            //  Matrices
            EmptyMatrix => format!("Matrix is empty"),
            DimensionsMismatch => format!("Dimensions don't match"),
            NonSquareMatrix => format!("Matrix is not square"),
            NotAVector => format!("Matrix is not a vector"),
            IsNotFullRankMatrix => format!("Matrix is not full rank"),
            IsFullRankMatrix => format!("Matrix is full rank"),
            IsSingular => format!("Matrix is singular"),
            IsNonSingular => format!("Matrix is not singular"),
            IsPositiveDefinite => format!("Matrix is positive definite"),
            IsPositiveSemiDefinite => format!("Matrix is positive semi-definite"),
            IsNegativeDefinite => format!("Matrix is negative definite"),
            IsNegativeSemiDefinite => format!("Matrix is negative semi-definite"),
            IsNonDefinite => format!("Matrix is non-definite"),
            // Linear systems
            NoSolution => format!("No solution"),
            InfiniteSolutions => format!("Infinite solutions"),
            // Discrete numbers
            IsNotPowerOfTwo => format!("Number is not power of two"),

        }
    }
}

<|endoftext|>