<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[macro_export]
macro_rules! executable(
    () => ({
        let module = module_path!();
        if &module[0..3] == "uu_" {
            &module[3..]
        } else {
            module
        }
    })
);

#[macro_export]
macro_rules! show_error(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: error: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! show_warning(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! show_info(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! disp_err(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
        pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", executable!());
    })
);

#[macro_export]
macro_rules! eprint(
    ($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+))
);

#[macro_export]
macro_rules! eprintln(
    ($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+))
);

#[macro_export]
macro_rules! crash(
    ($exitcode:expr, $($args:tt)+) => ({
        show_error!($($args)+);
        ::std::process::exit($exitcode)
    })
);

#[macro_export]
macro_rules! exit(
    ($exitcode:expr) => ({
        ::std::process::exit($exitcode)
    })
);

#[macro_export]
macro_rules! crash_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => crash!($exitcode, "{}", f),
        }
    )
);

#[macro_export]
macro_rules! pipe_crash_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(_) => (),
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    ()
                } else {
                    crash!($exitcode, "{}", f)
                }
            },
        }
    )
);

#[macro_export]
macro_rules! return_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => {
                show_error!("{}", f);
                return $exitcode;
            }
        }
    )
);

// XXX: should the pipe_* macros return an Err just to show the write failed?

#[macro_export]
macro_rules! pipe_print(
    ($($args:tt)+) => (
        match write!(&mut ::std::io::stdout(), $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_println(
    ($($args:tt)+) => (
        match writeln!(&mut ::std::io::stdout(), $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_write(
    ($fd:expr, $($args:tt)+) => (
        match write!($fd, $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_writeln(
    ($fd:expr, $($args:tt)+) => (
        match writeln!($fd, $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_flush(
    () => (
        match ::std::io::stdout().flush() {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    );
    ($fd:expr) => (
        match $fd.flush() {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! safe_write(
    ($fd:expr, $($args:tt)+) => (
        match write!($fd, $($args)+) {
            Ok(_) => {}
            Err(f) => panic!(f.to_string())
        }
    )
);

#[macro_export]
macro_rules! safe_writeln(
    ($fd:expr, $($args:tt)+) => (
        match writeln!($fd, $($args)+) {
            Ok(_) => {}
            Err(f) => panic!(f.to_string())
        }
    )
);

#[macro_export]
macro_rules! safe_unwrap(
    ($exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => crash!(1, "{}", f.to_string())
        }
    )
);
<commit_msg>uucore: add message templates<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[macro_export]
macro_rules! executable(
    () => ({
        let module = module_path!();
        if &module[0..3] == "uu_" {
            &module[3..]
        } else {
            module
        }
    })
);

#[macro_export]
macro_rules! show_error(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: error: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! show_warning(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! show_info(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
    })
);

#[macro_export]
macro_rules! disp_err(
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: ", executable!());
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
        pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", executable!());
    })
);

#[macro_export]
macro_rules! eprint(
    ($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+))
);

#[macro_export]
macro_rules! eprintln(
    ($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+))
);

#[macro_export]
macro_rules! crash(
    ($exitcode:expr, $($args:tt)+) => ({
        show_error!($($args)+);
        ::std::process::exit($exitcode)
    })
);

#[macro_export]
macro_rules! exit(
    ($exitcode:expr) => ({
        ::std::process::exit($exitcode)
    })
);

#[macro_export]
macro_rules! crash_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => crash!($exitcode, "{}", f),
        }
    )
);

#[macro_export]
macro_rules! pipe_crash_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(_) => (),
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    ()
                } else {
                    crash!($exitcode, "{}", f)
                }
            },
        }
    )
);

#[macro_export]
macro_rules! return_if_err(
    ($exitcode:expr, $exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => {
                show_error!("{}", f);
                return $exitcode;
            }
        }
    )
);

// XXX: should the pipe_* macros return an Err just to show the write failed?

#[macro_export]
macro_rules! pipe_print(
    ($($args:tt)+) => (
        match write!(&mut ::std::io::stdout(), $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_println(
    ($($args:tt)+) => (
        match writeln!(&mut ::std::io::stdout(), $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_write(
    ($fd:expr, $($args:tt)+) => (
        match write!($fd, $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_writeln(
    ($fd:expr, $($args:tt)+) => (
        match writeln!($fd, $($args)+) {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! pipe_flush(
    () => (
        match ::std::io::stdout().flush() {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    );
    ($fd:expr) => (
        match $fd.flush() {
            Ok(_) => true,
            Err(f) => {
                if f.kind() == ::std::io::ErrorKind::BrokenPipe {
                    false
                } else {
                    panic!("{}", f)
                }
            }
        }
    )
);

#[macro_export]
macro_rules! safe_write(
    ($fd:expr, $($args:tt)+) => (
        match write!($fd, $($args)+) {
            Ok(_) => {}
            Err(f) => panic!(f.to_string())
        }
    )
);

#[macro_export]
macro_rules! safe_writeln(
    ($fd:expr, $($args:tt)+) => (
        match writeln!($fd, $($args)+) {
            Ok(_) => {}
            Err(f) => panic!(f.to_string())
        }
    )
);

#[macro_export]
macro_rules! safe_unwrap(
    ($exp:expr) => (
        match $exp {
            Ok(m) => m,
            Err(f) => crash!(1, "{}", f.to_string())
        }
    )
);

//-- message templates

//-- message templates : general

#[macro_export]
macro_rules! snippet_list_join_oxford {
    ($conjunction:expr, $valOne:expr, $valTwo:expr) => (
        format!("{}, {} {}", $valOne, $conjunction, $valTwo)
    );
    ($conjunction:expr, $valOne:expr, $valTwo:expr $(, $remainingVals:expr)*) => (
        format!("{}, {}", $valOne, snippet_list_join_inner!($conjunction, $valTwo $(, $remainingVals)*))
    );
}

#[macro_export]
macro_rules! snippet_list_join_or {
    ($valOne:expr, $valTwo:expr) => (
        format!("{} or {}", $valOne, $valTwo)
    );
    ($valOne:expr, $valTwo:expr $(, $remainingVals:expr)*) => (
        format!("{}, {}", $valOne, snippet_list_join_oxford!("or", $valTwo $(, $remainingVals)*))
    );
}

//-- message templates : help and version

#[macro_export]
macro_rules! msg_version {
    () => (
        format!("{} {}", executable!(), env!("CARGO_PKG_VERSION"))
    )
}

//-- message templates : invalid input

#[macro_export]
macro_rules! msg_invalid_input { ($reason: expr) => (
    format!("invalid input: {}", $reason) ); }

#[macro_export]
macro_rules! snippet_no_file_at_path { ($path:expr) => (
    format!("nonexistent path {}", $path) ); }

// -- message templates : invalid input : flag

#[macro_export]
macro_rules! msg_invalid_opt_use {
    ($about:expr, $flag:expr) => (
        msg_invalid_input!(format!("The '{}' option {}", $flag, $about))
    );
    ($about:expr, $longflag:expr, $shortflag:expr) => {
        msg_invalid_input!(format!("The '{}' ('{}') option {}", $longflag, $shortflag, $about))
    };
}

#[macro_export]
macro_rules! msg_opt_only_usable_if {
    ($clause:expr, $flag:expr) => (
        msg_invalid_opt_use!(format!("only usable if {}", $clause), $flag)
    );
    ($clause:expr, $longflag:expr, $shortflag:expr) => (
        msg_invalid_opt_use!(format!("only usable if {}", $clause), $longflag, $shortflag)
    );
}

#[macro_export]
macro_rules! msg_opt_invalid_should_be {
    ($expects:expr, $received:expr, $flag:expr) => (
        msg_invalid_opt_use!(format!("expects {}, but was provided {}", $expects, $received), $flag)
    );
    ($expects:expr, $received:expr, $longflag:expr, $shortflag:expr) => (
        msg_invalid_opt_use!(format!("expects {}, but was provided {}", $expects, $received), $longflag, $shortflag)
    );
}

// -- message templates : invalid input : args

#[macro_export]
macro_rules! msg_arg_invalid_value { ($expects:expr, $received:expr) => (
    msg_invalid_input!(format!("expects its argument to be {}, but was provided {}", $expects, $received)) ); }

#[macro_export]
macro_rules! msg_args_invalid_value { ($expects:expr, $received:expr) => (
    msg_invalid_input!(format!("expects its arguments to be {}, but was provided {}", $expects, $received)) ); }

#[macro_export]
macro_rules! msg_args_nonexistent_file { ($received:expr) => (
    msg_args_invalid_value!("paths to files", snippet_no_file_at_path!($received)));}

#[macro_export]
macro_rules! msg_wrong_number_of_arguments { ($received:expr) => (
    msg_args_invalid_value!("wrong number of arguments") ); }

// -- message templates : invalid input : input combinations

#[macro_export]
macro_rules! msg_expects_one_of {
    ($valOne:expr $(, $remainingVals:expr)*) => (
        msg_invalid_input!(format!("expects one of {}", snippet_list_join_or!($valOne $(, $remainingVals)*)))
    );
}

#[macro_export]
macro_rules! msg_expects_no_more_than_one_of {
    ($valOne:expr $(, $remainingVals:expr)*) => (
        msg_invalid_input!(format!("expects no more than one of {}", snippet_list_join_or!($valOne $(, $remainingVals)*))) ;
    );
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use context::Context;
use framebuffer::FramebufferBinding;
use vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinding,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind_attrib_pointers(&mut self, binder: T::Binder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<T>(&mut self,
                                    gl_vbo: &VertexBufferBinding<T>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where T: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<T>(&mut self,
                              gl_vbo: &VertexBufferBinding<T>,
                              mode: DrawingMode)
        where T: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<T, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<T>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where T: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<T, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<T>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where T: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<T, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, T>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indicies);
        }
    }

    pub fn draw_elements_vbo<T, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, T>,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<commit_msg>Add `attrib_pointers!` macro<commit_after>use std::marker::PhantomData;
use context::Context;
use framebuffer::FramebufferBinding;
use vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinding,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind_attrib_pointers(&mut self, binder: T::Binder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<T>(&mut self,
                                    gl_vbo: &VertexBufferBinding<T>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where T: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<T>(&mut self,
                              gl_vbo: &VertexBufferBinding<T>,
                              mode: DrawingMode)
        where T: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<T, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<T>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where T: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<T, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<T>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where T: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<T, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, T>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indicies);
        }
    }

    pub fn draw_elements_vbo<T, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, T>,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        $vbo.build_attrib_binder()
            $(.$field_name($field_attrib))*
            .unwrap($gl);
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

/// Escape characters <, >, and &
pub fn escape_html(input: &str) -> String {
    let mut output = String::new();
    for c in input.chars() {
        match c {
            '<' => output.push_str("<"),
            '>' => output.push_str(">"),
            '&' => output.push_str("&"),
            _ => output.push(c),
        }
    }

    output
}

/// Escape characters for tex file
pub fn escape_tex(input: &str) -> String {
    let mut output = String::new();
    let v:Vec<char> = input.chars().collect();
    for i in 0..v.len() {
        let c = v[i];
        let next = if i < v.len() - 1 { Some(v[i+1]) } else { None };
        match c {
            '-' => {
                if next == Some('-') {
                    output.push_str(r"-{}"); // if next char is also a -, to avoid tex ligatures
                } else {
                    output.push(c);
                }
            },
            '&' => output.push_str(r"\&"),
            '%' => output.push_str(r"\%"),
            '$' => output.push_str(r"\$"),
            '#' => output.push_str(r"\#"),
            '_' => output.push_str(r"\_"),
            '{' => output.push_str(r"\{"),
            '}' => output.push_str(r"\}"),
            '~' => output.push_str(r"\textasciitilde{}" ),
            '^' => output.push_str(r"\textasciicircum{}"),
            '\\' => output.push_str(r"\textbackslash{}"),
            _  => output.push(c)
        }
    }
    output
}
<commit_msg>Clean code for escape_tex<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

/// Escape characters <, >, and &
pub fn escape_html(input: &str) -> String {
    let mut output = String::new();
    for c in input.chars() {
        match c {
            '<' => output.push_str("<"),
            '>' => output.push_str(">"),
            '&' => output.push_str("&"),
            _ => output.push(c),
        }
    }

    output
}

/// Escape characters for tex file
pub fn escape_tex(input: &str) -> String {
    let mut output = String::new();
    let mut chars:Vec<char> = input.chars().collect();
    chars.push(' '); // add a dummy char for call to .windows()
    // for &[c, next] in chars.windows(2) { // still experimental, uncomment when stable
    for win in chars.windows(2) {
        let c = win[0];
        let next = win[1];
        match c {
            '-' => {
                if next == '-' {
                    output.push_str(r"-{}"); // if next char is also a -, to avoid tex ligatures
                } else {
                    output.push(c);
                }
            },
            '&' => output.push_str(r"\&"),
            '%' => output.push_str(r"\%"),
            '$' => output.push_str(r"\$"),
            '#' => output.push_str(r"\#"),
            '_' => output.push_str(r"\_"),
            '{' => output.push_str(r"\{"),
            '}' => output.push_str(r"\}"),
            '~' => output.push_str(r"\textasciitilde{}" ),
            '^' => output.push_str(r"\textasciicircum{}"),
            '\\' => output.push_str(r"\textbackslash{}"),
            _  => output.push(c)
        }
    }
    output
}
<|endoftext|>


<commit_before>use std::collections::BinaryHeap;
use std::path::Path;

use config::Config;
use event::{Event, EventKind, Job};
use id::ID;
use platform::Platform;
use traffic::Traffic;
use workload::Workload;
use {Result, Source};

pub struct System {
    jobs: usize,

    platform: Platform,
    traffic: Traffic,
    workload: Workload,

    queue: BinaryHeap<Event>,
}

impl System {
    pub fn new<T: AsRef<Path>>(config: T, source: &Source) -> Result<System> {
        let config = try!(Config::new(config));

        let platform = {
            let config = some!(config.branch("platform"), "a platform configuration is required");
            try!(Platform::new(&config))
        };
        let traffic = {
            let config = some!(config.branch("traffic"), "a traffic configuration is required");
            try!(Traffic::new(&config, source))
        };
        let workload = {
            let config = some!(config.branch("workload"), "a workload configuration is required");
            try!(Workload::new(&config, source))
        };

        Ok(System {
            jobs: 0,

            platform: platform,
            traffic: traffic,
            workload: workload,

            queue: BinaryHeap::new(),
        })
    }
}

impl Iterator for System {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        let time = match self.traffic.next() {
            Some(time) => time,
            _ => return None,
        };
        let pattern = match self.workload.next() {
            Some(pattern) => pattern,
            _ => return None,
        };
        self.queue.push(Event {
            time: time,
            kind: EventKind::JobArrival(Job {
                id: ID::new("job"),
                pattern: pattern,
            }),
        });
        self.jobs += 1;

        self.queue.pop()
    }
}
<commit_msg>system: eliminate leftovers<commit_after>use std::collections::BinaryHeap;
use std::path::Path;

use config::Config;
use event::{Event, EventKind, Job};
use id::ID;
use platform::Platform;
use traffic::Traffic;
use workload::Workload;
use {Result, Source};

pub struct System {
    platform: Platform,
    traffic: Traffic,
    workload: Workload,
    queue: BinaryHeap<Event>,
}

impl System {
    pub fn new<T: AsRef<Path>>(config: T, source: &Source) -> Result<System> {
        let config = try!(Config::new(config));

        let platform = {
            let config = some!(config.branch("platform"), "a platform configuration is required");
            try!(Platform::new(&config))
        };
        let traffic = {
            let config = some!(config.branch("traffic"), "a traffic configuration is required");
            try!(Traffic::new(&config, source))
        };
        let workload = {
            let config = some!(config.branch("workload"), "a workload configuration is required");
            try!(Workload::new(&config, source))
        };

        Ok(System {
            platform: platform,
            traffic: traffic,
            workload: workload,
            queue: BinaryHeap::new(),
        })
    }
}

impl Iterator for System {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        let time = match self.traffic.next() {
            Some(time) => time,
            _ => return None,
        };
        let pattern = match self.workload.next() {
            Some(pattern) => pattern,
            _ => return None,
        };
        self.queue.push(Event {
            time: time,
            kind: EventKind::JobArrival(Job {
                id: ID::new("job"),
                pattern: pattern,
            }),
        });

        self.queue.pop()
    }
}
<|endoftext|>


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

//! This module implements the `Any` trait, which enables dynamic typing
//! of any type.

use cast::transmute;
use cmp::Eq;
use option::{Option, Some, None};
use to_str::ToStr;
use unstable::intrinsics;
use util::Void;

///////////////////////////////////////////////////////////////////////////////
// TypeId
///////////////////////////////////////////////////////////////////////////////

/// `TypeId` represents a globally unique identifier for a type
pub struct TypeId {
    priv t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been instantiated with
    #[inline]
    pub fn of<T: 'static>() -> TypeId {
        TypeId{ t: unsafe { intrinsics::type_id::<T>() } }
    }
}

impl Eq for TypeId {
    #[inline]
    fn eq(&self, &other: &TypeId) -> bool {
        self.t == other.t
    }
}

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// The `Any` trait is implemented by all types, and can be used as a trait object
/// for dynamic typing
pub trait Any {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId;

    /// Get a void pointer to `self`
    fn as_void_ptr(&self) -> *Void;

    /// Get a mutable void pointer to `self`
    fn as_mut_void_ptr(&mut self) -> *mut Void;
}

impl<T: 'static> Any for T {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId {
        TypeId::of::<T>()
    }

    /// Get a void pointer to `self`
    fn as_void_ptr(&self) -> *Void {
        self as *T as *Void
    }

    /// Get a mutable void pointer to `self`
    fn as_mut_void_ptr(&mut self) -> *mut Void {
        self as *mut T as *mut Void
    }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
// Implemented as three extension traits so that generics work.
///////////////////////////////////////////////////////////////////////////////

/// Extension methods for a referenced `Any` trait object
pub trait AnyRefExt<'self> {
    /// Returns true if the boxed type is the same as `T`
    fn is<T: 'static>(self) -> bool;

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_ref<T: 'static>(self) -> Option<&'self T>;
}

impl<'self> AnyRefExt<'self> for &'self Any {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'self T> {
        if self.is::<T>() {
            Some(unsafe { transmute(self.as_void_ptr()) })
        } else {
            None
        }
    }
}

/// Extension methods for a mutable referenced `Any` trait object
pub trait AnyMutRefExt<'self> {
    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_mut<T: 'static>(self) -> Option<&'self mut T>;
}

impl<'self> AnyMutRefExt<'self> for &'self mut Any {
    #[inline]
    fn as_mut<T: 'static>(self) -> Option<&'self mut T> {
        if self.is::<T>() {
            Some(unsafe { transmute(self.as_mut_void_ptr()) })
        } else {
            None
        }
    }
}

/// Extension methods for a owning `Any` trait object
pub trait AnyOwnExt {
    /// Returns the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn move<T: 'static>(self) -> Option<~T>;
}

impl AnyOwnExt for ~Any {
    #[inline]
    fn move<T: 'static>(self) -> Option<~T> {
        if self.is::<T>() {
            unsafe {
                // Extract the pointer to the boxed value, temporary alias with self
                let ptr: ~T = transmute(self.as_void_ptr());

                // Prevent destructor on self being run
                intrinsics::forget(self);

                Some(ptr)
            }
        } else {
            None
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
// Trait implementations
///////////////////////////////////////////////////////////////////////////////

impl ToStr for ~Any {
    fn to_str(&self) -> ~str { ~"~Any" }
}

impl<'self> ToStr for &'self Any {
    fn to_str(&self) -> ~str { ~"&Any" }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::AnyRefExt;
    use option::{Some, None};

    #[deriving(Eq)]
    struct Test;

    static TEST: &'static str = "Test";

    #[test]
    fn type_id() {
        let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
                         TypeId::of::<Test>());
        let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
                         TypeId::of::<Test>());

        assert!(a != b);
        assert!(a != c);
        assert!(b != c);

        assert_eq!(a, d);
        assert_eq!(b, e);
        assert_eq!(c, f);
    }

    #[test]
    fn any_as_void_ptr() {
        let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let mut x = Test;
        let mut y: &'static str = "Test";
        let (a, b, c) = (&mut 5u as &mut Any,
                         &mut y as &mut Any,
                         &mut x as &mut Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (5u, "hello", Test);
        let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
    }

    #[test]
    fn any_as_mut_void_ptr() {
        let y: &'static str = "Test";
        let mut a = ~5u as ~Any;
        let mut b = ~y as ~Any;
        let mut c = ~Test as ~Any;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let a_r: &mut Any = a;
        let b_r: &mut Any = b;
        let c_r: &mut Any = c;

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());

        let mut x = Test;
        let mut y: &'static str = "Test";
        let a = &mut 5u as &mut Any;
        let b = &mut y as &mut Any;
        let c = &mut x as &mut Any;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let a_r: &mut Any = a;
        let b_r: &mut Any = b;
        let c_r: &mut Any = c;

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());

        let y: &'static str = "Test";
        let mut a = 5u;
        let mut b = y;
        let mut c = Test;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());
    }

    #[test]
    fn any_referenced() {
        let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_owning() {
        let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_managed() {
        let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_as_ref() {
        let a = &5u as &Any;

        match a.as_ref::<uint>() {
            Some(&5) => {}
            x => fail!("Unexpected value {:?}", x)
        }

        match a.as_ref::<Test>() {
            None => {}
            x => fail!("Unexpected value {:?}", x)
        }
    }

    #[test]
    fn any_as_mut() {
        let mut a = 5u;
        let mut b = ~7u;

        let a_r = &mut a as &mut Any;
        let tmp: &mut uint = b;
        let b_r = tmp as &mut Any;

        match a_r.as_mut::<uint>() {
            Some(x) => {
                assert_eq!(*x, 5u);
                *x = 612;
            }
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<uint>() {
            Some(x) => {
                assert_eq!(*x, 7u);
                *x = 413;
            }
            x => fail!("Unexpected value {:?}", x)
        }

        match a_r.as_mut::<Test>() {
            None => (),
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<Test>() {
            None => (),
            x => fail!("Unexpected value {:?}", x)
        }

        match a_r.as_mut::<uint>() {
            Some(&612) => {}
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<uint>() {
            Some(&413) => {}
            x => fail!("Unexpected value {:?}", x)
        }
    }

    #[test]
    fn any_move() {
        let a = ~8u as ~Any;
        let b = ~Test as ~Any;

        assert_eq!(a.move(), Some(~8u));
        assert_eq!(b.move(), Some(~Test));

        let a = ~8u as ~Any;
        let b = ~Test as ~Any;

        assert_eq!(a.move(), None::<~Test>);
        assert_eq!(b.move(), None::<~uint>);
    }
}
<commit_msg>Implement IterBytes for TypeId<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements the `Any` trait, which enables dynamic typing
//! of any type.

use cast::transmute;
use cmp::Eq;
use option::{Option, Some, None};
use to_bytes::{IterBytes, Cb};
use to_str::ToStr;
use unstable::intrinsics;
use util::Void;

///////////////////////////////////////////////////////////////////////////////
// TypeId
///////////////////////////////////////////////////////////////////////////////

/// `TypeId` represents a globally unique identifier for a type
pub struct TypeId {
    priv t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been instantiated with
    #[inline]
    pub fn of<T: 'static>() -> TypeId {
        TypeId{ t: unsafe { intrinsics::type_id::<T>() } }
    }
}

impl Eq for TypeId {
    #[inline]
    fn eq(&self, &other: &TypeId) -> bool {
        self.t == other.t
    }
}

impl IterBytes for TypeId {
    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
        self.t.iter_bytes(lsb0, f)
    }
}

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// The `Any` trait is implemented by all types, and can be used as a trait object
/// for dynamic typing
pub trait Any {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId;

    /// Get a void pointer to `self`
    fn as_void_ptr(&self) -> *Void;

    /// Get a mutable void pointer to `self`
    fn as_mut_void_ptr(&mut self) -> *mut Void;
}

impl<T: 'static> Any for T {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId {
        TypeId::of::<T>()
    }

    /// Get a void pointer to `self`
    fn as_void_ptr(&self) -> *Void {
        self as *T as *Void
    }

    /// Get a mutable void pointer to `self`
    fn as_mut_void_ptr(&mut self) -> *mut Void {
        self as *mut T as *mut Void
    }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
// Implemented as three extension traits so that generics work.
///////////////////////////////////////////////////////////////////////////////

/// Extension methods for a referenced `Any` trait object
pub trait AnyRefExt<'self> {
    /// Returns true if the boxed type is the same as `T`
    fn is<T: 'static>(self) -> bool;

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_ref<T: 'static>(self) -> Option<&'self T>;
}

impl<'self> AnyRefExt<'self> for &'self Any {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'self T> {
        if self.is::<T>() {
            Some(unsafe { transmute(self.as_void_ptr()) })
        } else {
            None
        }
    }
}

/// Extension methods for a mutable referenced `Any` trait object
pub trait AnyMutRefExt<'self> {
    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_mut<T: 'static>(self) -> Option<&'self mut T>;
}

impl<'self> AnyMutRefExt<'self> for &'self mut Any {
    #[inline]
    fn as_mut<T: 'static>(self) -> Option<&'self mut T> {
        if self.is::<T>() {
            Some(unsafe { transmute(self.as_mut_void_ptr()) })
        } else {
            None
        }
    }
}

/// Extension methods for a owning `Any` trait object
pub trait AnyOwnExt {
    /// Returns the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn move<T: 'static>(self) -> Option<~T>;
}

impl AnyOwnExt for ~Any {
    #[inline]
    fn move<T: 'static>(self) -> Option<~T> {
        if self.is::<T>() {
            unsafe {
                // Extract the pointer to the boxed value, temporary alias with self
                let ptr: ~T = transmute(self.as_void_ptr());

                // Prevent destructor on self being run
                intrinsics::forget(self);

                Some(ptr)
            }
        } else {
            None
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
// Trait implementations
///////////////////////////////////////////////////////////////////////////////

impl ToStr for ~Any {
    fn to_str(&self) -> ~str { ~"~Any" }
}

impl<'self> ToStr for &'self Any {
    fn to_str(&self) -> ~str { ~"&Any" }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::AnyRefExt;
    use option::{Some, None};
    use hash::Hash;

    #[deriving(Eq)]
    struct Test;

    static TEST: &'static str = "Test";

    #[test]
    fn type_id() {
        let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
                         TypeId::of::<Test>());
        let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
                         TypeId::of::<Test>());

        assert!(a != b);
        assert!(a != c);
        assert!(b != c);

        assert_eq!(a, d);
        assert_eq!(b, e);
        assert_eq!(c, f);
    }

    #[test]
    fn type_id_hash() {
        let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>::());

        assert_eq!(a.hash(), b.hash());
    }

    #[test]
    fn any_as_void_ptr() {
        let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let mut x = Test;
        let mut y: &'static str = "Test";
        let (a, b, c) = (&mut 5u as &mut Any,
                         &mut y as &mut Any,
                         &mut x as &mut Any);
        let a_r: &Any = a;
        let b_r: &Any = b;
        let c_r: &Any = c;

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());

        let (a, b, c) = (5u, "hello", Test);
        let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);

        assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
        assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
        assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
    }

    #[test]
    fn any_as_mut_void_ptr() {
        let y: &'static str = "Test";
        let mut a = ~5u as ~Any;
        let mut b = ~y as ~Any;
        let mut c = ~Test as ~Any;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let a_r: &mut Any = a;
        let b_r: &mut Any = b;
        let c_r: &mut Any = c;

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());

        let mut x = Test;
        let mut y: &'static str = "Test";
        let a = &mut 5u as &mut Any;
        let b = &mut y as &mut Any;
        let c = &mut x as &mut Any;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let a_r: &mut Any = a;
        let b_r: &mut Any = b;
        let c_r: &mut Any = c;

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());

        let y: &'static str = "Test";
        let mut a = 5u;
        let mut b = y;
        let mut c = Test;

        let a_ptr = a.as_mut_void_ptr();
        let b_ptr = b.as_mut_void_ptr();
        let c_ptr = c.as_mut_void_ptr();

        let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);

        assert_eq!(a_ptr, a_r.as_mut_void_ptr());
        assert_eq!(b_ptr, b_r.as_mut_void_ptr());
        assert_eq!(c_ptr, c_r.as_mut_void_ptr());
    }

    #[test]
    fn any_referenced() {
        let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_owning() {
        let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_managed() {
        let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);

        assert!(a.is::<uint>());
        assert!(!b.is::<uint>());
        assert!(!c.is::<uint>());

        assert!(!a.is::<&'static str>());
        assert!(b.is::<&'static str>());
        assert!(!c.is::<&'static str>());

        assert!(!a.is::<Test>());
        assert!(!b.is::<Test>());
        assert!(c.is::<Test>());
    }

    #[test]
    fn any_as_ref() {
        let a = &5u as &Any;

        match a.as_ref::<uint>() {
            Some(&5) => {}
            x => fail!("Unexpected value {:?}", x)
        }

        match a.as_ref::<Test>() {
            None => {}
            x => fail!("Unexpected value {:?}", x)
        }
    }

    #[test]
    fn any_as_mut() {
        let mut a = 5u;
        let mut b = ~7u;

        let a_r = &mut a as &mut Any;
        let tmp: &mut uint = b;
        let b_r = tmp as &mut Any;

        match a_r.as_mut::<uint>() {
            Some(x) => {
                assert_eq!(*x, 5u);
                *x = 612;
            }
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<uint>() {
            Some(x) => {
                assert_eq!(*x, 7u);
                *x = 413;
            }
            x => fail!("Unexpected value {:?}", x)
        }

        match a_r.as_mut::<Test>() {
            None => (),
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<Test>() {
            None => (),
            x => fail!("Unexpected value {:?}", x)
        }

        match a_r.as_mut::<uint>() {
            Some(&612) => {}
            x => fail!("Unexpected value {:?}", x)
        }

        match b_r.as_mut::<uint>() {
            Some(&413) => {}
            x => fail!("Unexpected value {:?}", x)
        }
    }

    #[test]
    fn any_move() {
        let a = ~8u as ~Any;
        let b = ~Test as ~Any;

        assert_eq!(a.move(), Some(~8u));
        assert_eq!(b.move(), Some(~Test));

        let a = ~8u as ~Any;
        let b = ~Test as ~Any;

        assert_eq!(a.move(), None::<~Test>);
        assert_eq!(b.move(), None::<~uint>);
    }
}
<|endoftext|>


<commit_before>use super::write_file;
use crate::error::{Error, Result};
use std::path::Path;
use std::{fs, str};

const BINDING_CC_TEMPLATE: &'static str = include_str!("./templates/binding.cc");
const BINDING_GYP_TEMPLATE: &'static str = include_str!("./templates/binding.gyp");
const INDEX_JS_TEMPLATE: &'static str = include_str!("./templates/index.js");
const LIB_RS_TEMPLATE: &'static str = include_str!("./templates/lib.rs");
const BUILD_RS_TEMPLATE: &'static str = include_str!("./templates/build.rs");
const CARGO_TOML_TEMPLATE: &'static str = include_str!("./templates/cargo.toml");
const PACKAGE_JSON_TEMPLATE: &'static str = include_str!("./templates/package.json");
const PARSER_NAME_PLACEHOLDER: &'static str = "PARSER_NAME";
const CLI_VERSION_PLACEHOLDER: &'static str = "CLI_VERSION";
const CLI_VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<()> {
    let bindings_dir = repo_path.join("bindings");

    // Generate rust bindings if needed.
    let rust_binding_dir = bindings_dir.join("rust");
    if !rust_binding_dir.exists() {
        create_dir(&rust_binding_dir)?;
        generate_file(
            &rust_binding_dir.join("lib.rs"),
            LIB_RS_TEMPLATE,
            language_name,
        )?;
        generate_file(
            &rust_binding_dir.join("build.rs"),
            BUILD_RS_TEMPLATE,
            language_name,
        )?;
        let cargo_toml_path = repo_path.join("Cargo.toml");
        if !cargo_toml_path.exists() {
            generate_file(&cargo_toml_path, CARGO_TOML_TEMPLATE, language_name)?;
        }
    }

    // Generate node bindings
    let node_binding_dir = bindings_dir.join("node");
    if !node_binding_dir.exists() {
        create_dir(&node_binding_dir)?;
        generate_file(
            &node_binding_dir.join("index.js"),
            INDEX_JS_TEMPLATE,
            language_name,
        )?;
        generate_file(
            &node_binding_dir.join("binding.cc"),
            BINDING_CC_TEMPLATE,
            language_name,
        )?;

        // Create binding.gyp, or update it with new binding path.
        let binding_gyp_path = repo_path.join("binding.gyp");
        if binding_gyp_path.exists() {
            eprintln!("Updating binding.gyp with new binding path");

            let binding_gyp = fs::read_to_string(&binding_gyp_path)
                .map_err(Error::wrap(|| "Failed to read binding.gyp"))?;
            let binding_gyp = binding_gyp.replace("src/binding.cc", "bindings/node/binding.cc");
            write_file(&binding_gyp_path, binding_gyp)?;
        } else {
            generate_file(&binding_gyp_path, BINDING_GYP_TEMPLATE, language_name)?;
        }

        // Create package.json, or update it with new binding path.
        let package_json_path = repo_path.join("package.json");
        if package_json_path.exists() {
            let package_json_str = fs::read_to_string(&package_json_path)
                .map_err(Error::wrap(|| "Failed to read package.json"))?;
            let mut package_json =
                serde_json::from_str::<serde_json::Map<String, serde_json::Value>>(
                    &package_json_str,
                )
                .map_err(Error::wrap(|| "Failed to parse package.json"))?;
            let package_json_main = package_json.get("main");
            let package_json_needs_update = package_json_main.map_or(true, |v| {
                let main_string = v.as_str();
                main_string == Some("index.js") || main_string == Some("./index.js")
            });
            if package_json_needs_update {
                eprintln!("Updating package.json with new binding path");

                package_json.insert(
                    "main".to_string(),
                    serde_json::Value::String("bindings/node".to_string()),
                );
                let mut package_json_str = serde_json::to_string_pretty(&package_json)?;
                package_json_str.push('\n');
                write_file(&package_json_path, package_json_str)?;
            }
        } else {
            generate_file(&package_json_path, PACKAGE_JSON_TEMPLATE, language_name)?;
        }

        // Remove files from old node binding paths.
        let old_index_js_path = repo_path.join("index.js");
        let old_binding_cc_path = repo_path.join("src").join("binding.cc");
        if old_index_js_path.exists() {
            fs::remove_file(old_index_js_path).ok();
        }
        if old_binding_cc_path.exists() {
            fs::remove_file(old_binding_cc_path).ok();
        }
    }

    Ok(())
}

fn generate_file(path: &Path, template: &str, language_name: &str) -> Result<()> {
    write_file(
        path,
        template
            .replace(PARSER_NAME_PLACEHOLDER, language_name)
            .replace(CLI_VERSION_PLACEHOLDER, CLI_VERSION),
    )
}

fn create_dir(path: &Path) -> Result<()> {
    fs::create_dir_all(&path).map_err(Error::wrap(|| {
        format!("Failed to create {:?}", path.to_string_lossy())
    }))
}
<commit_msg>fix(cli): use dashed language name in generated package.json and Cargo.toml files<commit_after>use super::write_file;
use crate::error::{Error, Result};
use std::path::Path;
use std::{fs, str};

const BINDING_CC_TEMPLATE: &'static str = include_str!("./templates/binding.cc");
const BINDING_GYP_TEMPLATE: &'static str = include_str!("./templates/binding.gyp");
const INDEX_JS_TEMPLATE: &'static str = include_str!("./templates/index.js");
const LIB_RS_TEMPLATE: &'static str = include_str!("./templates/lib.rs");
const BUILD_RS_TEMPLATE: &'static str = include_str!("./templates/build.rs");
const CARGO_TOML_TEMPLATE: &'static str = include_str!("./templates/cargo.toml");
const PACKAGE_JSON_TEMPLATE: &'static str = include_str!("./templates/package.json");
const PARSER_NAME_PLACEHOLDER: &'static str = "PARSER_NAME";
const CLI_VERSION_PLACEHOLDER: &'static str = "CLI_VERSION";
const CLI_VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<()> {
    let bindings_dir = repo_path.join("bindings");

    let dashed_language_name = language_name.replace("_", "-");
    let dashed_language_name = dashed_language_name.as_str();

    // Generate rust bindings if needed.
    let rust_binding_dir = bindings_dir.join("rust");
    if !rust_binding_dir.exists() {
        create_dir(&rust_binding_dir)?;
        generate_file(
            &rust_binding_dir.join("lib.rs"),
            LIB_RS_TEMPLATE,
            language_name,
        )?;
        generate_file(
            &rust_binding_dir.join("build.rs"),
            BUILD_RS_TEMPLATE,
            language_name,
        )?;
        let cargo_toml_path = repo_path.join("Cargo.toml");
        if !cargo_toml_path.exists() {
            generate_file(&cargo_toml_path, CARGO_TOML_TEMPLATE, dashed_language_name)?;
        }
    }

    // Generate node bindings
    let node_binding_dir = bindings_dir.join("node");
    if !node_binding_dir.exists() {
        create_dir(&node_binding_dir)?;
        generate_file(
            &node_binding_dir.join("index.js"),
            INDEX_JS_TEMPLATE,
            language_name,
        )?;
        generate_file(
            &node_binding_dir.join("binding.cc"),
            BINDING_CC_TEMPLATE,
            language_name,
        )?;

        // Create binding.gyp, or update it with new binding path.
        let binding_gyp_path = repo_path.join("binding.gyp");
        if binding_gyp_path.exists() {
            eprintln!("Updating binding.gyp with new binding path");

            let binding_gyp = fs::read_to_string(&binding_gyp_path)
                .map_err(Error::wrap(|| "Failed to read binding.gyp"))?;
            let binding_gyp = binding_gyp.replace("src/binding.cc", "bindings/node/binding.cc");
            write_file(&binding_gyp_path, binding_gyp)?;
        } else {
            generate_file(&binding_gyp_path, BINDING_GYP_TEMPLATE, language_name)?;
        }

        // Create package.json, or update it with new binding path.
        let package_json_path = repo_path.join("package.json");
        if package_json_path.exists() {
            let package_json_str = fs::read_to_string(&package_json_path)
                .map_err(Error::wrap(|| "Failed to read package.json"))?;
            let mut package_json =
                serde_json::from_str::<serde_json::Map<String, serde_json::Value>>(
                    &package_json_str,
                )
                .map_err(Error::wrap(|| "Failed to parse package.json"))?;
            let package_json_main = package_json.get("main");
            let package_json_needs_update = package_json_main.map_or(true, |v| {
                let main_string = v.as_str();
                main_string == Some("index.js") || main_string == Some("./index.js")
            });
            if package_json_needs_update {
                eprintln!("Updating package.json with new binding path");

                package_json.insert(
                    "main".to_string(),
                    serde_json::Value::String("bindings/node".to_string()),
                );
                let mut package_json_str = serde_json::to_string_pretty(&package_json)?;
                package_json_str.push('\n');
                write_file(&package_json_path, package_json_str)?;
            }
        } else {
            generate_file(&package_json_path, PACKAGE_JSON_TEMPLATE, dashed_language_name)?;
        }

        // Remove files from old node binding paths.
        let old_index_js_path = repo_path.join("index.js");
        let old_binding_cc_path = repo_path.join("src").join("binding.cc");
        if old_index_js_path.exists() {
            fs::remove_file(old_index_js_path).ok();
        }
        if old_binding_cc_path.exists() {
            fs::remove_file(old_binding_cc_path).ok();
        }
    }

    Ok(())
}

fn generate_file(path: &Path, template: &str, language_name: &str) -> Result<()> {
    write_file(
        path,
        template
            .replace(PARSER_NAME_PLACEHOLDER, language_name)
            .replace(CLI_VERSION_PLACEHOLDER, CLI_VERSION),
    )
}

fn create_dir(path: &Path) -> Result<()> {
    fs::create_dir_all(&path).map_err(Error::wrap(|| {
        format!("Failed to create {:?}", path.to_string_lossy())
    }))
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::Write as _;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::path::MAIN_SEPARATOR;
use std::process::Command;
use std::process::Stdio;
use std::str;

use protobuf::descriptor::field_descriptor_proto;
use protobuf::descriptor::DescriptorProto;
use protobuf::descriptor::EnumDescriptorProto;
use protobuf::descriptor::FieldDescriptorProto;
use protobuf::descriptor::FileDescriptorProto;
use protobuf::descriptor::FileDescriptorSet;
use protobuf::descriptor::MethodDescriptorProto;
use protobuf::descriptor::OneofDescriptorProto;
use protobuf::descriptor::ServiceDescriptorProto;
use protobuf::text_format::lexer::float::parse_protobuf_float;
use protobuf_codegen::Codegen;
use protobuf_parse::Parser;
use protobuf_test_common::build::copy_tests_v2_v3;
use protobuf_test_common::build::glob_simple;
use regex::Regex;

fn to_paths(iter: impl IntoIterator<Item = impl Into<String>>) -> Vec<PathBuf> {
    iter.into_iter()
        .map(|item| item.into().replace(MAIN_SEPARATOR, "/").into())
        .collect()
}

#[derive(Default, Debug)]
struct TestStats {
    passed: u32,
    passed_marked_skip: u32,
    skipped: u32,
    failed: u32,
}

fn normalize_generated_file(contents: &str) -> String {
    let parsed_by = Regex::new("^// \\.proto file is parsed by.*").unwrap();

    let mut r = String::new();
    let mut inside_descriptor_data = false;
    for line in contents.lines() {
        let line = if inside_descriptor_data {
            if line == "\";" {
                inside_descriptor_data = false;
                line.to_owned()
            } else {
                continue;
            }
        } else if line.starts_with("static file_descriptor_proto_data") {
            inside_descriptor_data = true;
            line.to_owned()
        } else {
            parsed_by.replace(line, "").into_owned()
        };

        writeln!(&mut r, "{}", line).unwrap();
    }

    // sanity check
    assert!(!inside_descriptor_data);

    r
}

fn normalize_generated_file_in_place(path: &Path) {
    let contents = fs::read_to_string(path).unwrap();
    let contents = normalize_generated_file(&contents);
    fs::write(path, &contents).unwrap();
}

fn print_diff(dir: &Path, a: &Path, b: &Path) {
    if cfg!(windows) {
        // likely we don't have `diff` command on Windows
        return;
    }

    // sanity check
    let mut a_full = dir.to_path_buf();
    a_full.push(a);
    assert!(a_full.exists());
    let mut b_full = dir.to_path_buf();
    b_full.push(b);
    assert!(b_full.exists());

    // Not using difference crate because it's slow for large files
    let output = Command::new("diff")
        .current_dir(dir)
        .arg("-u")
        .arg(a)
        .arg(b)
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .unwrap();

    print!("{}", str::from_utf8(&output.stdout).unwrap());
    print!("{}", str::from_utf8(&output.stderr).unwrap());
}

fn normalize_descriptor_set(fds: &mut FileDescriptorSet) {
    for desc in &mut fds.file {
        normalize_file_descriptor(desc)
    }
}

fn normalize_file_descriptor(desc: &mut FileDescriptorProto) {
    if !desc.has_syntax() {
        desc.set_syntax("proto2".into())
    }
    for desc in &mut *desc.message_type {
        normalize_descriptor(desc)
    }
    for desc in &mut desc.enum_type {
        normalize_enum_descriptor(desc)
    }

    for desc in &mut desc.extension {
        desc.options.mut_or_default();
    }
    desc.options.mut_or_default();

    for service in &mut desc.service {
        normalize_service(service);
    }

    // for unittest_custom_options.proto where a custom option
    // is an extension. Probably nobody outside of Google uses it.
    desc.options
        .mut_or_default()
        .unknown_fields
        .remove(15478479);
}

fn normalize_enum_descriptor(desc: &mut EnumDescriptorProto) {
    desc.options.mut_or_default();

    for value in &mut desc.value {
        value.options.mut_or_default();
    }
}

fn normalize_oneof_descriptor(desc: &mut OneofDescriptorProto) {
    desc.options.mut_or_default();
}

fn normalize_descriptor(desc: &mut DescriptorProto) {
    for desc in &mut desc.nested_type {
        normalize_descriptor(desc);
    }
    for desc in &mut desc.enum_type {
        normalize_enum_descriptor(desc);
    }
    for desc in &mut desc.oneof_decl {
        normalize_oneof_descriptor(desc);
    }

    desc.options.mut_or_default();

    // group are not supported
    desc.options.mut_or_default().unknown_fields.remove(7636463);

    for field in &mut desc.field {
        normalize_field(field);
    }

    for ext in &mut desc.extension {
        ext.options.mut_or_default();
    }

    for ext in &mut desc.extension_range {
        // If ext range end exceeds max field number,
        // the actual upper limit does not matter.
        // protoc is not consistent in behavior thus flush
        // the value to some arbitrary compatible value.
        if ext.has_end() && ext.get_end() >= 0x20000000 {
            ext.set_end(0x20000000);
        }
    }
}

fn normalize_method(method: &mut MethodDescriptorProto) {
    method.options.mut_or_default();
}

fn normalize_service(service: &mut ServiceDescriptorProto) {
    for m in &mut service.method {
        normalize_method(m);
    }

    service.options.mut_or_default();
}

fn normalize_field(field: &mut FieldDescriptorProto) {
    field.options.mut_or_default();

    if field.has_default_value() {
        if field.get_field_type() == field_descriptor_proto::Type::TYPE_FLOAT {
            field.set_default_value(format!(
                "{}",
                parse_protobuf_float(field.get_default_value()).unwrap()
            ));
        }
    }
}

fn pretty_message<M: protobuf::Message>(message: &M) -> String {
    // TODO: pull this handy utility into the protobuf crate.
    struct FormatMessage<'a, M>(&'a M);

    impl<M: protobuf::Message> fmt::Display for FormatMessage<'_, M> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            protobuf::text_format::fmt(self.0, f)
        }
    }

    format!("{:#}", FormatMessage(message))
}

fn descriptor_for_file<'a>(fds: &'a FileDescriptorSet, file_name: &str) -> &'a FileDescriptorProto {
    for file in &fds.file {
        if Path::new(file.get_name()).file_name().unwrap()
            == Path::new(file_name).file_name().unwrap()
        {
            return file;
        }
    }
    panic!(
        "file not found: {}; all files: {}",
        file_name,
        fds.file
            .iter()
            .map(|f| f.get_name())
            .collect::<Vec<_>>()
            .join(", ")
    );
}

fn test_diff_in<F>(root: &str, sources_dir: &str, include: &str, should_skip: F)
where
    F: Fn(&str) -> bool,
{
    let mut stats = TestStats {
        passed: 0,
        passed_marked_skip: 0,
        skipped: 0,
        failed: 0,
    };

    let mut include_root = Path::new(root).to_path_buf();
    include_root.push(include);

    let include_full = format!("{}/{}", root, include);
    let s_full = format!("{}/{}", root, sources_dir);

    let inputs_glob = format!("{}/*.proto*", s_full);
    let inputs = to_paths(glob_simple(&inputs_glob));
    assert!(!inputs.is_empty(), "glob is empty: {}", inputs_glob);
    let includes = to_paths(vec![include_full.as_str(), "../proto"]);

    let temp_dir = tempfile::Builder::new()
        .prefix("protobuf-codegen-identical-test")
        .tempdir()
        .unwrap();

    let protoc_dir = format!("{}/protoc", temp_dir.path().to_str().unwrap());
    let pure_dir = format!("{}/pure", temp_dir.path().to_str().unwrap());

    fs::create_dir(&protoc_dir).unwrap();
    fs::create_dir(&pure_dir).unwrap();

    Codegen::new()
        .protoc()
        .protoc_path(&protoc_bin_vendored::protoc_bin_path().unwrap())
        .inputs(&inputs)
        .includes(&includes)
        .out_dir(&protoc_dir)
        .run()
        .unwrap();

    Codegen::new()
        .pure()
        .inputs(&inputs)
        .includes(&includes)
        .out_dir(&pure_dir)
        .run()
        .unwrap();

    let mut protoc_descriptors = Parser::new()
        .protoc()
        .includes(&includes)
        .inputs(&inputs)
        .file_descriptor_set()
        .unwrap();
    let mut pure_descriptors = Parser::new()
        .pure()
        .includes(&includes)
        .inputs(&inputs)
        .file_descriptor_set()
        .unwrap();
    normalize_descriptor_set(&mut protoc_descriptors);
    normalize_descriptor_set(&mut pure_descriptors);

    for input in &inputs {
        let label = input.strip_prefix(root).unwrap().to_str().unwrap();
        let proto_file_name = input.strip_prefix(&include_root).unwrap().to_str().unwrap();
        let proto_name = input.file_name().unwrap().to_str().unwrap();
        let rs_name = protobuf_codegen::proto_name_to_rs(proto_name);
        let protoc_rs = format!("{}/{}", protoc_dir, rs_name);
        let pure_rs = format!("{}/{}", pure_dir, rs_name);

        normalize_generated_file_in_place(Path::new(&protoc_rs));
        normalize_generated_file_in_place(Path::new(&pure_rs));

        let protoc_rs_contents =
            fs::read_to_string(&protoc_rs).expect(&format!("while reading {}", protoc_rs));
        let pure_rs_contents =
            fs::read_to_string(&pure_rs).expect(&format!("while reading {}", pure_rs));

        let protoc_descriptor_for_file = descriptor_for_file(&protoc_descriptors, &proto_file_name);
        let pure_descriptor_for_file = descriptor_for_file(&pure_descriptors, &proto_file_name);

        let skip = should_skip(input.to_str().unwrap());
        if protoc_rs_contents == pure_rs_contents
            && protoc_descriptor_for_file == pure_descriptor_for_file
        {
            if !skip {
                stats.passed += 1;
                println!("{}: PASSED", label);
            } else {
                stats.passed_marked_skip += 1;
                println!("{}: PASSED BUT MARKED SKIP", label);
            }
        } else {
            if skip {
                stats.skipped += 1;
                println!("{} SKIPPED", label);
            } else {
                stats.failed += 1;
                println!("{} FAILED", label);
            }

            print_diff(
                temp_dir.path(),
                Path::new(&protoc_rs).strip_prefix(temp_dir.path()).unwrap(),
                Path::new(&pure_rs).strip_prefix(temp_dir.path()).unwrap(),
            );

            fs::write(
                format!("{}/{}.descriptors", protoc_dir, proto_name),
                pretty_message(protoc_descriptor_for_file),
            )
            .unwrap();
            fs::write(
                format!("{}/{}.descriptors", pure_dir, proto_name),
                pretty_message(pure_descriptor_for_file),
            )
            .unwrap();
            print_diff(
                temp_dir.path(),
                Path::new(&format!("protoc/{}.descriptors", proto_name)),
                Path::new(&format!("pure/{}.descriptors", proto_name)),
            );
        }
    }

    println!("{:?}", stats);
    assert!(stats.failed == 0, "at least one test failed");
}

fn should_skip_with_marker(path: &str) -> bool {
    fs::read_to_string(path)
        .unwrap()
        .contains("@skip-codegen-identical-test")
}

#[test]
fn common_v2() {
    test_diff_in(
        "../protobuf-test",
        "src/common/v2",
        "src/common/v2",
        should_skip_with_marker,
    );
}

#[test]
fn common_v3() {
    let common_v3_root = tempfile::Builder::new()
        .prefix("common-v3")
        .tempdir()
        .unwrap();
    fs::create_dir_all(format!(
        "{}/src/common/v3",
        common_v3_root.path().to_str().unwrap()
    ))
    .unwrap();

    copy_tests_v2_v3(
        "../protobuf-test/src/common/v2",
        &format!("{}/src/common/v3", common_v3_root.path().to_str().unwrap()),
    );

    test_diff_in(
        common_v3_root.path().to_str().unwrap(),
        "src/common/v3",
        "src/common/v3",
        should_skip_with_marker,
    );
}

#[test]
fn v2() {
    test_diff_in(
        "../protobuf-test",
        "src/v2",
        "src/v2",
        should_skip_with_marker,
    );
}

#[test]
fn v3() {
    test_diff_in(
        "../protobuf-test",
        "src/v3",
        "src/v3",
        should_skip_with_marker,
    );
}

#[test]
fn interop() {
    test_diff_in(
        "../protobuf-test",
        "../interop/cxx",
        "../interop/cxx",
        should_skip_with_marker,
    );
}

#[test]
fn google() {
    test_diff_in("../protobuf-test", "src/google/protobuf", "src", |_| false);
}
<commit_msg>Code cleanup: Display for Message is text_format<commit_after>use std::fmt::Write as _;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::path::MAIN_SEPARATOR;
use std::process::Command;
use std::process::Stdio;
use std::str;

use protobuf::descriptor::field_descriptor_proto;
use protobuf::descriptor::DescriptorProto;
use protobuf::descriptor::EnumDescriptorProto;
use protobuf::descriptor::FieldDescriptorProto;
use protobuf::descriptor::FileDescriptorProto;
use protobuf::descriptor::FileDescriptorSet;
use protobuf::descriptor::MethodDescriptorProto;
use protobuf::descriptor::OneofDescriptorProto;
use protobuf::descriptor::ServiceDescriptorProto;
use protobuf::text_format::lexer::float::parse_protobuf_float;
use protobuf_codegen::Codegen;
use protobuf_parse::Parser;
use protobuf_test_common::build::copy_tests_v2_v3;
use protobuf_test_common::build::glob_simple;
use regex::Regex;

fn to_paths(iter: impl IntoIterator<Item = impl Into<String>>) -> Vec<PathBuf> {
    iter.into_iter()
        .map(|item| item.into().replace(MAIN_SEPARATOR, "/").into())
        .collect()
}

#[derive(Default, Debug)]
struct TestStats {
    passed: u32,
    passed_marked_skip: u32,
    skipped: u32,
    failed: u32,
}

fn normalize_generated_file(contents: &str) -> String {
    let parsed_by = Regex::new("^// \\.proto file is parsed by.*").unwrap();

    let mut r = String::new();
    let mut inside_descriptor_data = false;
    for line in contents.lines() {
        let line = if inside_descriptor_data {
            if line == "\";" {
                inside_descriptor_data = false;
                line.to_owned()
            } else {
                continue;
            }
        } else if line.starts_with("static file_descriptor_proto_data") {
            inside_descriptor_data = true;
            line.to_owned()
        } else {
            parsed_by.replace(line, "").into_owned()
        };

        writeln!(&mut r, "{}", line).unwrap();
    }

    // sanity check
    assert!(!inside_descriptor_data);

    r
}

fn normalize_generated_file_in_place(path: &Path) {
    let contents = fs::read_to_string(path).unwrap();
    let contents = normalize_generated_file(&contents);
    fs::write(path, &contents).unwrap();
}

fn print_diff(dir: &Path, a: &Path, b: &Path) {
    if cfg!(windows) {
        // likely we don't have `diff` command on Windows
        return;
    }

    // sanity check
    let mut a_full = dir.to_path_buf();
    a_full.push(a);
    assert!(a_full.exists());
    let mut b_full = dir.to_path_buf();
    b_full.push(b);
    assert!(b_full.exists());

    // Not using difference crate because it's slow for large files
    let output = Command::new("diff")
        .current_dir(dir)
        .arg("-u")
        .arg(a)
        .arg(b)
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .unwrap();

    print!("{}", str::from_utf8(&output.stdout).unwrap());
    print!("{}", str::from_utf8(&output.stderr).unwrap());
}

fn normalize_descriptor_set(fds: &mut FileDescriptorSet) {
    for desc in &mut fds.file {
        normalize_file_descriptor(desc)
    }
}

fn normalize_file_descriptor(desc: &mut FileDescriptorProto) {
    if !desc.has_syntax() {
        desc.set_syntax("proto2".into())
    }
    for desc in &mut *desc.message_type {
        normalize_descriptor(desc)
    }
    for desc in &mut desc.enum_type {
        normalize_enum_descriptor(desc)
    }

    for desc in &mut desc.extension {
        desc.options.mut_or_default();
    }
    desc.options.mut_or_default();

    for service in &mut desc.service {
        normalize_service(service);
    }

    // for unittest_custom_options.proto where a custom option
    // is an extension. Probably nobody outside of Google uses it.
    desc.options
        .mut_or_default()
        .unknown_fields
        .remove(15478479);
}

fn normalize_enum_descriptor(desc: &mut EnumDescriptorProto) {
    desc.options.mut_or_default();

    for value in &mut desc.value {
        value.options.mut_or_default();
    }
}

fn normalize_oneof_descriptor(desc: &mut OneofDescriptorProto) {
    desc.options.mut_or_default();
}

fn normalize_descriptor(desc: &mut DescriptorProto) {
    for desc in &mut desc.nested_type {
        normalize_descriptor(desc);
    }
    for desc in &mut desc.enum_type {
        normalize_enum_descriptor(desc);
    }
    for desc in &mut desc.oneof_decl {
        normalize_oneof_descriptor(desc);
    }

    desc.options.mut_or_default();

    // group are not supported
    desc.options.mut_or_default().unknown_fields.remove(7636463);

    for field in &mut desc.field {
        normalize_field(field);
    }

    for ext in &mut desc.extension {
        ext.options.mut_or_default();
    }

    for ext in &mut desc.extension_range {
        // If ext range end exceeds max field number,
        // the actual upper limit does not matter.
        // protoc is not consistent in behavior thus flush
        // the value to some arbitrary compatible value.
        if ext.has_end() && ext.get_end() >= 0x20000000 {
            ext.set_end(0x20000000);
        }
    }
}

fn normalize_method(method: &mut MethodDescriptorProto) {
    method.options.mut_or_default();
}

fn normalize_service(service: &mut ServiceDescriptorProto) {
    for m in &mut service.method {
        normalize_method(m);
    }

    service.options.mut_or_default();
}

fn normalize_field(field: &mut FieldDescriptorProto) {
    field.options.mut_or_default();

    if field.has_default_value() {
        if field.get_field_type() == field_descriptor_proto::Type::TYPE_FLOAT {
            field.set_default_value(format!(
                "{}",
                parse_protobuf_float(field.get_default_value()).unwrap()
            ));
        }
    }
}

fn pretty_message<M: protobuf::Message>(message: &M) -> String {
    format!("{:#}", message)
}

fn descriptor_for_file<'a>(fds: &'a FileDescriptorSet, file_name: &str) -> &'a FileDescriptorProto {
    for file in &fds.file {
        if Path::new(file.get_name()).file_name().unwrap()
            == Path::new(file_name).file_name().unwrap()
        {
            return file;
        }
    }
    panic!(
        "file not found: {}; all files: {}",
        file_name,
        fds.file
            .iter()
            .map(|f| f.get_name())
            .collect::<Vec<_>>()
            .join(", ")
    );
}

fn test_diff_in<F>(root: &str, sources_dir: &str, include: &str, should_skip: F)
where
    F: Fn(&str) -> bool,
{
    let mut stats = TestStats {
        passed: 0,
        passed_marked_skip: 0,
        skipped: 0,
        failed: 0,
    };

    let mut include_root = Path::new(root).to_path_buf();
    include_root.push(include);

    let include_full = format!("{}/{}", root, include);
    let s_full = format!("{}/{}", root, sources_dir);

    let inputs_glob = format!("{}/*.proto*", s_full);
    let inputs = to_paths(glob_simple(&inputs_glob));
    assert!(!inputs.is_empty(), "glob is empty: {}", inputs_glob);
    let includes = to_paths(vec![include_full.as_str(), "../proto"]);

    let temp_dir = tempfile::Builder::new()
        .prefix("protobuf-codegen-identical-test")
        .tempdir()
        .unwrap();

    let protoc_dir = format!("{}/protoc", temp_dir.path().to_str().unwrap());
    let pure_dir = format!("{}/pure", temp_dir.path().to_str().unwrap());

    fs::create_dir(&protoc_dir).unwrap();
    fs::create_dir(&pure_dir).unwrap();

    Codegen::new()
        .protoc()
        .protoc_path(&protoc_bin_vendored::protoc_bin_path().unwrap())
        .inputs(&inputs)
        .includes(&includes)
        .out_dir(&protoc_dir)
        .run()
        .unwrap();

    Codegen::new()
        .pure()
        .inputs(&inputs)
        .includes(&includes)
        .out_dir(&pure_dir)
        .run()
        .unwrap();

    let mut protoc_descriptors = Parser::new()
        .protoc()
        .includes(&includes)
        .inputs(&inputs)
        .file_descriptor_set()
        .unwrap();
    let mut pure_descriptors = Parser::new()
        .pure()
        .includes(&includes)
        .inputs(&inputs)
        .file_descriptor_set()
        .unwrap();
    normalize_descriptor_set(&mut protoc_descriptors);
    normalize_descriptor_set(&mut pure_descriptors);

    for input in &inputs {
        let label = input.strip_prefix(root).unwrap().to_str().unwrap();
        let proto_file_name = input.strip_prefix(&include_root).unwrap().to_str().unwrap();
        let proto_name = input.file_name().unwrap().to_str().unwrap();
        let rs_name = protobuf_codegen::proto_name_to_rs(proto_name);
        let protoc_rs = format!("{}/{}", protoc_dir, rs_name);
        let pure_rs = format!("{}/{}", pure_dir, rs_name);

        normalize_generated_file_in_place(Path::new(&protoc_rs));
        normalize_generated_file_in_place(Path::new(&pure_rs));

        let protoc_rs_contents =
            fs::read_to_string(&protoc_rs).expect(&format!("while reading {}", protoc_rs));
        let pure_rs_contents =
            fs::read_to_string(&pure_rs).expect(&format!("while reading {}", pure_rs));

        let protoc_descriptor_for_file = descriptor_for_file(&protoc_descriptors, &proto_file_name);
        let pure_descriptor_for_file = descriptor_for_file(&pure_descriptors, &proto_file_name);

        let skip = should_skip(input.to_str().unwrap());
        if protoc_rs_contents == pure_rs_contents
            && protoc_descriptor_for_file == pure_descriptor_for_file
        {
            if !skip {
                stats.passed += 1;
                println!("{}: PASSED", label);
            } else {
                stats.passed_marked_skip += 1;
                println!("{}: PASSED BUT MARKED SKIP", label);
            }
        } else {
            if skip {
                stats.skipped += 1;
                println!("{} SKIPPED", label);
            } else {
                stats.failed += 1;
                println!("{} FAILED", label);
            }

            print_diff(
                temp_dir.path(),
                Path::new(&protoc_rs).strip_prefix(temp_dir.path()).unwrap(),
                Path::new(&pure_rs).strip_prefix(temp_dir.path()).unwrap(),
            );

            fs::write(
                format!("{}/{}.descriptors", protoc_dir, proto_name),
                pretty_message(protoc_descriptor_for_file),
            )
            .unwrap();
            fs::write(
                format!("{}/{}.descriptors", pure_dir, proto_name),
                pretty_message(pure_descriptor_for_file),
            )
            .unwrap();
            print_diff(
                temp_dir.path(),
                Path::new(&format!("protoc/{}.descriptors", proto_name)),
                Path::new(&format!("pure/{}.descriptors", proto_name)),
            );
        }
    }

    println!("{:?}", stats);
    assert!(stats.failed == 0, "at least one test failed");
}

fn should_skip_with_marker(path: &str) -> bool {
    fs::read_to_string(path)
        .unwrap()
        .contains("@skip-codegen-identical-test")
}

#[test]
fn common_v2() {
    test_diff_in(
        "../protobuf-test",
        "src/common/v2",
        "src/common/v2",
        should_skip_with_marker,
    );
}

#[test]
fn common_v3() {
    let common_v3_root = tempfile::Builder::new()
        .prefix("common-v3")
        .tempdir()
        .unwrap();
    fs::create_dir_all(format!(
        "{}/src/common/v3",
        common_v3_root.path().to_str().unwrap()
    ))
    .unwrap();

    copy_tests_v2_v3(
        "../protobuf-test/src/common/v2",
        &format!("{}/src/common/v3", common_v3_root.path().to_str().unwrap()),
    );

    test_diff_in(
        common_v3_root.path().to_str().unwrap(),
        "src/common/v3",
        "src/common/v3",
        should_skip_with_marker,
    );
}

#[test]
fn v2() {
    test_diff_in(
        "../protobuf-test",
        "src/v2",
        "src/v2",
        should_skip_with_marker,
    );
}

#[test]
fn v3() {
    test_diff_in(
        "../protobuf-test",
        "src/v3",
        "src/v3",
        should_skip_with_marker,
    );
}

#[test]
fn interop() {
    test_diff_in(
        "../protobuf-test",
        "../interop/cxx",
        "../interop/cxx",
        should_skip_with_marker,
    );
}

#[test]
fn google() {
    test_diff_in("../protobuf-test", "src/google/protobuf", "src", |_| false);
}
<|endoftext|>