<commit_before>//! Decoding of OpenEXR (.exr) Images
//!
//! OpenEXR is an image format that is widely used, especially in VFX,
//! because it supports lossless and lossy compression for float data.
//!
//! # Related Links
//! * <https://www.openexr.com/documentation.html> - The OpenEXR reference.

// # ROADMAP
// - [x] ImageDecoder
// - [x] ImageEncoder
// - [ ] GenericImageView?
// - [ ] GenericImage?
// - [x] Progress

// # MAYBE SOON
// - [ ] ImageDecoderExt::read_rect_with_progress
// - [ ] Layers -> Animation?

extern crate exr;
use exr::prelude::*;

use crate::{ImageDecoder, ImageResult, ColorType, Progress, image, ImageError, ImageFormat};
use std::io::{Write, Seek, BufRead, Cursor};
use crate::error::{DecodingError, ImageFormatHint};

/// An OpenEXR decoder
#[derive(Debug)]
pub struct ExrDecoder<R> {
    exr_reader: exr::block::reader::Reader<R>,

    // select a header that is rgb and not deep
    header_index: usize,
}

impl<R: BufRead + Seek> ExrDecoder<R> {

    /// Create a decoder. Consumes the first few bytes of the source to extract image dimensions.
    pub fn read(source: R) -> ImageResult<Self> {

        // read meta data, then wait for further instructions, keeping the file open and ready
        let exr_reader = exr::block::read(source, false)?;

        let header_index = exr_reader.headers().into_iter()
            .position(|header|{
                let has_rgb = ["R","G","B"].iter().all( // alpha will be optional
                    // check if r/g/b exists in the channels
                    |required| header.channels.list.iter()
                        .find(|chan| chan.name.eq(required)).is_some() // TODO eq_lowercase only if exrs supports it
                );

                !header.deep && has_rgb
            })
            .ok_or_else(|| ImageError::Decoding(DecodingError::new(
                ImageFormatHint::Exact(ImageFormat::Exr),
                "image does not contain non-deep rgb channels"
            )))?;

        Ok(Self { exr_reader, header_index })
    }
}

impl<'a, R: 'a + BufRead + Seek> ImageDecoder<'a> for ExrDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u32, u32) {
        let size = self.exr_reader.headers()[self.header_index].layer_size;
        (size.width() as u32, size.height() as u32)
    }

    // TODO fn original_color_type(&self) -> ExtendedColorType {}

    fn color_type(&self) -> ColorType {
        // TODO adapt to actual exr color type
        // let _channels = &self.exr_reader.headers()[self.header_index].channels;
        ColorType::Rgba32F
    }

    /// Use `read_image` if possible,
    /// as this method creates a whole new buffer to contain the entire image.
    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(image::decoder_to_vec(self)?)) // TODO no vec?
    }

    fn scanline_bytes(&self) -> u64 {
        // we cannot always read individual scan lines for every file,
        // as the tiles or lines in the file could be in random or reversed order.
        // therefore we currently read all lines at once
        // Todo: optimize for specific exr.line_order?
       self.total_bytes()
    }

    fn read_image_with_progress<F: Fn(Progress)>(self, target: &mut [u8], progress_callback: F) -> ImageResult<()> {
        let blocks_in_header = self.exr_reader.headers()[self.header_index].chunk_count as u64;
        let height = self.dimensions().1 as usize;

        let result = read()
            .no_deep_data().largest_resolution_level()
            .rgba_channels(
                |size, _channels|
                    (size, vec![0_f32; size.area()*4])
                ,

                move |(size, buffer), mut position, (r,g,b,a_or_1): (f32,f32,f32,f32)| {
                    // TODO white point chromaticities + srgb/linear conversion?
                    position.1 = height - (position.1 + 1); // openexr stores +y upwards, but we need +y downwards
                    let first_f32_index = position.flat_index_for_size(*size);
                    buffer[first_f32_index*4 .. (first_f32_index + 1)*4].copy_from_slice(&[r, g, b, a_or_1]);
                }
            )
            .first_valid_layer() // TODO select exact layer by self.header_index?
            .all_attributes()
            .on_progress(|progress| {
                progress_callback(Progress::new(
                    (progress*blocks_in_header as f64) as u64, blocks_in_header) // TODO precision errors?
                );
            })
            .from_chunks(self.exr_reader)?;

        // TODO this copy is strictly not necessary, but the exr api is a little too simple for reading into a borrowed target slice
        target.copy_from_slice(bytemuck::cast_slice(result.layer_data.channel_data.pixels.1.as_slice()));

        // TODO keep meta data?
        Ok(())
    }
}

pub fn write_image(mut write: impl Write/* + Seek*/, bytes: &[u8], width: u32, height: u32, color_type: ColorType) -> ImageResult<()> {
    let width = width as usize;
    let height = height as usize;

    let pixels: &[f32] = bytemuck::try_cast_slice(bytes).expect("image byte buffer must be aligned to f32");
    let mut seekable_write = Cursor::new(Vec::with_capacity(width*height*3*4));

    match color_type {
        ColorType::Rgb32F => {
            exr::prelude::Image
                ::from_channels(
                    (width, height),
                    SpecificChannels::rgb(|mut pixel: Vec2<usize>| {
                        pixel.1 = height - (pixel.1 + 1); // openexr stores +y upwards, but we need +y downwards
                        let pixel_index = 3 * pixel.flat_index_for_size(Vec2(width, height));
                        (pixels[pixel_index], pixels[pixel_index+1], pixels[pixel_index+2])
                    })
                )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?; // TODO BufWrite::new()?
        }

        ColorType::Rgba32F => {
            exr::prelude::Image
                ::from_channels(
                    (width, height),
                    SpecificChannels::rgba(|mut pixel: Vec2<usize>| {
                        pixel.1 = height - (pixel.1 + 1); // openexr stores +y upwards, but we need +y downwards
                        let pixel_index = 4 * pixel.flat_index_for_size(Vec2(width, height));
                        (pixels[pixel_index], pixels[pixel_index+1], pixels[pixel_index+2], pixels[pixel_index+3])
                    })
                )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?; // TODO BufWrite::new()?
        }

        _ => todo!()
    }

    write.write_all(seekable_write.into_inner().as_slice())?;
    Ok(())
}

impl From<Error> for ImageError {
    fn from(exr_error: Error) -> Self {
        ImageError::Decoding(DecodingError::new(
            ImageFormatHint::Exact(ImageFormat::Exr),
            exr_error
        ))
    }
}

<commit_msg>fix panic triggering for unsupported color types<commit_after>//! Decoding of OpenEXR (.exr) Images
//!
//! OpenEXR is an image format that is widely used, especially in VFX,
//! because it supports lossless and lossy compression for float data.
//!
//! # Related Links
//! * <https://www.openexr.com/documentation.html> - The OpenEXR reference.

// ROADMAP: See https://github.com/image-rs/image/pull/1475

extern crate exr;
use exr::prelude::*;

use crate::{ImageDecoder, ImageResult, ColorType, Progress, image, ImageError, ImageFormat};
use std::io::{Write, Seek, BufRead, Cursor};
use crate::error::{DecodingError, ImageFormatHint};

/// An OpenEXR decoder
#[derive(Debug)]
pub struct ExrDecoder<R> {
    exr_reader: exr::block::reader::Reader<R>,

    // select a header that is rgb and not deep
    header_index: usize,
}

impl<R: BufRead + Seek> ExrDecoder<R> {

    /// Create a decoder. Consumes the first few bytes of the source to extract image dimensions.
    pub fn read(source: R) -> ImageResult<Self> {

        // read meta data, then wait for further instructions, keeping the file open and ready
        let exr_reader = exr::block::read(source, false)?;

        let header_index = exr_reader.headers().into_iter()
            .position(|header|{
                let has_rgb = ["R","G","B"].iter().all( // alpha will be optional
                    // check if r/g/b exists in the channels
                    |required| header.channels.list.iter()
                        .find(|chan| chan.name.eq(required)).is_some() // TODO eq_lowercase only if exrs supports it
                );

                !header.deep && has_rgb
            })
            .ok_or_else(|| ImageError::Decoding(DecodingError::new(
                ImageFormatHint::Exact(ImageFormat::Exr),
                "image does not contain non-deep rgb channels"
            )))?;

        Ok(Self { exr_reader, header_index })
    }
}

impl<'a, R: 'a + BufRead + Seek> ImageDecoder<'a> for ExrDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u32, u32) {
        let size = self.exr_reader.headers()[self.header_index].layer_size;
        (size.width() as u32, size.height() as u32)
    }

    // TODO fn original_color_type(&self) -> ExtendedColorType {}

    fn color_type(&self) -> ColorType {
        // TODO adapt to actual exr color type
        // let _channels = &self.exr_reader.headers()[self.header_index].channels;
        ColorType::Rgba32F
    }

    /// Use `read_image` if possible,
    /// as this method creates a whole new buffer to contain the entire image.
    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(image::decoder_to_vec(self)?)) // TODO no vec?
    }

    fn scanline_bytes(&self) -> u64 {
        // we cannot always read individual scan lines for every file,
        // as the tiles or lines in the file could be in random or reversed order.
        // therefore we currently read all lines at once
        // Todo: optimize for specific exr.line_order?
       self.total_bytes()
    }

    fn read_image_with_progress<F: Fn(Progress)>(self, target: &mut [u8], progress_callback: F) -> ImageResult<()> {
        let blocks_in_header = self.exr_reader.headers()[self.header_index].chunk_count as u64;
        let height = self.dimensions().1 as usize;

        let result = read()
            .no_deep_data().largest_resolution_level()
            .rgba_channels(
                |size, _channels|
                    (size, vec![0_f32; size.area()*4])
                ,

                move |(size, buffer), mut position, (r,g,b,a_or_1): (f32,f32,f32,f32)| {
                    // TODO white point chromaticities + srgb/linear conversion?
                    position.1 = height - (position.1 + 1); // openexr stores +y upwards, but we need +y downwards
                    let first_f32_index = position.flat_index_for_size(*size);
                    buffer[first_f32_index*4 .. (first_f32_index + 1)*4].copy_from_slice(&[r, g, b, a_or_1]);
                }
            )
            .first_valid_layer() // TODO select exact layer by self.header_index?
            .all_attributes()
            .on_progress(|progress| {
                progress_callback(Progress::new(
                    (progress*blocks_in_header as f64) as u64, blocks_in_header) // TODO precision errors?
                );
            })
            .from_chunks(self.exr_reader)?;

        // TODO this copy is strictly not necessary, but the exr api is a little too simple for reading into a borrowed target slice
        target.copy_from_slice(bytemuck::cast_slice(result.layer_data.channel_data.pixels.1.as_slice()));

        // TODO keep meta data?
        Ok(())
    }
}

pub fn write_image(mut write: impl Write/* + Seek*/, bytes: &[u8], width: u32, height: u32, color_type: ColorType) -> ImageResult<()> {
    let width = width as usize;
    let height = height as usize;

    let mut seekable_write = Cursor::new(Vec::with_capacity(width*height*3*4)); // TODO remove

    match color_type {
        ColorType::Rgb32F => {
            let pixels: &[f32] = bytemuck::try_cast_slice(bytes)
                .expect("image byte buffer must be aligned to f32");

            exr::prelude::Image
                ::from_channels(
                    (width, height),
                    SpecificChannels::rgb(|mut pixel: Vec2<usize>| {
                        debug_assert_ne!(height, 0);
                        pixel.1 = height - 1 - pixel.1; // openexr stores +y upwards, but we need +y downwards

                        let pixel_index = 3 * pixel.flat_index_for_size(Vec2(width, height));
                        (pixels[pixel_index], pixels[pixel_index+1], pixels[pixel_index+2])
                    })
                )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?; // TODO BufWrite::new()?
        }

        ColorType::Rgba32F => {
            let pixels: &[f32] = bytemuck::try_cast_slice(bytes)
                .expect("image byte buffer must be aligned to f32");

            exr::prelude::Image
                ::from_channels(
                    (width, height),
                    SpecificChannels::rgba(|mut pixel: Vec2<usize>| {
                        debug_assert_ne!(height, 0);
                        pixel.1 = height - 1 - pixel.1; // openexr stores +y upwards, but we need +y downwards

                        let pixel_index = 4 * pixel.flat_index_for_size(Vec2(width, height));
                        (pixels[pixel_index], pixels[pixel_index+1], pixels[pixel_index+2], pixels[pixel_index+3])
                    })
                )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?; // TODO BufWrite::new()?
        }

        _ => todo!()
    }

    write.write_all(seekable_write.into_inner().as_slice())?;
    Ok(())
}

impl From<Error> for ImageError {
    fn from(exr_error: Error) -> Self {
        ImageError::Decoding(DecodingError::new(
            ImageFormatHint::Exact(ImageFormat::Exr),
            exr_error
        ))
    }
}

<|endoftext|>


<commit_before>extern crate serenity;

command!(clear(_context, msg, args) {
	if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(countdown)) {
				let mut vec_id = Vec::new();
				for message in vec {
					vec_id.push(message.id);
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
	else if args.len() == 1 {
		let countdown: usize = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let counter: usize = match args[1].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let full = countdown + counter;
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(full as u64)) {
				let mut vec_id = Vec::new();
				let mut i = 0;
				while i < countdown {
					vec_id.push(vec[i].id);
					i += 1;
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
});
<commit_msg>Fixes for clear<commit_after>extern crate serenity;

command!(clear(_context, msg, args) {
	if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(countdown)) {
				let mut vec_id = Vec::new();
				for message in vec {
					vec_id.push(message.id);
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
	else if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let counter: u64 = match args[1].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let full = countdown + counter;
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(full)) {
				let mut vec_id = Vec::new();
				let mut i = 0;
				for message in vec {
					if i < countdown {
						vec_id.push(message.id);
					}
					i += 1;
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
});
<|endoftext|>


<commit_before>use std::sync::{Arc,Mutex,Once,ONCE_INIT};
use std::collections::VecDeque;
use std::mem;
use gfx;
use gfx::traits::*;
use gfx_text;
use vecmath::*;

use line_renderer::LineRenderer;

#[derive(Debug)]
pub enum DebugRendererError {
    ShaderProgramError(gfx::ProgramError),
    BufferUpdateError(gfx::device::BufferUpdateError),
    GfxTextError(gfx_text::Error)
}

impl From<gfx::ProgramError> for DebugRendererError {
    fn from(err: gfx::ProgramError) -> DebugRendererError {
        DebugRendererError::ShaderProgramError(err)
    }
}

impl From<gfx::device::BufferUpdateError> for DebugRendererError {
    fn from(err: gfx::device::BufferUpdateError) -> DebugRendererError {
        DebugRendererError::BufferUpdateError(err)
    }
}

impl From<gfx_text::Error> for DebugRendererError {
    fn from(err: gfx_text::Error) -> DebugRendererError {
        DebugRendererError::GfxTextError(err)
    }
}

pub struct DebugRenderer<R: gfx::Resources, F: Factory<R>> {
    line_renderer: LineRenderer<R>,
    text_renderer: gfx_text::Renderer<R, F>,
    factory: F,
}

type WorldPosition = [f32; 3];
type ScreenPosition = [i32; 2];
type Color = [f32; 4];
type Size = f32;

enum DrawCommand {
    DrawLine(WorldPosition, WorldPosition, Color),
    DrawMarker(WorldPosition, Size, Color),
    DrawScreenText(String, ScreenPosition, Color),
    DrawWorldText(String, WorldPosition, Color),
}

#[derive(Clone)]
struct CommandQueue {
    queue: Arc<Mutex<VecDeque<DrawCommand>>>
}

impl CommandQueue {

    fn push_back(&mut self, command: DrawCommand) {
        let mut queue = self.queue.lock().unwrap();
        queue.push_back(command);
    }

    fn pop_front(&mut self) -> Option<DrawCommand> {
        let mut queue = self.queue.lock().unwrap();
        queue.pop_front()
    }

    fn instance() -> CommandQueue {
        static mut command_queue_singleton: *const CommandQueue = 0 as *const CommandQueue;
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                let command_queue = CommandQueue {
                    queue: Arc::new(Mutex::new(VecDeque::<DrawCommand>::new()))
                };
                command_queue_singleton = mem::transmute(Box::new(command_queue));
            });
            (*command_queue_singleton).clone()
        }
    }
}

pub fn draw_marker(position: [f32; 3], size: f32, color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawMarker(position, size, color));
}

pub fn draw_line(start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawLine(start, end, color));
}

pub fn draw_text_on_screen(text: &str, screen_position: [i32; 2], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawScreenText(text.to_string(), screen_position, color));
}

pub fn draw_text_at_position(text: &str, position: [f32; 3], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawWorldText(text.to_string(), position, color));
}

impl<R: gfx::Resources, F: Factory<R>> DebugRenderer<R, F> {

    pub fn new (
        factory: F,
        text_renderer: gfx_text::Renderer<R, F>,
        initial_buffer_size: usize,
    ) -> Result<DebugRenderer<R, F>, DebugRendererError> {

        let mut factory = factory;
        let line_renderer = try!(LineRenderer::new(&mut factory, initial_buffer_size));

        Ok(DebugRenderer {
            line_renderer: line_renderer,
            text_renderer: text_renderer,
            factory: factory,
        })
    }

    pub fn draw_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
        self.line_renderer.draw_line(start, end, color);
    }

    pub fn draw_marker(&mut self, position: [f32; 3], size: f32, color: [f32; 4]) {
        self.line_renderer.draw_line(vec3_add(position, [size, 0.0, 0.0]),
                                     vec3_add(position, [-size, 0.0, 0.0]),
                                     color);

        self.line_renderer.draw_line(vec3_add(position, [0.0, size, 0.0]),
                                     vec3_add(position, [0.0, -size, 0.0]),
                                     color);

        self.line_renderer.draw_line(vec3_add(position, [0.0, 0.0, size]),
                                     vec3_add(position, [0.0, 0.0, -size]),
                                     color);
    }

    pub fn draw_text_on_screen (
        &mut self,
        text: &str,
        screen_position: [i32; 2],
        color: [f32; 4],
    ) {
        self.text_renderer.draw(text, screen_position, color);
    }

    pub fn draw_text_at_position (
        &mut self,
        text: &str,
        world_position: [f32; 3],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_at(text, world_position, color);
    }

    pub fn render<S: gfx::Stream<R>> (
        &mut self,
        stream: &mut S,
        projection: [[f32; 4]; 4],
    ) -> Result<(), DebugRendererError> {

        loop {
            match CommandQueue::instance().pop_front() {
                Some(DrawCommand::DrawLine(start, end, color)) => {
                    self.draw_line(start, end, color);
                },
                Some(DrawCommand::DrawMarker(position, size, color)) => {
                    self.draw_marker(position, size, color);
                },
                Some(DrawCommand::DrawScreenText(ref text, position, color)) => {
                    self.draw_text_on_screen(&text, position, color);
                },
                Some(DrawCommand::DrawWorldText(ref text, position, color)) => {
                    self.draw_text_at_position(&text, position, color);
                }
                None => break
            }
        }

        try!(self.line_renderer.render(stream, &mut self.factory, projection));
        try!(self.text_renderer.draw_end_at(stream, projection));
        Ok(())
    }
}
<commit_msg>Band-aid fix for singleton memory leak<commit_after>use std::collections::VecDeque;
use std::mem;
use std::sync::{Arc,Mutex,Once,ONCE_INIT};
use gfx;
use gfx::traits::*;
use gfx_text;
use vecmath::*;

use line_renderer::LineRenderer;

type WorldPosition = [f32; 3];
type ScreenPosition = [i32; 2];
type Color = [f32; 4];
type Size = f32;

enum DrawCommand {
    DrawLine(WorldPosition, WorldPosition, Color),
    DrawMarker(WorldPosition, Size, Color),
    DrawScreenText(String, ScreenPosition, Color),
    DrawWorldText(String, WorldPosition, Color),
}

#[derive(Clone)]
struct CommandQueue {
    queue: Arc<Mutex<VecDeque<DrawCommand>>>
}

static mut command_queue_singleton: *const CommandQueue = 0 as *const CommandQueue;

impl CommandQueue {

    fn push_back(&mut self, command: DrawCommand) {
        let mut queue = self.queue.lock().unwrap();
        queue.push_back(command);
    }

    fn pop_front(&mut self) -> Option<DrawCommand> {
        let mut queue = self.queue.lock().unwrap();
        queue.pop_front()
    }

    fn instance() -> CommandQueue {
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                let command_queue = CommandQueue {
                    queue: Arc::new(Mutex::new(VecDeque::<DrawCommand>::new()))
                };
                command_queue_singleton = mem::transmute(Box::new(command_queue));
            });
            (*command_queue_singleton).clone()
        }
    }
}

pub fn draw_marker(position: [f32; 3], size: f32, color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawMarker(position, size, color));
}

pub fn draw_line(start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawLine(start, end, color));
}

pub fn draw_text_on_screen(text: &str, screen_position: [i32; 2], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawScreenText(text.to_string(), screen_position, color));
}

pub fn draw_text_at_position(text: &str, position: [f32; 3], color: [f32; 4]) {
    CommandQueue::instance().push_back(DrawCommand::DrawWorldText(text.to_string(), position, color));
}

#[derive(Debug)]
pub enum DebugRendererError {
    ShaderProgramError(gfx::ProgramError),
    BufferUpdateError(gfx::device::BufferUpdateError),
    GfxTextError(gfx_text::Error)
}

impl From<gfx::ProgramError> for DebugRendererError {
    fn from(err: gfx::ProgramError) -> DebugRendererError {
        DebugRendererError::ShaderProgramError(err)
    }
}

impl From<gfx::device::BufferUpdateError> for DebugRendererError {
    fn from(err: gfx::device::BufferUpdateError) -> DebugRendererError {
        DebugRendererError::BufferUpdateError(err)
    }
}

impl From<gfx_text::Error> for DebugRendererError {
    fn from(err: gfx_text::Error) -> DebugRendererError {
        DebugRendererError::GfxTextError(err)
    }
}

pub struct DebugRenderer<R: gfx::Resources, F: Factory<R>> {
    line_renderer: LineRenderer<R>,
    text_renderer: gfx_text::Renderer<R, F>,
    factory: F,
}

impl<R: gfx::Resources, F: Factory<R>> Drop for DebugRenderer<R, F> {

    /// Frees memory alocated for the command queue singleton
    ///
    /// Could be leaky if a `gfx_debug_draw::draw_*` method is called without
    /// ever instantiating a DebugRenderer. Also could be problematic if there
    /// are multiple DebugRenderer instances.
    ///
    /// Should look into freeing memory on `rt::at_exit` if/when that becomes stable
    /// See http://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton
    fn drop(&mut self) {
        unsafe {
            if command_queue_singleton != 0 as *const _ {
                let command_queue: Box<CommandQueue> = mem::transmute(command_queue_singleton);
                drop(command_queue);
                command_queue_singleton = 0 as *const _;
            }
        }
    }
}

impl<R: gfx::Resources, F: Factory<R>> DebugRenderer<R, F> {

    pub fn new (
        factory: F,
        text_renderer: gfx_text::Renderer<R, F>,
        initial_buffer_size: usize,
    ) -> Result<DebugRenderer<R, F>, DebugRendererError> {

        let mut factory = factory;
        let line_renderer = try!(LineRenderer::new(&mut factory, initial_buffer_size));

        Ok(DebugRenderer {
            line_renderer: line_renderer,
            text_renderer: text_renderer,
            factory: factory,
        })
    }

    pub fn draw_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
        self.line_renderer.draw_line(start, end, color);
    }

    pub fn draw_marker(&mut self, position: [f32; 3], size: f32, color: [f32; 4]) {
        self.line_renderer.draw_line(vec3_add(position, [size, 0.0, 0.0]),
                                     vec3_add(position, [-size, 0.0, 0.0]),
                                     color);

        self.line_renderer.draw_line(vec3_add(position, [0.0, size, 0.0]),
                                     vec3_add(position, [0.0, -size, 0.0]),
                                     color);

        self.line_renderer.draw_line(vec3_add(position, [0.0, 0.0, size]),
                                     vec3_add(position, [0.0, 0.0, -size]),
                                     color);
    }

    pub fn draw_text_on_screen (
        &mut self,
        text: &str,
        screen_position: [i32; 2],
        color: [f32; 4],
    ) {
        self.text_renderer.draw(text, screen_position, color);
    }

    pub fn draw_text_at_position (
        &mut self,
        text: &str,
        world_position: [f32; 3],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_at(text, world_position, color);
    }

    pub fn render<S: gfx::Stream<R>> (
        &mut self,
        stream: &mut S,
        projection: [[f32; 4]; 4],
    ) -> Result<(), DebugRendererError> {

        loop {
            match CommandQueue::instance().pop_front() {
                Some(DrawCommand::DrawLine(start, end, color)) => {
                    self.draw_line(start, end, color);
                },
                Some(DrawCommand::DrawMarker(position, size, color)) => {
                    self.draw_marker(position, size, color);
                },
                Some(DrawCommand::DrawScreenText(ref text, position, color)) => {
                    self.draw_text_on_screen(&text, position, color);
                },
                Some(DrawCommand::DrawWorldText(ref text, position, color)) => {
                    self.draw_text_at_position(&text, position, color);
                }
                None => break
            }
        }

        try!(self.line_renderer.render(stream, &mut self.factory, projection));
        try!(self.text_renderer.draw_end_at(stream, projection));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use EitherOrBoth::*;

use either::Either;

/// Value that either holds a single A or B, or both.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum EitherOrBoth<A, B> {
    /// Both values are present.
    Both(A, B),
    /// Only the left value of type `A` is present.
    Left(A),
    /// Only the right value of type `B` is present.
    Right(B),
}

impl<A, B> EitherOrBoth<A, B> {
    /// If `Left`, or `Both`, return true, otherwise, return false.
    pub fn has_left(&self) -> bool {
        self.as_ref().left().is_some()
    }

    /// If `Right`, or `Both`, return true, otherwise, return false.
    pub fn has_right(&self) -> bool {
        self.as_ref().right().is_some()
    }

    /// If Left, return true otherwise, return false.
    /// Exclusive version of [`has_left`].
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            _ => false,
        }
    }

    /// If Right, return true otherwise, return false.
    /// Exclusive version of [`has_right`].
    pub fn is_right(&self) -> bool {
        match *self {
            Right(_) => true,
            _ => false,
        }
    }

    /// If Right, return true otherwise, return false.
    /// Equivalent to `self.as_ref().both().is_some()`.
    pub fn is_both(&self) -> bool {
        self.as_ref().both().is_some()
    }

    /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`.
    pub fn left(self) -> Option<A> {
        match self {
            Left(left) | Both(left, _) => Some(left),
            _ => None,
        }
    }

    /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`.
    pub fn right(self) -> Option<B> {
        match self {
            Right(right) | Both(_, right) => Some(right),
            _ => None,
        }
    }

    /// If Both, return `Some` tuple containing left and right.
    pub fn both(self) -> Option<(A, B)> {
        match self {
            Both(a, b) => Some((a, b)),
            _ => None,
        }
    }

    /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`.
    pub fn as_ref(&self) -> EitherOrBoth<&A, &B> {
        match *self {
            Left(ref left) => Left(left),
            Right(ref right) => Right(right),
            Both(ref left, ref right) => Both(left, right),
        }
    }

    /// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut A, &mut B>`.
    pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> {
        match *self {
            Left(ref mut left) => Left(left),
            Right(ref mut right) => Right(right),
            Both(ref mut left, ref mut right) => Both(left, right),
        }
    }

    /// Convert `EitherOrBoth<A, B>` to `EitherOrBoth<B, A>`.
    pub fn flip(self) -> EitherOrBoth<B, A> {
        match self {
            Left(a) => Right(a),
            Right(b) => Left(b),
            Both(a, b) => Both(b, a),
        }
    }

    /// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is
    /// present rewrapping the result in `self`'s original variant.
    pub fn map_left<F, M>(self, f: F) -> EitherOrBoth<M, B>
    where
        F: FnOnce(A) -> M,
    {
        match self {
            Both(a, b) => Both(f(a), b),
            Left(a) => Left(f(a)),
            Right(b) => Right(b),
        }
    }

    /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants.
    /// If it is present rewrapping the result in `self`'s original variant.
    pub fn map_right<F, M>(self, f: F) -> EitherOrBoth<A, M>
    where
        F: FnOnce(B) -> M,
    {
        match self {
            Left(a) => Left(a),
            Right(b) => Right(f(b)),
            Both(a, b) => Both(a, f(b)),
        }
    }

    /// Apply the functions `f` and `g` on the value `a` and `b` respectively;
    /// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants.
    /// The Result is rewrapped `self`'s original variant.
    pub fn map_any<F, L, G, R>(self, f: F, g: G) -> EitherOrBoth<L, R>
    where
        F: FnOnce(A) -> L,
        G: FnOnce(B) -> R,
    {
        match self {
            Left(a) => Left(f(a)),
            Right(b) => Right(g(b)),
            Both(a, b) => Both(f(a), g(b)),
        }
    }

    /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, _)` variants if it is
    /// present.
    pub fn left_and_then<F, L>(self, f: F) -> EitherOrBoth<L, B>
    where
        F: FnOnce(A) -> EitherOrBoth<L, B>,
    {
        match self {
            Left(a) | Both(a, _) => f(a),
            Right(b) => Right(b),
        }
    }

    /// Apply the function `f` on the value `a`
    /// in `Left(a)` or `Both(a, _)` variants if it is present.
    pub fn right_and_then<F, R>(self, f: F) -> EitherOrBoth<A, R>
    where
        F: FnOnce(B) -> EitherOrBoth<A, R>,
    {
        match self {
            Left(a) => Left(a),
            Right(b) | Both(_, b) => f(b),
        }
    }
}

impl<T> EitherOrBoth<T, T> {
    /// Return either value of left, right, or the product of `f` applied where `Both` are present.
    pub fn reduce<F>(self, f: F) -> T
    where
        F: FnOnce(T, T) -> T,
    {
        match self {
            Left(a) => a,
            Right(b) => b,
            Both(a, b) => f(a, b),
        }
    }
}

impl<A, B> Into<Option<Either<A, B>>> for EitherOrBoth<A, B> {
    fn into(self) -> Option<Either<A, B>> {
        match self {
            EitherOrBoth::Left(l) => Some(Either::Left(l)),
            EitherOrBoth::Right(r) => Some(Either::Right(r)),
            _ => None,
        }
    }
}
<commit_msg>Derive Hash for EitherOrBoth<commit_after>use EitherOrBoth::*;

use either::Either;

/// Value that either holds a single A or B, or both.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum EitherOrBoth<A, B> {
    /// Both values are present.
    Both(A, B),
    /// Only the left value of type `A` is present.
    Left(A),
    /// Only the right value of type `B` is present.
    Right(B),
}

impl<A, B> EitherOrBoth<A, B> {
    /// If `Left`, or `Both`, return true, otherwise, return false.
    pub fn has_left(&self) -> bool {
        self.as_ref().left().is_some()
    }

    /// If `Right`, or `Both`, return true, otherwise, return false.
    pub fn has_right(&self) -> bool {
        self.as_ref().right().is_some()
    }

    /// If Left, return true otherwise, return false.
    /// Exclusive version of [`has_left`].
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            _ => false,
        }
    }

    /// If Right, return true otherwise, return false.
    /// Exclusive version of [`has_right`].
    pub fn is_right(&self) -> bool {
        match *self {
            Right(_) => true,
            _ => false,
        }
    }

    /// If Right, return true otherwise, return false.
    /// Equivalent to `self.as_ref().both().is_some()`.
    pub fn is_both(&self) -> bool {
        self.as_ref().both().is_some()
    }

    /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`.
    pub fn left(self) -> Option<A> {
        match self {
            Left(left) | Both(left, _) => Some(left),
            _ => None,
        }
    }

    /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`.
    pub fn right(self) -> Option<B> {
        match self {
            Right(right) | Both(_, right) => Some(right),
            _ => None,
        }
    }

    /// If Both, return `Some` tuple containing left and right.
    pub fn both(self) -> Option<(A, B)> {
        match self {
            Both(a, b) => Some((a, b)),
            _ => None,
        }
    }

    /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`.
    pub fn as_ref(&self) -> EitherOrBoth<&A, &B> {
        match *self {
            Left(ref left) => Left(left),
            Right(ref right) => Right(right),
            Both(ref left, ref right) => Both(left, right),
        }
    }

    /// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut A, &mut B>`.
    pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> {
        match *self {
            Left(ref mut left) => Left(left),
            Right(ref mut right) => Right(right),
            Both(ref mut left, ref mut right) => Both(left, right),
        }
    }

    /// Convert `EitherOrBoth<A, B>` to `EitherOrBoth<B, A>`.
    pub fn flip(self) -> EitherOrBoth<B, A> {
        match self {
            Left(a) => Right(a),
            Right(b) => Left(b),
            Both(a, b) => Both(b, a),
        }
    }

    /// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is
    /// present rewrapping the result in `self`'s original variant.
    pub fn map_left<F, M>(self, f: F) -> EitherOrBoth<M, B>
    where
        F: FnOnce(A) -> M,
    {
        match self {
            Both(a, b) => Both(f(a), b),
            Left(a) => Left(f(a)),
            Right(b) => Right(b),
        }
    }

    /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants.
    /// If it is present rewrapping the result in `self`'s original variant.
    pub fn map_right<F, M>(self, f: F) -> EitherOrBoth<A, M>
    where
        F: FnOnce(B) -> M,
    {
        match self {
            Left(a) => Left(a),
            Right(b) => Right(f(b)),
            Both(a, b) => Both(a, f(b)),
        }
    }

    /// Apply the functions `f` and `g` on the value `a` and `b` respectively;
    /// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants.
    /// The Result is rewrapped `self`'s original variant.
    pub fn map_any<F, L, G, R>(self, f: F, g: G) -> EitherOrBoth<L, R>
    where
        F: FnOnce(A) -> L,
        G: FnOnce(B) -> R,
    {
        match self {
            Left(a) => Left(f(a)),
            Right(b) => Right(g(b)),
            Both(a, b) => Both(f(a), g(b)),
        }
    }

    /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, _)` variants if it is
    /// present.
    pub fn left_and_then<F, L>(self, f: F) -> EitherOrBoth<L, B>
    where
        F: FnOnce(A) -> EitherOrBoth<L, B>,
    {
        match self {
            Left(a) | Both(a, _) => f(a),
            Right(b) => Right(b),
        }
    }

    /// Apply the function `f` on the value `a`
    /// in `Left(a)` or `Both(a, _)` variants if it is present.
    pub fn right_and_then<F, R>(self, f: F) -> EitherOrBoth<A, R>
    where
        F: FnOnce(B) -> EitherOrBoth<A, R>,
    {
        match self {
            Left(a) => Left(a),
            Right(b) | Both(_, b) => f(b),
        }
    }
}

impl<T> EitherOrBoth<T, T> {
    /// Return either value of left, right, or the product of `f` applied where `Both` are present.
    pub fn reduce<F>(self, f: F) -> T
    where
        F: FnOnce(T, T) -> T,
    {
        match self {
            Left(a) => a,
            Right(b) => b,
            Both(a, b) => f(a, b),
        }
    }
}

impl<A, B> Into<Option<Either<A, B>>> for EitherOrBoth<A, B> {
    fn into(self) -> Option<Either<A, B>> {
        match self {
            EitherOrBoth::Left(l) => Some(Either::Left(l)),
            EitherOrBoth::Right(r) => Some(Either::Right(r)),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>use super::{Leaf, Node};
use metric::Line;

#[test]
fn line_split_test_1() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_2() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_3() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
#[should_panic(expected = "invalid index!")]
fn line_split_test_4() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
}

#[test]
fn line_split_test_5() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_6() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdf\nqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_7() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
fn line_split_test_8() {
    let l1 = Node::new_leaf("");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "qwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_9() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l1, l2);
    let b2 = Node::new_branch(b1, l3);
    let (left, right) = b2.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    assert_eq!(right.strings().collect::<String>(), "qweryxcv\n");
}

#[test]
fn line_split_test_10() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l2, l3);
    let b2 = Node::new_branch(l1, b1);
    let (left, right) = b2.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "yxcv\n");
    } else { assert!(false) }
}
<commit_msg>test(rope internals): fix scoped import issue in tests<commit_after>use super::{Value, Node};
use self::Value::Leaf;
use metric::Line;

#[test]
fn line_split_test_1() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_2() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_3() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
#[should_panic(expected = "invalid index!")]
fn line_split_test_4() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
}

#[test]
fn line_split_test_5() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_6() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdf\nqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_7() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
fn line_split_test_8() {
    let l1 = Node::new_leaf("");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "qwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_9() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l1, l2);
    let b2 = Node::new_branch(b1, l3);
    let (left, right) = b2.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    assert_eq!(right.strings().collect::<String>(), "qweryxcv\n");
}

#[test]
fn line_split_test_10() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l2, l3);
    let b2 = Node::new_branch(l1, b1);
    let (left, right) = b2.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "yxcv\n");
    } else { assert!(false) }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//! Keys for RxRPC clients.

use std::borrow::Cow;

use crate::keytype::*;

/// An RxRPC client key.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct RxRPC;

impl KeyType for RxRPC {
    /// RxRPC client key descriptions are free-form.
    type Description = str;
    type Payload = Payload;

    fn name() -> &'static str {
        "rxrpc"
    }
}

/// The payload for RxRPC client keys.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Payload {
    expiry: u32,
    version: u8,
    session_key: [u8; 8],
    ticket: Vec<u8>,
}

impl KeyPayload for Payload {
    fn payload(&self) -> Cow<[u8]> {
        let mut payload = Vec::new();

        // struct rxrpc_key_sec2_v1 {
        //     uint16_t    security_index; /* 2 */
        //     uint16_t    ticket_length;  /* length of ticket[] */
        //     uint32_t    expiry;         /* time at which expires */
        //     uint8_t     kvno;           /* key version number */
        //     uint8_t     __pad[3];
        //     uint8_t     session_key[8]; /* DES session key */
        //     uint8_t     ticket[0];      /* the encrypted ticket */
        // };

        payload.extend((2 as u16).to_ne_bytes().iter());
        payload.extend((self.ticket.len() as u16).to_ne_bytes().iter());
        payload.extend(self.expiry.to_ne_bytes().iter());
        payload.extend(self.version.to_ne_bytes().iter());
        payload.extend([0u8; 3].iter());
        payload.extend(self.session_key.iter());
        payload.extend(self.ticket.iter());

        payload.into()
    }
}
<commit_msg>rxrpc: avoid an unnecessary cast<commit_after>// Copyright (c) 2015, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//! Keys for RxRPC clients.

use std::borrow::Cow;

use crate::keytype::*;

/// An RxRPC client key.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct RxRPC;

impl KeyType for RxRPC {
    /// RxRPC client key descriptions are free-form.
    type Description = str;
    type Payload = Payload;

    fn name() -> &'static str {
        "rxrpc"
    }
}

/// The payload for RxRPC client keys.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Payload {
    expiry: u32,
    version: u8,
    session_key: [u8; 8],
    ticket: Vec<u8>,
}

impl KeyPayload for Payload {
    fn payload(&self) -> Cow<[u8]> {
        let mut payload = Vec::new();

        // struct rxrpc_key_sec2_v1 {
        //     uint16_t    security_index; /* 2 */
        //     uint16_t    ticket_length;  /* length of ticket[] */
        //     uint32_t    expiry;         /* time at which expires */
        //     uint8_t     kvno;           /* key version number */
        //     uint8_t     __pad[3];
        //     uint8_t     session_key[8]; /* DES session key */
        //     uint8_t     ticket[0];      /* the encrypted ticket */
        // };

        payload.extend(2_u16.to_ne_bytes().iter());
        payload.extend((self.ticket.len() as u16).to_ne_bytes().iter());
        payload.extend(self.expiry.to_ne_bytes().iter());
        payload.extend(self.version.to_ne_bytes().iter());
        payload.extend([0u8; 3].iter());
        payload.extend(self.session_key.iter());
        payload.extend(self.ticket.iter());

        payload.into()
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::io::Write;
use std::process::Command;
use std::path::Path;
use std::env;
use std::string::String;

pub struct Python {
    user: String,
    subject: String,
}

pub struct Scala {
    user: String,
    subject: String,
}

fn echo(solution: &str, path: &Path) -> io::Result<()> {
    let mut file = try!(fs::File::create(path));
    file.write_all(solution.as_bytes())
}

pub trait Lang {
    fn new(user: String, subject: String) -> Self;
    fn run_test(&self, solution: &str) -> String;
}

impl Lang for Python {
    fn new(user: String, subject: String) -> Python {
        Python { user: user, subject: subject}
    }

    fn run_test(&self, solution: &str) -> String {
        let from = format!("/home/{}/Code-Fight/python/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/python/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        // write solution to solution.py
        echo(solution, &Path::new(&format!("{}/solution.py", &to)));

        // run test
        let result = Command::new("nosetests")
               .arg(&to)
               .output()
               .expect("cat error to start");

    //    println!("result: {:?}", &result);
        format!("{:?}", &result)
    }
}

impl Lang for Scala {
    fn new(user: String, subject: String) -> Scala {
        Scala { user: user, subject: subject}
    }

    fn run_test(&self, solution: &str) -> String {
        let from = format!("/home/{}/Code-Fight/scala/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/scala/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        // write solution to Solution.scala
        echo(solution, &Path::new(&format!("{}/src/main/scala/org/sparktw/codefight/Solution.scala", &to)));

        // change location to subject
        let path = Path::new(&to);
        env::set_current_dir(&path).is_ok();

        // run test
        let result = Command::new("sbt")
               .arg("test")
               .output()
               .expect("cat error to start");

        println!("result: {:?}", &result);
        format!("{:?}", &result)
    }
}
<commit_msg>remove sbt test result<commit_after>use std::fs;
use std::io;
use std::io::Write;
use std::process::Command;
use std::path::Path;
use std::env;
use std::string::String;

pub struct Python {
    user: String,
    subject: String,
}

pub struct Scala {
    user: String,
    subject: String,
}

fn echo(solution: &str, path: &Path) -> io::Result<()> {
    let mut file = try!(fs::File::create(path));
    file.write_all(solution.as_bytes())
}

pub trait Lang {
    fn new(user: String, subject: String) -> Self;
    fn run_test(&self, solution: &str) -> String;
}

impl Lang for Python {
    fn new(user: String, subject: String) -> Python {
        Python { user: user, subject: subject}
    }

    fn run_test(&self, solution: &str) -> String {
        let from = format!("/home/{}/Code-Fight/python/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/python/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        // write solution to solution.py
        echo(solution, &Path::new(&format!("{}/solution.py", &to)));

        // run test
        let result = Command::new("nosetests")
               .arg(&to)
               .output()
               .expect("cat error to start");

    //    println!("result: {:?}", &result);
        format!("{:?}", &result)
    }
}

impl Lang for Scala {
    fn new(user: String, subject: String) -> Scala {
        Scala { user: user, subject: subject}
    }

    fn run_test(&self, solution: &str) -> String {
        let from = format!("/home/{}/Code-Fight/scala/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/scala/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        // write solution to Solution.scala
        echo(solution, &Path::new(&format!("{}/src/main/scala/org/sparktw/codefight/Solution.scala", &to)));

        // change location to subject
        let path = Path::new(&to);
        env::set_current_dir(&path).is_ok();

        // run test
        let result = Command::new("sbt")
               .arg("test")
               .output()
               .expect("cat error to start");

        //println!("result: {:?}", &result);
        format!("{:?}", &result)
    }
}
<|endoftext|>


<commit_before>extern crate mysql;
extern crate regex;

use mysql::conn::pool::MyPool;
use mysql::conn::pool::MyPooledConn;
use mysql::conn::Stmt;

use std::process::{Command, Stdio};
use std::error::Error;
use std::io::prelude::*;
use std::io::BufReader;

#[derive(Debug)]
pub enum DownloadError {
	ConsoleError,
	RadError,
	DMCAError,
	InternalError,
}
///Regex: [download]  13.4% of 275.27MiB at 525.36KiB/s ETA 07:52
///
///Downloads a video, updates the DB
///TODO: get the sql statements out of the class
///TODO: wrap errors
///Doesn't care about DMCAs, will emit errors on them
pub fn download_video(url: &str, quality: i32, qid: i64, folderFormat: &str, pool: MyPool) -> Result<bool,DownloadError> {
	println!("{:?}", url);
	let process = match Command::new("youtube-dl")
								.arg("--newline")
								.arg(format!("-o {}",folderFormat))
								.arg(url)
								.stdin(Stdio::null())
                                .stdout(Stdio::piped())
                                .spawn() {
        Err(why) => panic!("couldn't spawn cmd: {}", Error::description(&why)),
        Ok(process) => process,
    };
	let mut s = String::new(); //buffer prep
	let mut stdout = BufReader::new(process.stdout.unwrap());

	let mut conn = pool.get_conn().unwrap();
	let statement = prepare_progress_updater(&mut conn);

	let re = create_regex(&r"\d+\.\d%");

	let i = 0;

	for line in &mut stdout.lines(){
		match line{
			Err(why) => panic!("couldn't read cmd stdout: {}", Error::description(&why)),
			Ok(text) => {
					println!("Out: {}",text);
					if re.is_match(&text) {
						println!("Match: {:?}", text);
					}
				},
		}
	}

	Ok(true)
}

fn create_regex(expression: & str) -> regex::Regex {
	match regex::Regex::new(expression) {
	    Ok(re) => re,
	    Err(err) => panic!("regex {}", err),
	}
}

fn prepare_progress_updater<'a>(conn: &'a mut MyPooledConn) -> Stmt<'a> {
	conn.prepare("UPDATE querydetails SET status = ? WHERE qid = ?").unwrap()
}

///updater called from the stdout progress
fn update_progress(stmt: &mut Stmt, progress: &String, qid: &String){
	stmt.execute(&[progress,qid]);
}<commit_msg>milestone #1 closed with this, basic progress etc working<commit_after>extern crate mysql;
extern crate regex;

use mysql::conn::pool::MyPool;
use mysql::conn::pool::MyPooledConn;
use mysql::value::ToValue;
use mysql::conn::Stmt;

use std::process::{Command, Stdio};
use std::error::Error;
use std::io::prelude::*;
use std::io::BufReader;

#[derive(Debug)]
pub enum DownloadError {
	ConsoleError,
	RadError,
	DMCAError,
	InternalError,
}
///Regex: [download]  13.4% of 275.27MiB at 525.36KiB/s ETA 07:52
///
///Downloads a video, updates the DB
///TODO: get the sql statements out of the class
///TODO: wrap errors
///Doesn't care about DMCAs, will emit errors on them
pub fn download_video(url: &str, quality: i32, qid: i64, folderFormat: &str, pool: MyPool) -> Result<bool,DownloadError> {
	println!("{:?}", url);
	let process = match Command::new("youtube-dl")
								.arg("--newline")
								.arg(format!("-o {}",folderFormat))
								.arg(url)
								.stdin(Stdio::null())
                                .stdout(Stdio::piped())
                                .spawn() {
        Err(why) => panic!("couldn't spawn cmd: {}", Error::description(&why)),
        Ok(process) => process,
    };
	let mut s = String::new(); //buffer prep
	let mut stdout = BufReader::new(process.stdout.unwrap());

	let mut conn = pool.get_conn().unwrap();
	let mut statement = prepare_progress_updater(&mut conn);
	let mut conn = pool.get_conn().unwrap();
	let re = create_regex(&r"\d+\.\d%");

	let i = 0;

	set_query_code(&mut conn, &1, &qid);

	for line in &mut stdout.lines(){
		match line{
			Err(why) => panic!("couldn't read cmd stdout: {}", Error::description(&why)),
			Ok(text) => {
					println!("Out: {}",text);
					match re.find(&text) {
						Some(s) => { println!("Match at {}", s.0);
									println!("{}", &text[s.0..s.1]); // ONLY with ASCII chars makeable!
									update_progress(&mut statement, &text[s.0..s.1].to_string(), &qid);
								},
						None => println!("Detected no % match."),
					}
					//if re.is_match(&text) {println!("Match: {:?}", text);}
				},
		}
	}

	update_progress(&mut statement, &"Finished".to_string(), &qid);
	set_query_code(&mut conn, &3, &qid);

	Ok(true)
}

fn create_regex(expression: & str) -> regex::Regex {
	match regex::Regex::new(expression) {
	    Ok(re) => re,
	    Err(err) => panic!("regex {}", err),
	}
}

// MyPooledConn does only live when MyOpts is alive -> lifetime needs to be declared
fn prepare_progress_updater<'a>(conn: &'a mut MyPooledConn) -> Stmt<'a> {
	conn.prepare("UPDATE querydetails SET status = ? WHERE qid = ?").unwrap()
}

fn set_query_code<'a>(conn: &'a mut MyPooledConn, code: &i8, qid: &i64){
	let mut stmt = conn.prepare("UPDATE querydetails SET code = ? WHERE qid = ?").unwrap();
	stmt.execute(&[code,qid]);
}

///updater called from the stdout progress
fn update_progress(stmt: &mut Stmt, progress: &String, qid: &i64){
	stmt.execute(&[progress,qid]);
}<|endoftext|>


<commit_before>// Copyright 2015 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use ::util::core::*;
use ::util::string::*;
use ::source_model::*;

use ::syntex_syntax::syntax::ast;
use ::syntex_syntax::parse::{ self, ParseSess };
use ::syntex_syntax::visit;
use ::syntex_syntax::codemap:: { self, Span, CodeMap};
use ::syntex_syntax::errors:: { Handler, RenderSpan, Level, emitter };

use std::boxed::Box;
use std::path::Path;

use ::token_writer::TokenWriter;

use std::cell::RefCell;
use std::rc::*;
use std::io;
use std::io::Write;
use std::fmt;

/* -----------------  ----------------- */

pub fn parse_analysis_forStdout(source : &str) {
    parse_analysis(source, StdoutWrite(io::stdout())).ok();
    println!("");
    io::stdout().flush().ok();
}

pub fn parse_analysis<T : fmt::Write + 'static>(source : &str, out : T) -> GResult<T> {
    let (messages, elements) = parse_crate_with_messages(source);

    let outRc = Rc::new(RefCell::new(out));
    try!(write_parse_analysis_do(messages, elements, outRc.clone()));
    let res = unwrap_Rc_RefCell(outRc);
    return Ok(res);
}

use std::thread;
use std::sync::{Arc, Mutex};

pub fn parse_crate_with_messages(source: &str) -> (Vec<SourceMessage>, Vec<StructureElement>) {

    let messages = Arc::new(Mutex::new(vec![]));
    let elements =
    {
        let source = String::from(source);
        let messages = messages.clone();

        let worker_thread = thread::Builder::new().name("parser_thread".to_string()).spawn(move || {
            parse_crate_with_messages_do(&source, messages)
        }).unwrap();

        worker_thread.join().unwrap_or(vec![])
    };

    let messages : Mutex<Vec<SourceMessage>> = Arc::try_unwrap(messages).ok().unwrap();
    let messages : Vec<SourceMessage> = messages.into_inner().unwrap();

    return (messages, elements);
}

pub fn parse_crate_with_messages_do(source: &str, messages: Arc<Mutex<Vec<SourceMessage>>>)
    -> Vec<StructureElement>
{
    use ::structure_visitor::StructureVisitor;

    let mut elements = vec![];

    let fileLoader = Box::new(DummyFileLoader::new());
    let codemap = Rc::new(CodeMap::with_file_loader(fileLoader));

    let krate = parse_crate(source, codemap.clone(), messages.clone());

    if let Some(krate) = krate {
        let mut visitor : StructureVisitor = StructureVisitor::new(&codemap);
        visit::walk_crate(&mut visitor, &krate);

        elements = visitor.elements;
    }
    return elements;
}

/* -----------------  ----------------- */

use std::ffi::OsStr;

/// A FileLoader that loads any file successfully
pub struct DummyFileLoader {
       modName : &'static OsStr,
}

impl DummyFileLoader {
    fn new() -> DummyFileLoader {
        DummyFileLoader { modName : OsStr::new("mod.rs") }
    }
}

impl codemap::FileLoader for DummyFileLoader {
    fn file_exists(&self, path: &Path) -> bool {
        return path.file_name() == Some(self.modName);
    }

    fn read_file(&self, _path: &Path) -> io::Result<String> {
        Ok(String::new())
    }
}

struct MessagesHandler {
    codemap : Rc<CodeMap>,
    messages : Arc<Mutex<Vec<SourceMessage>>>,
}

fn parse_crate<'a>(source: &str, codemap: Rc<CodeMap>, messages: Arc<Mutex<Vec<SourceMessage>>>) -> Option<ast::Crate>
{
    let emitter = MessagesHandler::new(codemap.clone(), messages.clone());

    let handler = Handler::with_emitter(true, false, Box::new(emitter));
    let sess = ParseSess::with_span_handler(handler, codemap.clone());

    let krate_result = parse_crate_do(source, &sess);

    return match krate_result {
        Ok(_krate) => {
            Some(_krate)
        }
        Err(mut db) => {
            db.emit();
            None
        }
    }
}

pub fn parse_crate_do<'a>(source : &str, sess : &'a ParseSess) -> parse::PResult<'a, ast::Crate>
{
    let source = source.to_string();

    let cfg = vec![];
    let name = "_file_module_".to_string();

//    We inlined: let mut parser = parse::new_parser_from_source_str(&sess, cfg, name, source);

    let filemap = sess.codemap().new_filemap(name, source);

    // filemap_to_tts but without a panic
    let tts =
    {
        let cfg = Vec::new();
        let srdr = parse::lexer::StringReader::new(&sess.span_diagnostic, filemap);
        let mut p1 = parse::parser::Parser::new(sess, cfg, Box::new(srdr));

        try!(p1.parse_all_token_trees())
    };

    let trdr = parse::lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
    let mut parser = parse::parser::Parser::new(sess, cfg, Box::new(trdr));

    return parser.parse_crate_mod();
}

impl MessagesHandler {

    fn new(codemap: Rc<CodeMap>, messages: Arc<Mutex<Vec<SourceMessage>>>) -> MessagesHandler {
        MessagesHandler { codemap : codemap, messages : messages }
    }

    fn writeMessage_handled(&mut self, sourcerange : Option<SourceRange>, msg: &str, severity: Severity) {

        let msg = SourceMessage{ severity : severity , sourcerange : sourcerange,  message : String::from(msg) };

        let mut messages = self.messages.lock().unwrap();
        messages.push(msg);
    }

}

impl emitter::Emitter for MessagesHandler {

    fn emit(&mut self, span: Option<Span>, msg: &str, code: Option<&str>, lvl: Level) {

        if let Some(code) = code {
               io::stderr().write_fmt(format_args!("Code: {}\n", code)).unwrap();
               panic!("What is code: Option<&str>??");
        }

        let sourcerange = match span {
            Some(span) => Some(SourceRange::new(&self.codemap, span)),
            None => None,
        };

        self.writeMessage_handled(sourcerange, msg, level_to_status_level(lvl));
    }

    fn custom_emit(&mut self, _: RenderSpan, msg: &str, lvl: Level) {
        match lvl { Level::Help | Level::Note => return, _ => () }

        self.writeMessage_handled(None, msg, level_to_status_level(lvl));
    }

}

fn level_to_status_level(lvl: Level) -> Severity {
    match lvl {
        Level::Bug => panic!("Level::BUG"),
        Level::Cancelled => panic!("Level::CANCELLED"),
        Level::Help | Level::Note => Severity::INFO,
        Level::Warning => Severity::WARNING,
        Level::Error | Level::Fatal => Severity::ERROR,
    }
}

impl MessagesHandler {
}

/* ----------------- describe writting ----------------- */

pub fn write_parse_analysis_do(messages: Vec<SourceMessage>, elements: Vec<StructureElement>,
    out : Rc<RefCell<fmt::Write>>) -> Void {

    let mut tokenWriter = TokenWriter { out : out };

    try!(tokenWriter.writeRaw("RUST_PARSE_DESCRIBE 1.0 {\n"));
    try!(write_parse_analysis_contents(messages, elements, &mut tokenWriter));
    try!(tokenWriter.writeRaw("\n}"));

    Ok(())
}

pub fn write_parse_analysis_contents(messages: Vec<SourceMessage>, elements: Vec<StructureElement>,
    tokenWriter : &mut TokenWriter) -> Void {

    try!(tokenWriter.writeRaw("MESSAGES {\n"));
    for msg in messages {
        try!(output_message(tokenWriter, msg.sourcerange, &msg.message, &msg.severity));
    }
    try!(tokenWriter.writeRaw("}\n"));

    for element in elements {
        try!(write_structure_element(tokenWriter, &element, 0));
    }

    Ok(())
}

fn output_message(tokenWriter: &mut TokenWriter, opt_sr : Option<SourceRange>, msg: & str, lvl: &Severity)
    -> Void
{

    try!(tokenWriter.writeRaw("{ "));

    try!(outputString_Level(&lvl, tokenWriter));

    try!(outputString_optSourceRange(&opt_sr, tokenWriter));

    try!(tokenWriter.writeStringToken(msg));

    try!(tokenWriter.writeRaw("}\n"));

    Ok(())
}

pub fn outputString_Level(lvl : &Severity, writer : &mut TokenWriter) -> Void {

    try!(writer.writeRawToken(lvl.to_string()));

    Ok(())
}

pub fn outputString_SourceRange(sr : &SourceRange, tw : &mut TokenWriter) -> Void {
    try!(tw.writeRaw("{ "));
    {
        let mut out = tw.getCharOut();
        try!(out.write_fmt(format_args!("{}:{} {}:{} ",
            sr.start_pos.line-1, sr.start_pos.col.0,
            sr.end_pos.line-1, sr.end_pos.col.0,
        )));
    }
    try!(tw.writeRaw("}"));

    Ok(())
}

pub fn outputString_optSourceRange(sr : &Option<SourceRange>, writer : &mut TokenWriter) -> Void {

    match sr {
        &None => try!(writer.writeRaw("{ }")) ,
        &Some(ref sr) => try!(outputString_SourceRange(sr, writer)) ,
    }

    try!(writer.writeRaw(" "));

    Ok(())
}

pub fn write_indent(tokenWriter : &mut TokenWriter, level : u32) -> Void {
    try!(writeNTimes(&mut *tokenWriter.getCharOut(), ' ', level * 2));
    Ok(())
}

pub fn write_structure_element(tw : &mut TokenWriter, element: &StructureElement, level: u32) -> Void
{
    try!(tw.writeRawToken(element.kind.to_String()));

    try!(tw.writeRaw("{ "));

    try!(tw.writeStringToken(&element.name));

    try!(outputString_SourceRange(&element.sourcerange, tw));

    try!(tw.getCharOut().write_str(" {}")); // name source range, Not Supported

    try!(tw.getCharOut().write_str(" "));
    try!(tw.writeStringToken(&element.type_desc));

    try!(tw.getCharOut().write_str("{}")); // attribs, Not Supported

    if element.children.is_empty() {
        try!(tw.getCharOut().write_str(" "));
    } else {
        let level = level + 1;

        for child in &element.children {
            try!(tw.getCharOut().write_str("\n"));
            try!(write_indent(tw, level));
            try!(write_structure_element(tw, child, level));
        }

        try!(tw.getCharOut().write_str("\n"));
        try!(write_indent(tw, level-1));
    }

    try!(tw.getCharOut().write_str("}"));

    Ok(())
}

#[cfg(test)]
mod parse_describe_tests {

    use parse_describe::*;
    use source_model::*;
    use token_writer::TokenWriter;
    use util::core::*;

    use std::rc::Rc;
    use std::cell::RefCell;

    #[test]
    fn tests_write_structure_element() {

        fn test_writeStructureElement(name : &str, kind : StructureElementKind, sr: SourceRange, type_desc : String,
            expected : &str,
        ) {
            let stringRc = Rc::new(RefCell::new(String::new()));
            {
                let name = String::from(name);
                let element = StructureElement { name: name, kind: kind, sourcerange: sr, type_desc: type_desc,
                     children: vec![]};
                let mut tw = TokenWriter { out : stringRc.clone() };

                write_structure_element(&mut tw, &element, 0).ok();
            }

            assert_eq!(unwrap_Rc_RefCell(stringRc).trim(), expected);
        }

        test_writeStructureElement("blah", StructureElementKind::Var, sourceRange(1, 0, 2, 5), "desc".to_string(),
            r#"Var { "blah" { 0:0 1:5 } {} "desc" {} }"#);
    }

    #[test]
    fn parse_analysis_tests() {
        test_parse_analysis("", "");

        test_parse_analysis(" #blah ", r#"{ ERROR { 0:2 0:6 } "expected `[`, found `blah`" }"#);

        test_parse_analysis("fn foo(\n  blah", r#"
    { ERROR { 1:6 1:6 } "this file contains an un-closed delimiter" }
    { INFO { 0:6 0:7 } "did you mean to close this delimiter?" }"#);

        // Test a lexer panic
        test_parse_analysis("const a = '",
            r#"{ ERROR { 0:10 0:11 } "character literal may only contain one codepoint: '" }"#);

//        test_parse_analysis("pub extern crate futures;",
//            r#""#);
    }

    fn test_parse_analysis(source : &str, expected_msgs : &str) {
        let result = parse_analysis(source, String::new()).ok().unwrap();
        let mut result : &str = &result;

        result = assert_surrounding_string("RUST_PARSE_DESCRIBE 1.0 {", result, "}");

        result = assert_starts_with("MESSAGES {", result.trim());
        result = assert_starts_with(expected_msgs.trim(), result.trim());
        result = assert_starts_with("}", result.trim());

        assert_eq!(result, "");
    }

    fn assert_surrounding_string<'a> (start : &str, string : &'a str, end : &str) -> &'a str {
        let mut string : &str = string;

        string = assert_starts_with(start, string);
        string = assert_ends_with(string, end);

        return string;
    }

    fn assert_starts_with<'a> (start : &str, string : &'a str) -> &'a str {
        assert!(string.starts_with(start), "`{}` does not start with `{}`", string, start);
        return &string[start.len() .. ];
    }

    fn assert_ends_with<'a> (string : &'a str, end : &str) -> &'a str {
        assert!(string.ends_with(end), "`{}` does not end with `{}`", string, end);
        return &string[0 .. string.len() - end.len()];
    }

}
<commit_msg>fix test<commit_after>// Copyright 2015 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use ::util::core::*;
use ::util::string::*;
use ::source_model::*;

use ::syntex_syntax::syntax::ast;
use ::syntex_syntax::parse::{ self, ParseSess };
use ::syntex_syntax::visit;
use ::syntex_syntax::codemap:: { self, Span, CodeMap};
use ::syntex_syntax::errors:: { Handler, RenderSpan, Level, emitter };

use std::boxed::Box;
use std::path::Path;

use ::token_writer::TokenWriter;

use std::cell::RefCell;
use std::rc::*;
use std::io;
use std::io::Write;
use std::fmt;

/* -----------------  ----------------- */

pub fn parse_analysis_forStdout(source : &str) {
    parse_analysis(source, StdoutWrite(io::stdout())).ok();
    println!("");
    io::stdout().flush().ok();
}

pub fn parse_analysis<T : fmt::Write + 'static>(source : &str, out : T) -> GResult<T> {
    let (messages, elements) = parse_crate_with_messages(source);

    let outRc = Rc::new(RefCell::new(out));
    try!(write_parse_analysis_do(messages, elements, outRc.clone()));
    let res = unwrap_Rc_RefCell(outRc);
    return Ok(res);
}

use std::thread;
use std::sync::{Arc, Mutex};

pub fn parse_crate_with_messages(source: &str) -> (Vec<SourceMessage>, Vec<StructureElement>) {

    let messages = Arc::new(Mutex::new(vec![]));
    let elements =
    {
        let source = String::from(source);
        let messages = messages.clone();

        let worker_thread = thread::Builder::new().name("parser_thread".to_string()).spawn(move || {
            parse_crate_with_messages_do(&source, messages)
        }).unwrap();

        worker_thread.join().unwrap_or(vec![])
    };

    let messages : Mutex<Vec<SourceMessage>> = Arc::try_unwrap(messages).ok().unwrap();
    let messages : Vec<SourceMessage> = messages.into_inner().unwrap();

    return (messages, elements);
}

pub fn parse_crate_with_messages_do(source: &str, messages: Arc<Mutex<Vec<SourceMessage>>>)
    -> Vec<StructureElement>
{
    use ::structure_visitor::StructureVisitor;

    let mut elements = vec![];

    let fileLoader = Box::new(DummyFileLoader::new());
    let codemap = Rc::new(CodeMap::with_file_loader(fileLoader));

    let krate = parse_crate(source, codemap.clone(), messages.clone());

    if let Some(krate) = krate {
        let mut visitor : StructureVisitor = StructureVisitor::new(&codemap);
        visit::walk_crate(&mut visitor, &krate);

        elements = visitor.elements;
    }
    return elements;
}

/* -----------------  ----------------- */

use std::ffi::OsStr;

/// A FileLoader that loads any file successfully
pub struct DummyFileLoader {
       modName : &'static OsStr,
}

impl DummyFileLoader {
    fn new() -> DummyFileLoader {
        DummyFileLoader { modName : OsStr::new("mod.rs") }
    }
}

impl codemap::FileLoader for DummyFileLoader {
    fn file_exists(&self, path: &Path) -> bool {
        return path.file_name() == Some(self.modName);
    }

    fn read_file(&self, _path: &Path) -> io::Result<String> {
        Ok(String::new())
    }
}

struct MessagesHandler {
    codemap : Rc<CodeMap>,
    messages : Arc<Mutex<Vec<SourceMessage>>>,
}

fn parse_crate<'a>(source: &str, codemap: Rc<CodeMap>, messages: Arc<Mutex<Vec<SourceMessage>>>) -> Option<ast::Crate>
{
    let emitter = MessagesHandler::new(codemap.clone(), messages.clone());

    let handler = Handler::with_emitter(true, false, Box::new(emitter));
    let sess = ParseSess::with_span_handler(handler, codemap.clone());

    let krate_result = parse_crate_do(source, &sess);

    return match krate_result {
        Ok(_krate) => {
            Some(_krate)
        }
        Err(mut db) => {
            db.emit();
            None
        }
    }
}

pub fn parse_crate_do<'a>(source : &str, sess : &'a ParseSess) -> parse::PResult<'a, ast::Crate>
{
    let source = source.to_string();

    let cfg = vec![];
    let name = "_file_module_".to_string();

//    We inlined: let mut parser = parse::new_parser_from_source_str(&sess, cfg, name, source);

    let filemap = sess.codemap().new_filemap(name, source);

    // filemap_to_tts but without a panic
    let tts =
    {
        let cfg = Vec::new();
        let srdr = parse::lexer::StringReader::new(&sess.span_diagnostic, filemap);
        let mut p1 = parse::parser::Parser::new(sess, cfg, Box::new(srdr));

        try!(p1.parse_all_token_trees())
    };

    let trdr = parse::lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
    let mut parser = parse::parser::Parser::new(sess, cfg, Box::new(trdr));

    return parser.parse_crate_mod();
}

impl MessagesHandler {

    fn new(codemap: Rc<CodeMap>, messages: Arc<Mutex<Vec<SourceMessage>>>) -> MessagesHandler {
        MessagesHandler { codemap : codemap, messages : messages }
    }

    fn writeMessage_handled(&mut self, sourcerange : Option<SourceRange>, msg: &str, severity: Severity) {

        let msg = SourceMessage{ severity : severity , sourcerange : sourcerange,  message : String::from(msg) };

        let mut messages = self.messages.lock().unwrap();
        messages.push(msg);
    }

}

impl emitter::Emitter for MessagesHandler {

    fn emit(&mut self, span: Option<Span>, msg: &str, code: Option<&str>, lvl: Level) {

        if let Some(code) = code {
               io::stderr().write_fmt(format_args!("Code: {}\n", code)).unwrap();
               panic!("What is code: Option<&str>??");
        }

        let sourcerange = match span {
            Some(span) => Some(SourceRange::new(&self.codemap, span)),
            None => None,
        };

        self.writeMessage_handled(sourcerange, msg, level_to_status_level(lvl));
    }

    fn custom_emit(&mut self, _: RenderSpan, msg: &str, lvl: Level) {
        match lvl { Level::Help | Level::Note => return, _ => () }

        self.writeMessage_handled(None, msg, level_to_status_level(lvl));
    }

}

fn level_to_status_level(lvl: Level) -> Severity {
    match lvl {
        Level::Bug => panic!("Level::BUG"),
        Level::Cancelled => panic!("Level::CANCELLED"),
        Level::Help | Level::Note => Severity::INFO,
        Level::Warning => Severity::WARNING,
        Level::Error | Level::Fatal => Severity::ERROR,
    }
}

impl MessagesHandler {
}

/* ----------------- describe writting ----------------- */

pub fn write_parse_analysis_do(messages: Vec<SourceMessage>, elements: Vec<StructureElement>,
    out : Rc<RefCell<fmt::Write>>) -> Void {

    let mut tokenWriter = TokenWriter { out : out };

    try!(tokenWriter.writeRaw("RUST_PARSE_DESCRIBE 1.0 {\n"));
    try!(write_parse_analysis_contents(messages, elements, &mut tokenWriter));
    try!(tokenWriter.writeRaw("\n}"));

    Ok(())
}

pub fn write_parse_analysis_contents(messages: Vec<SourceMessage>, elements: Vec<StructureElement>,
    tokenWriter : &mut TokenWriter) -> Void {

    try!(tokenWriter.writeRaw("MESSAGES {\n"));
    for msg in messages {
        try!(output_message(tokenWriter, msg.sourcerange, &msg.message, &msg.severity));
    }
    try!(tokenWriter.writeRaw("}\n"));

    for element in elements {
        try!(write_structure_element(tokenWriter, &element, 0));
    }

    Ok(())
}

fn output_message(tokenWriter: &mut TokenWriter, opt_sr : Option<SourceRange>, msg: & str, lvl: &Severity)
    -> Void
{

    try!(tokenWriter.writeRaw("{ "));

    try!(outputString_Level(&lvl, tokenWriter));

    try!(outputString_optSourceRange(&opt_sr, tokenWriter));

    try!(tokenWriter.writeStringToken(msg));

    try!(tokenWriter.writeRaw("}\n"));

    Ok(())
}

pub fn outputString_Level(lvl : &Severity, writer : &mut TokenWriter) -> Void {

    try!(writer.writeRawToken(lvl.to_string()));

    Ok(())
}

pub fn outputString_SourceRange(sr : &SourceRange, tw : &mut TokenWriter) -> Void {
    try!(tw.writeRaw("{ "));
    {
        let mut out = tw.getCharOut();
        try!(out.write_fmt(format_args!("{}:{} {}:{} ",
            sr.start_pos.line-1, sr.start_pos.col.0,
            sr.end_pos.line-1, sr.end_pos.col.0,
        )));
    }
    try!(tw.writeRaw("}"));

    Ok(())
}

pub fn outputString_optSourceRange(sr : &Option<SourceRange>, writer : &mut TokenWriter) -> Void {

    match sr {
        &None => try!(writer.writeRaw("{ }")) ,
        &Some(ref sr) => try!(outputString_SourceRange(sr, writer)) ,
    }

    try!(writer.writeRaw(" "));

    Ok(())
}

pub fn write_indent(tokenWriter : &mut TokenWriter, level : u32) -> Void {
    try!(writeNTimes(&mut *tokenWriter.getCharOut(), ' ', level * 2));
    Ok(())
}

pub fn write_structure_element(tw : &mut TokenWriter, element: &StructureElement, level: u32) -> Void
{
    try!(tw.writeRawToken(element.kind.to_String()));

    try!(tw.writeRaw("{ "));

    try!(tw.writeStringToken(&element.name));

    try!(outputString_SourceRange(&element.sourcerange, tw));

    try!(tw.getCharOut().write_str(" {}")); // name source range, Not Supported

    try!(tw.getCharOut().write_str(" "));
    try!(tw.writeStringToken(&element.type_desc));

    try!(tw.getCharOut().write_str("{}")); // attribs, Not Supported

    if element.children.is_empty() {
        try!(tw.getCharOut().write_str(" "));
    } else {
        let level = level + 1;

        for child in &element.children {
            try!(tw.getCharOut().write_str("\n"));
            try!(write_indent(tw, level));
            try!(write_structure_element(tw, child, level));
        }

        try!(tw.getCharOut().write_str("\n"));
        try!(write_indent(tw, level-1));
    }

    try!(tw.getCharOut().write_str("}"));

    Ok(())
}

#[cfg(test)]
mod parse_describe_tests {

    use parse_describe::*;
    use source_model::*;
    use token_writer::TokenWriter;
    use util::core::*;

    use std::rc::Rc;
    use std::cell::RefCell;

    #[test]
    fn tests_write_structure_element() {

        fn test_writeStructureElement(name : &str, kind : StructureElementKind, sr: SourceRange, type_desc : String,
            expected : &str,
        ) {
            let stringRc = Rc::new(RefCell::new(String::new()));
            {
                let name = String::from(name);
                let element = StructureElement { name: name, kind: kind, sourcerange: sr, type_desc: type_desc,
                     children: vec![]};
                let mut tw = TokenWriter { out : stringRc.clone() };

                write_structure_element(&mut tw, &element, 0).ok();
            }

            assert_eq!(unwrap_Rc_RefCell(stringRc).trim(), expected);
        }

        test_writeStructureElement("blah", StructureElementKind::Var, sourceRange(1, 0, 2, 5), "desc".to_string(),
            r#"Var { "blah" { 0:0 1:5 } {} "desc" {} }"#);
    }

    #[test]
    fn parse_analysis_tests() {
        test_parse_analysis("", "");

        test_parse_analysis(" #blah ", r#"{ ERROR { 0:2 0:6 } "expected `[`, found `blah`" }"#);

        test_parse_analysis("fn foo(\n  blah", r#"
{ ERROR { 1:6 1:6 } "this file contains an un-closed delimiter" }
{ INFO { 0:6 0:7 } "did you mean to close this delimiter?" }"#);

        // Test a lexer panic
        test_parse_analysis("const a = '",
            r#"{ ERROR { 0:10 0:11 } "character literal may only contain one codepoint: '" }"#);

//        test_parse_analysis("pub extern crate futures;",
//            r#""#);
    }

    fn test_parse_analysis(source : &str, expected_msgs : &str) {
        let result = parse_analysis(source, String::new()).ok().unwrap();
        let mut result : &str = &result;

        result = assert_surrounding_string("RUST_PARSE_DESCRIBE 1.0 {", result, "}");

        result = assert_starts_with("MESSAGES {", result.trim());
        expected_msgs.replace("\r\n", "\n");
        result = assert_starts_with(expected_msgs.trim(), result.trim());
        result = assert_starts_with("}", result.trim());

        assert_eq!(result, "");
    }

    fn assert_surrounding_string<'a> (start : &str, string : &'a str, end : &str) -> &'a str {
        let mut string : &str = string;

        string = assert_starts_with(start, string);
        string = assert_ends_with(string, end);

        return string;
    }

    fn assert_starts_with<'a> (start : &str, string : &'a str) -> &'a str {
        if !string.starts_with(start) {
            println!("\nThe string:\n{}\n does not start with:\n`{}`", string, start);
            assert!(false);
        }
        return &string[start.len() .. ];
    }

    fn assert_ends_with<'a> (string : &'a str, end : &str) -> &'a str {
        assert!(string.ends_with(end), "`{}` does not end with `{}`", string, end);
        return &string[0 .. string.len() - end.len()];
    }

}
<|endoftext|>