<commit_before>// inspired by the muxing sample: http://ffmpeg.org/doxygen/trunk/muxing_8c-source.html

use libc::c_void;
use std::cast;
use swscale;
use swscale::Struct_SwsContext;
use avcodec;
use avcodec::{AVCodec, AVCodecContext, AVPacket};
use avformat;
use avformat::{AVFormatContext, AVStream};
use avutil;
use avutil::{AVFrame, Struct_AVRational};
use std::ptr;
use std::mem;
use sync::one::{Once, ONCE_INIT};
use window::Window;

static mut avformat_init: Once = ONCE_INIT;

/// OpenGL rendering video recorder.
///
/// Use this to make a video of your crazy 3D scene.
pub struct Recorder {
    tmp_frame_buf:    Vec<u8>,
    frame_buf:        Vec<u8>,
    curr_frame_index: uint,
    initialized:      bool,
    bit_rate:         uint,
    width:            uint,
    height:           uint,
    time_base:        (uint, uint),
    gop_size:         uint,
    max_b_frames:     uint,
    pix_fmt:          i32,
    tmp_frame:        *mut AVFrame,
    frame:            *mut AVFrame,
    context:          *mut AVCodecContext,
    format_context:   *mut AVFormatContext,
    video_st:         *mut AVStream,
    scale_context:    *mut Struct_SwsContext,
    path:             Path
}

impl Recorder {
    /// Creates a new video recorder.
    ///
    /// # Arguments:
    /// * `path`   - path to the output file.
    /// * `width`  - width of the recorded video.
    /// * `height` - height of the recorded video.
    pub fn new(path: Path, width: uint, height: uint) -> Recorder {
        Recorder::new_with_params(path, width, height, None, None, None, None, None)
    }

    /// Creates a new video recorder with custom recording parameters.
    ///
    /// # Arguments:
    /// * `path`         - path to the output file.
    /// * `width`        - width of the recorded video.
    /// * `height`       - height of the recorded video.
    /// * `bit_rate`     - the average bit rate. Default value: 400000.
    /// * `time_base`    - this is the fundamental unit of time (in seconds) in terms of which
    ///                    frame timestamps are represented. Default value: (1, 60), i-e, 60fps.
    /// * `gop_size`     - the number of pictures in a group of pictures. Default value: 10.
    /// * `max_b_frames` - maximum number of B-frames between non-B-frames. Default value: 1.
    /// * `pix_fmt`      - pixel format. Default value: `avcodec::AV_CODEC_ID_MPEG1VIDEO`.
    pub fn new_with_params(path:         Path,
                           width:        uint,
                           height:       uint,
                           bit_rate:     Option<uint>,
                           time_base:    Option<(uint, uint)>,
                           gop_size:     Option<uint>,
                           max_b_frames: Option<uint>,
                           pix_fmt:      Option<i32>)
                           -> Recorder {
        unsafe {
            avformat_init.doit(|| {
                avformat::av_register_all();
            });
        }

        let bit_rate     = bit_rate.unwrap_or(400000); // FIXME
        let time_base    = time_base.unwrap_or((1, 60));
        let gop_size     = gop_size.unwrap_or(10);
        let max_b_frames = max_b_frames.unwrap_or(1);
        let pix_fmt      = pix_fmt.unwrap_or(avutil::PIX_FMT_YUV420P);
        // width and height must be a multiple of two.
        let width        = if width  % 2 == 0 { width }  else { width + 1 };
        let height       = if height % 2 == 0 { height } else { height + 1 };

        Recorder {
            initialized:      false,
            curr_frame_index: 0,
            bit_rate:         bit_rate,
            width:            width,
            height:           height,
            time_base:        time_base,
            gop_size:         gop_size,
            max_b_frames:     max_b_frames,
            pix_fmt:          pix_fmt,
            frame:            ptr::mut_null(),
            tmp_frame:        ptr::mut_null(),
            context:          ptr::mut_null(),
            scale_context:    ptr::mut_null(),
            format_context:   ptr::mut_null(),
            video_st:         ptr::mut_null(),
            path:             path,
            // XXX: we do the following hacky allocation since the bindings do not give
            // access to avcodec::av_image_alloc…
            // FIXME: does that depend on the pix_fmt ?
            frame_buf:        Vec::new(),
            tmp_frame_buf:    Vec::new()
        }
    }

    /// Captures an image from the window and adds it to the current video.
    pub fn snap(&mut self, window: &Window) {
        self.init();

        let mut pkt: AVPacket = unsafe { mem::uninit() };

        unsafe {
            avcodec::av_init_packet(&mut pkt);
        }

        pkt.data = RawPtr::null();  // packet data will be allocated by the encoder
        pkt.size = 0;

        /*
         *
         * Fill the snapshot frame.
         *
         */
        window.snap(&mut self.tmp_frame_buf);

        let win_width  = window.width() as i32;
        let win_height = window.height() as i32;

        unsafe {
            (*self.frame).pts += avutil::av_rescale_q(1, (*self.context).time_base, (*self.video_st).time_base);
            self.curr_frame_index = self.curr_frame_index + 1;
        }

        unsafe {

            (*self.tmp_frame).width  = win_width;
            (*self.tmp_frame).height = win_height;

            let _ = avcodec::avpicture_fill(self.tmp_frame as *mut avcodec::AVPicture,
                                            self.tmp_frame_buf.get(0),
                                            avutil::PIX_FMT_RGB24,
                                            win_width,
                                            win_height);
        }

        /*
         * Convert the snapshot frame to the right format for the destination frame.
         */
        unsafe {
            self.scale_context = swscale::sws_getCachedContext(
                self.scale_context, win_width, win_height, avutil::PIX_FMT_RGB24,
                self.width as i32, self.height as i32, avutil::PIX_FMT_YUV420P,
                swscale::SWS_BICUBIC as i32, ptr::mut_null(), ptr::mut_null(), ptr::null()
                );

            let _ = swscale::sws_scale(self.scale_context,
                                       &(*self.tmp_frame).data[0], &(*self.tmp_frame).linesize[0],
                                       0, win_height,
                                       cast::transmute(&(*self.frame).data[0]), &(*self.frame).linesize[0]);
        }

        // Encode the image.

        let mut got_output = 0;
        let ret;

        unsafe {
            ret = avcodec::avcodec_encode_video2(self.context,
                                                 &mut pkt,
                                                 self.frame as *AVFrame,
                                                 &mut got_output);
        }

        if ret < 0 {
            fail!("Error encoding frame.");
        }

        if got_output != 0 {
            unsafe {
                let _ = avformat::av_interleaved_write_frame(self.format_context, &mut pkt);
                avcodec::av_free_packet(&mut pkt);
            }
        }
    }

    /// Initializes the recorder.
    ///
    /// This is automatically called when the first snapshot is made. Call this explicitly if you
    /// do not want the extra time overhead when the first snapshot is made.
    pub fn init(&mut self) {
        if self.initialized {
            return;
        }

        unsafe {
            // try to guess the container type from the path.
            let mut fmt = ptr::mut_null();

            self.path.with_c_str(|path| {
                let _ = avformat::avformat_alloc_output_context2(&mut fmt, ptr::mut_null(), ptr::null(), path);

                if self.format_context.is_null() {
                    // could not guess, default to MPEG
                    "mpeg".with_c_str(|mpeg| {
                        let _ = avformat::avformat_alloc_output_context2(&mut fmt, ptr::mut_null(), mpeg, path);
                    });
                }
            });

            self.format_context = fmt;

            if self.format_context.is_null() {
                fail!("Unable to create the output context.");
            }

            let fmt = (*self.format_context).oformat;

            if (*fmt).video_codec == avcodec::AV_CODEC_ID_NONE {
                fail!("The selected output container does not support video encoding.")
            }

            let mut codec: *mut AVCodec;

            let ret: i32 = 0;

            codec = avcodec::avcodec_find_encoder((*fmt).video_codec);

            if codec.is_null() {
                fail!("Codec not found.");
            }

            self.video_st = avformat::avformat_new_stream(self.format_context, codec as *AVCodec);

            if self.video_st.is_null() {
                fail!("Failed to allocate the video stream.");
            }

            (*self.video_st).id = ((*self.format_context).nb_streams - 1) as i32;

            self.context = (*self.video_st).codec;

            let _ = avcodec::avcodec_get_context_defaults3(self.context, codec as *AVCodec);

            if self.context.is_null() {
                fail!("Could not allocate video codec context.");
            }

            // sws scaling context
            self.scale_context = swscale::sws_getContext(
                self.width as i32, self.height as i32, avutil::PIX_FMT_RGB24,
                self.width as i32, self.height as i32, (*fmt).video_codec as i32,
                swscale::SWS_BICUBIC as i32, ptr::mut_null(), ptr::mut_null(), ptr::null());

            // Put sample parameters.
            (*self.context).bit_rate = self.bit_rate as i32;

            // Resolution must be a multiple of two.
            (*self.context).width    = self.width  as i32;
            (*self.context).height   = self.height as i32;

            // frames per second.
            let (tnum, tdenum)           = self.time_base;
            (*self.context).time_base    = Struct_AVRational { num: tnum as i32, den: tdenum as i32 };
            (*self.context).gop_size     = self.gop_size as i32;
            (*self.context).max_b_frames = self.max_b_frames as i32;
            (*self.context).pix_fmt      = self.pix_fmt;

            if (*self.context).codec_id == avcodec::AV_CODEC_ID_MPEG1VIDEO {
                // Needed to avoid using macroblocks in which some coeffs overflow.
                // This does not happen with normal video, it just happens here as
                // the motion of the chroma plane does not match the luma plane.
                (*self.context).mb_decision = 2;
            }

            /*
            if (*fmt).flags & avformat::AVFMT_GLOBALHEADER != 0 {
                (*self.context).flags = (*self.context).flags | CODEC_FLAG_GLOBAL_HEADER;
            }
            */

            // Open the codec.
            if avcodec::avcodec_open2(self.context, codec as *AVCodec, ptr::mut_null()) < 0 {
                fail!("Could not open the codec.");
            }

            /*
             * Init the destination video frame.
             */
            self.frame = avcodec::avcodec_alloc_frame();

            if self.frame.is_null() {
                fail!("Could not allocate the video frame.");
            }

            (*self.frame).format = (*self.context).pix_fmt;
            (*self.frame).width  = (*self.context).width;
            (*self.frame).height = (*self.context).height;
            (*self.frame).pts    = 0;

            // alloc the buffer
            let nframe_bytes = avcodec::avpicture_get_size(self.pix_fmt,
                                                           self.width as i32,
                                                           self.height as i32);
            self.frame_buf = Vec::from_elem(nframe_bytes as uint, 0u8);

            let _ = avcodec::avpicture_fill(self.frame as *mut avcodec::AVPicture,
                                            self.frame_buf.get(0),
                                            self.pix_fmt,
                                            self.width as i32,
                                            self.height as i32);

            /*
             * Init the temporary video frame.
             */
            self.tmp_frame = avcodec::avcodec_alloc_frame();

            if self.tmp_frame.is_null() {
                fail!("Could not allocate the video frame.");
            }

            (*self.frame).format = (*self.context).pix_fmt;
            // the rest (width, height, data, linesize) are set at the moment of the snapshot.

            // Open the output file.
            self.path.with_c_str(|path| {
                static AVIO_FLAG_WRITE: i32 = 2; // XXX: this should be defined by the bindings.
                if avformat::avio_open(&mut (*self.format_context).pb, path, AVIO_FLAG_WRITE) < 0 {
                    fail!("Failed to open the output file.");
                }
            });

            if avformat::avformat_write_header(self.format_context, ptr::mut_null()) < 0 {
                fail!("Failed to open the output file.");
            }

            if ret < 0 {
                fail!("Could not allocate raw picture buffer");
            }
        }

        self.initialized = true;
    }
}

impl Drop for Recorder {
    fn drop(&mut self) {
        if self.initialized {
            // Get the delayed frames.
            let mut pkt:   AVPacket = unsafe { mem::uninit() };
            let mut got_output = 1;
            while got_output != 0 {
                let ret;

                unsafe {
                    avcodec::av_init_packet(&mut pkt);
                }

                pkt.data = RawPtr::null();  // packet data will be allocated by the encoder
                pkt.size = 0;

                unsafe {
                    ret = avcodec::avcodec_encode_video2(self.context, &mut pkt, ptr::null(), &mut got_output);
                }

                if ret < 0 {
                    fail!("Error encoding frame.");
                }

                if got_output != 0 {
                    unsafe {
                        let _ = avformat::av_interleaved_write_frame(self.format_context, &mut pkt);
                        avcodec::av_free_packet(&mut pkt);
                    }
                }
            }

            // Free things and stuffs.
            unsafe {
                let _ = avcodec::avcodec_close(self.context);
                avutil::av_free(self.context as *mut c_void);
                // avutil::av_freep((*self.frame).data[0] as *mut c_void);
                avcodec::avcodec_free_frame(&mut self.frame as *mut *mut AVFrame);
                avcodec::avcodec_free_frame(&mut self.tmp_frame as *mut *mut AVFrame);
            }
        }
    }
}
<commit_msg>Fix a comment.<commit_after>// inspired by the muxing sample: http://ffmpeg.org/doxygen/trunk/muxing_8c-source.html

use libc::c_void;
use std::cast;
use swscale;
use swscale::Struct_SwsContext;
use avcodec;
use avcodec::{AVCodec, AVCodecContext, AVPacket};
use avformat;
use avformat::{AVFormatContext, AVStream};
use avutil;
use avutil::{AVFrame, Struct_AVRational};
use std::ptr;
use std::mem;
use sync::one::{Once, ONCE_INIT};
use window::Window;

static mut avformat_init: Once = ONCE_INIT;

/// OpenGL rendering video recorder.
///
/// Use this to make a video of your crazy 3D scene.
pub struct Recorder {
    tmp_frame_buf:    Vec<u8>,
    frame_buf:        Vec<u8>,
    curr_frame_index: uint,
    initialized:      bool,
    bit_rate:         uint,
    width:            uint,
    height:           uint,
    time_base:        (uint, uint),
    gop_size:         uint,
    max_b_frames:     uint,
    pix_fmt:          i32,
    tmp_frame:        *mut AVFrame,
    frame:            *mut AVFrame,
    context:          *mut AVCodecContext,
    format_context:   *mut AVFormatContext,
    video_st:         *mut AVStream,
    scale_context:    *mut Struct_SwsContext,
    path:             Path
}

impl Recorder {
    /// Creates a new video recorder.
    ///
    /// # Arguments:
    /// * `path`   - path to the output file.
    /// * `width`  - width of the recorded video.
    /// * `height` - height of the recorded video.
    pub fn new(path: Path, width: uint, height: uint) -> Recorder {
        Recorder::new_with_params(path, width, height, None, None, None, None, None)
    }

    /// Creates a new video recorder with custom recording parameters.
    ///
    /// # Arguments:
    /// * `path`         - path to the output file.
    /// * `width`        - width of the recorded video.
    /// * `height`       - height of the recorded video.
    /// * `bit_rate`     - the average bit rate. Default value: 400000.
    /// * `time_base`    - this is the fundamental unit of time (in seconds) in terms of which
    ///                    frame timestamps are represented. Default value: (1, 60), i-e, 60fps.
    /// * `gop_size`     - the number of pictures in a group of pictures. Default value: 10.
    /// * `max_b_frames` - maximum number of B-frames between non-B-frames. Default value: 1.
    /// * `pix_fmt`      - pixel format. Default value: `avutil::PIX_FMT_YUV420P`.
    pub fn new_with_params(path:         Path,
                           width:        uint,
                           height:       uint,
                           bit_rate:     Option<uint>,
                           time_base:    Option<(uint, uint)>,
                           gop_size:     Option<uint>,
                           max_b_frames: Option<uint>,
                           pix_fmt:      Option<i32>)
                           -> Recorder {
        unsafe {
            avformat_init.doit(|| {
                avformat::av_register_all();
            });
        }

        let bit_rate     = bit_rate.unwrap_or(400000); // FIXME
        let time_base    = time_base.unwrap_or((1, 60));
        let gop_size     = gop_size.unwrap_or(10);
        let max_b_frames = max_b_frames.unwrap_or(1);
        let pix_fmt      = pix_fmt.unwrap_or(avutil::PIX_FMT_YUV420P);
        // width and height must be a multiple of two.
        let width        = if width  % 2 == 0 { width }  else { width + 1 };
        let height       = if height % 2 == 0 { height } else { height + 1 };

        Recorder {
            initialized:      false,
            curr_frame_index: 0,
            bit_rate:         bit_rate,
            width:            width,
            height:           height,
            time_base:        time_base,
            gop_size:         gop_size,
            max_b_frames:     max_b_frames,
            pix_fmt:          pix_fmt,
            frame:            ptr::mut_null(),
            tmp_frame:        ptr::mut_null(),
            context:          ptr::mut_null(),
            scale_context:    ptr::mut_null(),
            format_context:   ptr::mut_null(),
            video_st:         ptr::mut_null(),
            path:             path,
            frame_buf:        Vec::new(),
            tmp_frame_buf:    Vec::new()
        }
    }

    /// Captures an image from the window and adds it to the current video.
    pub fn snap(&mut self, window: &Window) {
        self.init();

        let mut pkt: AVPacket = unsafe { mem::uninit() };

        unsafe {
            avcodec::av_init_packet(&mut pkt);
        }

        pkt.data = RawPtr::null();  // packet data will be allocated by the encoder
        pkt.size = 0;

        /*
         *
         * Fill the snapshot frame.
         *
         */
        window.snap(&mut self.tmp_frame_buf);

        let win_width  = window.width() as i32;
        let win_height = window.height() as i32;

        unsafe {
            (*self.frame).pts += avutil::av_rescale_q(1, (*self.context).time_base, (*self.video_st).time_base);
            self.curr_frame_index = self.curr_frame_index + 1;
        }

        unsafe {

            (*self.tmp_frame).width  = win_width;
            (*self.tmp_frame).height = win_height;

            let _ = avcodec::avpicture_fill(self.tmp_frame as *mut avcodec::AVPicture,
                                            self.tmp_frame_buf.get(0),
                                            avutil::PIX_FMT_RGB24,
                                            win_width,
                                            win_height);
        }

        /*
         * Convert the snapshot frame to the right format for the destination frame.
         */
        unsafe {
            self.scale_context = swscale::sws_getCachedContext(
                self.scale_context, win_width, win_height, avutil::PIX_FMT_RGB24,
                self.width as i32, self.height as i32, avutil::PIX_FMT_YUV420P,
                swscale::SWS_BICUBIC as i32, ptr::mut_null(), ptr::mut_null(), ptr::null()
                );

            let _ = swscale::sws_scale(self.scale_context,
                                       &(*self.tmp_frame).data[0], &(*self.tmp_frame).linesize[0],
                                       0, win_height,
                                       cast::transmute(&(*self.frame).data[0]), &(*self.frame).linesize[0]);
        }

        // Encode the image.

        let mut got_output = 0;
        let ret;

        unsafe {
            ret = avcodec::avcodec_encode_video2(self.context,
                                                 &mut pkt,
                                                 self.frame as *AVFrame,
                                                 &mut got_output);
        }

        if ret < 0 {
            fail!("Error encoding frame.");
        }

        if got_output != 0 {
            unsafe {
                let _ = avformat::av_interleaved_write_frame(self.format_context, &mut pkt);
                avcodec::av_free_packet(&mut pkt);
            }
        }
    }

    /// Initializes the recorder.
    ///
    /// This is automatically called when the first snapshot is made. Call this explicitly if you
    /// do not want the extra time overhead when the first snapshot is made.
    pub fn init(&mut self) {
        if self.initialized {
            return;
        }

        unsafe {
            // try to guess the container type from the path.
            let mut fmt = ptr::mut_null();

            self.path.with_c_str(|path| {
                let _ = avformat::avformat_alloc_output_context2(&mut fmt, ptr::mut_null(), ptr::null(), path);

                if self.format_context.is_null() {
                    // could not guess, default to MPEG
                    "mpeg".with_c_str(|mpeg| {
                        let _ = avformat::avformat_alloc_output_context2(&mut fmt, ptr::mut_null(), mpeg, path);
                    });
                }
            });

            self.format_context = fmt;

            if self.format_context.is_null() {
                fail!("Unable to create the output context.");
            }

            let fmt = (*self.format_context).oformat;

            if (*fmt).video_codec == avcodec::AV_CODEC_ID_NONE {
                fail!("The selected output container does not support video encoding.")
            }

            let mut codec: *mut AVCodec;

            let ret: i32 = 0;

            codec = avcodec::avcodec_find_encoder((*fmt).video_codec);

            if codec.is_null() {
                fail!("Codec not found.");
            }

            self.video_st = avformat::avformat_new_stream(self.format_context, codec as *AVCodec);

            if self.video_st.is_null() {
                fail!("Failed to allocate the video stream.");
            }

            (*self.video_st).id = ((*self.format_context).nb_streams - 1) as i32;

            self.context = (*self.video_st).codec;

            let _ = avcodec::avcodec_get_context_defaults3(self.context, codec as *AVCodec);

            if self.context.is_null() {
                fail!("Could not allocate video codec context.");
            }

            // sws scaling context
            self.scale_context = swscale::sws_getContext(
                self.width as i32, self.height as i32, avutil::PIX_FMT_RGB24,
                self.width as i32, self.height as i32, (*fmt).video_codec as i32,
                swscale::SWS_BICUBIC as i32, ptr::mut_null(), ptr::mut_null(), ptr::null());

            // Put sample parameters.
            (*self.context).bit_rate = self.bit_rate as i32;

            // Resolution must be a multiple of two.
            (*self.context).width    = self.width  as i32;
            (*self.context).height   = self.height as i32;

            // frames per second.
            let (tnum, tdenum)           = self.time_base;
            (*self.context).time_base    = Struct_AVRational { num: tnum as i32, den: tdenum as i32 };
            (*self.context).gop_size     = self.gop_size as i32;
            (*self.context).max_b_frames = self.max_b_frames as i32;
            (*self.context).pix_fmt      = self.pix_fmt;

            if (*self.context).codec_id == avcodec::AV_CODEC_ID_MPEG1VIDEO {
                // Needed to avoid using macroblocks in which some coeffs overflow.
                // This does not happen with normal video, it just happens here as
                // the motion of the chroma plane does not match the luma plane.
                (*self.context).mb_decision = 2;
            }

            /*
            if (*fmt).flags & avformat::AVFMT_GLOBALHEADER != 0 {
                (*self.context).flags = (*self.context).flags | CODEC_FLAG_GLOBAL_HEADER;
            }
            */

            // Open the codec.
            if avcodec::avcodec_open2(self.context, codec as *AVCodec, ptr::mut_null()) < 0 {
                fail!("Could not open the codec.");
            }

            /*
             * Init the destination video frame.
             */
            self.frame = avcodec::avcodec_alloc_frame();

            if self.frame.is_null() {
                fail!("Could not allocate the video frame.");
            }

            (*self.frame).format = (*self.context).pix_fmt;
            (*self.frame).width  = (*self.context).width;
            (*self.frame).height = (*self.context).height;
            (*self.frame).pts    = 0;

            // alloc the buffer
            let nframe_bytes = avcodec::avpicture_get_size(self.pix_fmt,
                                                           self.width as i32,
                                                           self.height as i32);
            self.frame_buf = Vec::from_elem(nframe_bytes as uint, 0u8);

            let _ = avcodec::avpicture_fill(self.frame as *mut avcodec::AVPicture,
                                            self.frame_buf.get(0),
                                            self.pix_fmt,
                                            self.width as i32,
                                            self.height as i32);

            /*
             * Init the temporary video frame.
             */
            self.tmp_frame = avcodec::avcodec_alloc_frame();

            if self.tmp_frame.is_null() {
                fail!("Could not allocate the video frame.");
            }

            (*self.frame).format = (*self.context).pix_fmt;
            // the rest (width, height, data, linesize) are set at the moment of the snapshot.

            // Open the output file.
            self.path.with_c_str(|path| {
                static AVIO_FLAG_WRITE: i32 = 2; // XXX: this should be defined by the bindings.
                if avformat::avio_open(&mut (*self.format_context).pb, path, AVIO_FLAG_WRITE) < 0 {
                    fail!("Failed to open the output file.");
                }
            });

            if avformat::avformat_write_header(self.format_context, ptr::mut_null()) < 0 {
                fail!("Failed to open the output file.");
            }

            if ret < 0 {
                fail!("Could not allocate raw picture buffer");
            }
        }

        self.initialized = true;
    }
}

impl Drop for Recorder {
    fn drop(&mut self) {
        if self.initialized {
            // Get the delayed frames.
            let mut pkt:   AVPacket = unsafe { mem::uninit() };
            let mut got_output = 1;
            while got_output != 0 {
                let ret;

                unsafe {
                    avcodec::av_init_packet(&mut pkt);
                }

                pkt.data = RawPtr::null();  // packet data will be allocated by the encoder
                pkt.size = 0;

                unsafe {
                    ret = avcodec::avcodec_encode_video2(self.context, &mut pkt, ptr::null(), &mut got_output);
                }

                if ret < 0 {
                    fail!("Error encoding frame.");
                }

                if got_output != 0 {
                    unsafe {
                        let _ = avformat::av_interleaved_write_frame(self.format_context, &mut pkt);
                        avcodec::av_free_packet(&mut pkt);
                    }
                }
            }

            // Free things and stuffs.
            unsafe {
                let _ = avcodec::avcodec_close(self.context);
                avutil::av_free(self.context as *mut c_void);
                // avutil::av_freep((*self.frame).data[0] as *mut c_void);
                avcodec::avcodec_free_frame(&mut self.frame as *mut *mut AVFrame);
                avcodec::avcodec_free_frame(&mut self.tmp_frame as *mut *mut AVFrame);
            }
        }
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl Clone for ListNode {
    fn clone(&self) -> ListNode {
        let mut result = ListNode::new(self.val);
        result.next = self.next.clone();
        return result;
    }
}

impl ListNode {
    fn new(v: i32) -> Self {
        ListNode { val: v, next: None }
    }

    fn check_ten(&mut self, flag: i32) {
        let mut inner_flag = flag;
        self.val += flag;
        if self.val >= 10 {
            self.val -= 10;
            inner_flag = 1;
        } else {
            inner_flag = 0;
        }

        match self.next {
            Some(ref mut n) => n.check_ten(inner_flag),
            None => if inner_flag == 1 {
                self.next = Some(Box::new(ListNode::new(inner_flag)));
            },
        }
    }
}

fn add_two_numbers(a: ListNode, b: ListNode, flag: i32) -> ListNode {
    let mut inner_flag = flag;
    let mut result = ListNode::new(a.val + b.val);

    let mut inner_a = a;
    let mut inner_b = b;

    if inner_a.next.is_some() && inner_b.next.is_some() {
        result.val += inner_flag;
        if result.val >= 10 {
            result.val -= 10;
            inner_flag = 1;
        } else {
            inner_flag = 0;
        }

        inner_a = Box::leak(inner_a.next.unwrap()).clone();
        inner_b = Box::leak(inner_b.next.unwrap()).clone();
        result.next = Some(Box::new(add_two_numbers(inner_a, inner_b, inner_flag)))
    } else if inner_a.next.is_none() && inner_b.next.is_some() {
        let temp = Box::leak(inner_b.next.unwrap()).clone();
        result.next = Some(Box::new(temp));
        result.check_ten(inner_flag)
    } else if inner_b.next.is_none() && inner_a.next.is_some() {
        let temp = Box::leak(inner_a.next.unwrap()).clone();
        result.next = Some(Box::new(temp));
        result.check_ten(inner_flag)
    } else if inner_a.next.is_none() && inner_b.next.is_none() {
        result.check_ten(inner_flag);
    }

    return result;
}

fn main() {
    let a = ListNode::new(1);
    let mut b = ListNode::new(9);
    b.next = Some(Box::new(ListNode::new(2)));

    println!("{:?}", add_two_numbers(a, b, 0));

    let c = ListNode::new(2);
    let mut d = ListNode::new(8);
    let mut d1 = ListNode::new(9);
    let mut d2 = ListNode::new(9);
    d1.next = Some(Box::new(d2));
    d.next = Some(Box::new(d1));

    println!("{:?}", add_two_numbers(c, d, 0));
}
<commit_msg>a bit<commit_after>#[derive(Debug)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl Clone for ListNode {
    fn clone(&self) -> ListNode {
        let mut result = ListNode::new(self.val);
        result.next = self.next.clone();
        return result;
    }
}

impl ListNode {
    fn new(v: i32) -> Self {
        ListNode { val: v, next: None }
    }

    fn check_ten(&mut self, flag: i32) {
        let mut inner_flag = flag;
        self.val += flag;
        if self.val >= 10 {
            self.val -= 10;
            inner_flag = 1;
        } else {
            inner_flag = 0;
        }

        match self.next {
            Some(ref mut n) => n.check_ten(inner_flag),
            None => if inner_flag == 1 {
                self.next = Some(Box::new(ListNode::new(inner_flag)));
            },
        }
    }
}

fn add_two_numbers(a: ListNode, b: ListNode, flag: i32) -> ListNode {
    let mut inner_flag = flag;
    let mut result = ListNode::new(a.val + b.val);

    if a.next.is_some() && b.next.is_some() {
        result.val += inner_flag;
        if result.val >= 10 {
            result.val -= 10;
            inner_flag = 1;
        } else {
            inner_flag = 0;
        }

        let inner_a = Box::leak(a.next.unwrap()).clone();
        let inner_b = Box::leak(b.next.unwrap()).clone();
        result.next = Some(Box::new(add_two_numbers(inner_a, inner_b, inner_flag)))
    } else if a.next.is_none() && b.next.is_some() {
        let temp = Box::leak(b.next.unwrap()).clone();
        result.next = Some(Box::new(temp));
        result.check_ten(inner_flag)
    } else if b.next.is_none() && a.next.is_some() {
        let temp = Box::leak(a.next.unwrap()).clone();
        result.next = Some(Box::new(temp));
        result.check_ten(inner_flag)
    } else if a.next.is_none() && b.next.is_none() {
        result.check_ten(inner_flag);
    }

    return result;
}

fn main() {
    let a = ListNode::new(1);
    let mut b = ListNode::new(9);
    b.next = Some(Box::new(ListNode::new(2)));

    println!("{:?}", add_two_numbers(a, b, 0));

    let c = ListNode::new(2);
    let mut d = ListNode::new(8);
    let mut d1 = ListNode::new(9);
    let mut d2 = ListNode::new(9);
    d1.next = Some(Box::new(d2));
    d.next = Some(Box::new(d1));

    println!("{:?}", add_two_numbers(c, d, 0));
}
<|endoftext|>


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

use std::cmp;

use matches::matches;
use crate::rustc::hir;
use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::FnKind;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use crate::rustc::ty::TyKind;
use crate::rustc::ty::FnSig;
use crate::rustc::session::config::Config as SessionConfig;
use crate::rustc_target::spec::abi::Abi;
use crate::rustc_target::abi::LayoutOf;
use crate::syntax::ast::NodeId;
use crate::syntax_pos::Span;
use crate::utils::{in_macro, is_copy, is_self_ty, span_lint_and_sugg, snippet};

/// **What it does:** Checks for functions taking arguments by reference, where
/// the argument type is `Copy` and small enough to be more efficient to always
/// pass by value.
///
/// **Why is this bad?** In many calling conventions instances of structs will
/// be passed through registers if they fit into two or less general purpose
/// registers.
///
/// **Known problems:** This lint is target register size dependent, it is
/// limited to 32-bit to try and reduce portability problems between 32 and
/// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
/// will be different.
///
/// The configuration option `trivial_copy_size_limit` can be set to override
/// this limit for a project.
///
/// This lint attempts to allow passing arguments by reference if a reference
/// to that argument is returned. This is implemented by comparing the lifetime
/// of the argument and return value for equality. However, this can cause
/// false positives in cases involving multiple lifetimes that are bounded by
/// each other.
///
/// **Example:**
/// ```rust
/// fn foo(v: &u32) {
///     assert_eq!(v, 42);
/// }
/// // should be
/// fn foo(v: u32) {
///     assert_eq!(v, 42);
/// }
/// ```
declare_clippy_lint! {
    pub TRIVIALLY_COPY_PASS_BY_REF,
    perf,
    "functions taking small copyable arguments by reference"
}

pub struct TriviallyCopyPassByRef {
    limit: u64,
}

impl<'a, 'tcx> TriviallyCopyPassByRef {
    pub fn new(limit: Option<u64>, target: &SessionConfig) -> Self {
        let limit = limit.unwrap_or_else(|| {
            let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64;
            // Cap the calculated bit width at 32-bits to reduce
            // portability problems between 32 and 64-bit targets
            let bit_width = cmp::min(bit_width, 32);
            let byte_width = bit_width / 8;
            // Use a limit of 2 times the register bit width
            byte_width * 2
        });
        Self { limit }
    }

    fn check_trait_method(
        &mut self,
        cx: &LateContext<'_, 'tcx>,
        item: &TraitItemRef
    ) {
        let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id);
        let method_sig = cx.tcx.fn_sig(method_def_id);
        let method_sig = cx.tcx.erase_late_bound_regions(&method_sig);

        let decl = match cx.tcx.hir.fn_decl(item.id.node_id) {
            Some(b) => b,
            None => return,
        };

        self.check_poly_fn(cx, &decl, &method_sig, None);
    }

    fn check_poly_fn(
        &mut self,
        cx: &LateContext<'_, 'tcx>,
        decl: &FnDecl,
        sig: &FnSig<'tcx>,
        span: Option<Span>,
    ) {
        // Use lifetimes to determine if we're returning a reference to the
        // argument. In that case we can't switch to pass-by-value as the
        // argument will not live long enough.
        let output_lts = match sig.output().sty {
            TyKind::Ref(output_lt, _, _) => vec![output_lt],
            TyKind::Adt(_, substs) => substs.regions().collect(),
            _ => vec![],
        };

        for (input, &ty) in decl.inputs.iter().zip(sig.inputs()) {
            // All spans generated from a proc-macro invocation are the same...
            match span {
                Some(s) if  s == input.span => return,
                _ => (),
            }

            if_chain! {
                if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty;
                if !output_lts.contains(&input_lt);
                if is_copy(cx, ty);
                if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
                if size <= self.limit;
                if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node;
                then {
                    let value_type = if is_self_ty(decl_ty) {
                        "self".into()
                    } else {
                        snippet(cx, decl_ty.span, "_").into()
                    };
                    span_lint_and_sugg(
                        cx,
                        TRIVIALLY_COPY_PASS_BY_REF,
                        input.span,
                        "this argument is passed by reference, but would be more efficient if passed by value",
                        "consider passing by value instead",
                        value_type);
                }
            }
        }
    }

    fn check_trait_items(
        &mut self,
        cx: &LateContext<'_, '_>,
        trait_items: &[TraitItemRef]
    ) {
        for item in trait_items {
            match item.kind {
                AssociatedItemKind::Method{ has_self: _ } => self.check_trait_method(cx, item),
                _ => (),
            }
        }
    }
}

impl LintPass for TriviallyCopyPassByRef {
    fn get_lints(&self) -> LintArray {
        lint_array![TRIVIALLY_COPY_PASS_BY_REF]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro(item.span) {
            return;
        }
        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => self.check_trait_items(cx, trait_items),
            _ => (),
        }
    }

    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        _body: &'tcx Body,
        span: Span,
        node_id: NodeId,
    ) {
        if in_macro(span) {
            return;
        }

        match kind {
            FnKind::ItemFn(.., header, _, attrs) => {
                if header.abi != Abi::Rust {
                    return;
                }
                for a in attrs {
                    if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
                        return;
                    }
                }
            },
            FnKind::Method(..) => (),
            _ => return,
        }

        // Exclude non-inherent impls
        if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
            if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) |
                ItemKind::Trait(..))
            {
                return;
            }
        }

        let fn_def_id = cx.tcx.hir.local_def_id(node_id);

        let fn_sig = cx.tcx.fn_sig(fn_def_id);
        let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig);

        self.check_poly_fn(cx, decl, &fn_sig, Some(span));
    }
}
<commit_msg>Address travis CI lint failure<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;

use matches::matches;
use crate::rustc::hir;
use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::FnKind;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use crate::rustc::ty::TyKind;
use crate::rustc::ty::FnSig;
use crate::rustc::session::config::Config as SessionConfig;
use crate::rustc_target::spec::abi::Abi;
use crate::rustc_target::abi::LayoutOf;
use crate::syntax::ast::NodeId;
use crate::syntax_pos::Span;
use crate::utils::{in_macro, is_copy, is_self_ty, span_lint_and_sugg, snippet};

/// **What it does:** Checks for functions taking arguments by reference, where
/// the argument type is `Copy` and small enough to be more efficient to always
/// pass by value.
///
/// **Why is this bad?** In many calling conventions instances of structs will
/// be passed through registers if they fit into two or less general purpose
/// registers.
///
/// **Known problems:** This lint is target register size dependent, it is
/// limited to 32-bit to try and reduce portability problems between 32 and
/// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
/// will be different.
///
/// The configuration option `trivial_copy_size_limit` can be set to override
/// this limit for a project.
///
/// This lint attempts to allow passing arguments by reference if a reference
/// to that argument is returned. This is implemented by comparing the lifetime
/// of the argument and return value for equality. However, this can cause
/// false positives in cases involving multiple lifetimes that are bounded by
/// each other.
///
/// **Example:**
/// ```rust
/// fn foo(v: &u32) {
///     assert_eq!(v, 42);
/// }
/// // should be
/// fn foo(v: u32) {
///     assert_eq!(v, 42);
/// }
/// ```
declare_clippy_lint! {
    pub TRIVIALLY_COPY_PASS_BY_REF,
    perf,
    "functions taking small copyable arguments by reference"
}

pub struct TriviallyCopyPassByRef {
    limit: u64,
}

impl<'a, 'tcx> TriviallyCopyPassByRef {
    pub fn new(limit: Option<u64>, target: &SessionConfig) -> Self {
        let limit = limit.unwrap_or_else(|| {
            let bit_width = target.usize_ty.bit_width().expect("usize should have a width") as u64;
            // Cap the calculated bit width at 32-bits to reduce
            // portability problems between 32 and 64-bit targets
            let bit_width = cmp::min(bit_width, 32);
            let byte_width = bit_width / 8;
            // Use a limit of 2 times the register bit width
            byte_width * 2
        });
        Self { limit }
    }

    fn check_trait_method(
        &mut self,
        cx: &LateContext<'_, 'tcx>,
        item: &TraitItemRef
    ) {
        let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id);
        let method_sig = cx.tcx.fn_sig(method_def_id);
        let method_sig = cx.tcx.erase_late_bound_regions(&method_sig);

        let decl = match cx.tcx.hir.fn_decl(item.id.node_id) {
            Some(b) => b,
            None => return,
        };

        self.check_poly_fn(cx, &decl, &method_sig, None);
    }

    fn check_poly_fn(
        &mut self,
        cx: &LateContext<'_, 'tcx>,
        decl: &FnDecl,
        sig: &FnSig<'tcx>,
        span: Option<Span>,
    ) {
        // Use lifetimes to determine if we're returning a reference to the
        // argument. In that case we can't switch to pass-by-value as the
        // argument will not live long enough.
        let output_lts = match sig.output().sty {
            TyKind::Ref(output_lt, _, _) => vec![output_lt],
            TyKind::Adt(_, substs) => substs.regions().collect(),
            _ => vec![],
        };

        for (input, &ty) in decl.inputs.iter().zip(sig.inputs()) {
            // All spans generated from a proc-macro invocation are the same...
            match span {
                Some(s) if  s == input.span => return,
                _ => (),
            }

            if_chain! {
                if let TyKind::Ref(input_lt, ty, Mutability::MutImmutable) = ty.sty;
                if !output_lts.contains(&input_lt);
                if is_copy(cx, ty);
                if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
                if size <= self.limit;
                if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.node;
                then {
                    let value_type = if is_self_ty(decl_ty) {
                        "self".into()
                    } else {
                        snippet(cx, decl_ty.span, "_").into()
                    };
                    span_lint_and_sugg(
                        cx,
                        TRIVIALLY_COPY_PASS_BY_REF,
                        input.span,
                        "this argument is passed by reference, but would be more efficient if passed by value",
                        "consider passing by value instead",
                        value_type);
                }
            }
        }
    }

    fn check_trait_items(
        &mut self,
        cx: &LateContext<'_, '_>,
        trait_items: &[TraitItemRef]
    ) {
        for item in trait_items {
            match item.kind {
                AssociatedItemKind::Method{..} => self.check_trait_method(cx, item),
                _ => (),
            }
        }
    }
}

impl LintPass for TriviallyCopyPassByRef {
    fn get_lints(&self) -> LintArray {
        lint_array![TRIVIALLY_COPY_PASS_BY_REF]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro(item.span) {
            return;
        }
        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => self.check_trait_items(cx, trait_items),
            _ => (),
        }
    }

    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        kind: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        _body: &'tcx Body,
        span: Span,
        node_id: NodeId,
    ) {
        if in_macro(span) {
            return;
        }

        match kind {
            FnKind::ItemFn(.., header, _, attrs) => {
                if header.abi != Abi::Rust {
                    return;
                }
                for a in attrs {
                    if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
                        return;
                    }
                }
            },
            FnKind::Method(..) => (),
            _ => return,
        }

        // Exclude non-inherent impls
        if let Some(Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
            if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) |
                ItemKind::Trait(..))
            {
                return;
            }
        }

        let fn_def_id = cx.tcx.hir.local_def_id(node_id);

        let fn_sig = cx.tcx.fn_sig(fn_def_id);
        let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig);

        self.check_poly_fn(cx, decl, &fn_sig, Some(span));
    }
}
<|endoftext|>


<commit_before>use core::borrow::Borrow;
use core::cmp::Ordering;
use core::ops::{Bound, RangeBounds};

use super::node::{marker, ForceResult::*, Handle, NodeRef};

use SearchBound::*;
use SearchResult::*;

pub enum SearchBound<T> {
    /// An inclusive bound to look for, just like `Bound::Included(T)`.
    Included(T),
    /// An exclusive bound to look for, just like `Bound::Excluded(T)`.
    Excluded(T),
    /// An unconditional inclusive bound, just like `Bound::Unbounded`.
    AllIncluded,
    /// An unconditional exclusive bound.
    AllExcluded,
}

impl<T> SearchBound<T> {
    pub fn from_range(range_bound: Bound<T>) -> Self {
        match range_bound {
            Bound::Included(t) => Included(t),
            Bound::Excluded(t) => Excluded(t),
            Bound::Unbounded => AllIncluded,
        }
    }
}

pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
    Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
    GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
}

pub enum IndexResult {
    KV(usize),
    Edge(usize),
}

impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
    /// Looks up a given key in a (sub)tree headed by the node, recursively.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the leaf edge where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_tree<Q: ?Sized>(
        mut self,
        key: &Q,
    ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        loop {
            self = match self.search_node(key) {
                Found(handle) => return Found(handle),
                GoDown(handle) => match handle.force() {
                    Leaf(leaf) => return GoDown(leaf),
                    Internal(internal) => internal.descend(),
                },
            }
        }
    }

    /// Descends to the nearest node where the edge matching the lower bound
    /// of the range is different from the edge matching the upper bound, i.e.,
    /// the nearest node that has at least one key contained in the range.
    ///
    /// If found, returns an `Ok` with that node, the pair of edge indices in it
    /// delimiting the range, and the corresponding pair of bounds for
    /// continuing the search in the child nodes, in case the node is internal.
    ///
    /// If not found, returns an `Err` with the leaf edge matching the entire
    /// range.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
        mut self,
        range: &'r R,
    ) -> Result<
        (
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
            usize,
            usize,
            SearchBound<&'r Q>,
            SearchBound<&'r Q>,
        ),
        Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
    >
    where
        Q: Ord,
        K: Borrow<Q>,
        R: RangeBounds<Q>,
    {
        // WARNING: Inlining these variables would be unsound (#81138)
        // We assume the bounds reported by `range` remain the same, but
        // an adversarial implementation could change between calls
        let (start, end) = (range.start_bound(), range.end_bound());
        match (start, end) {
            (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
                panic!("range start and end are equal and excluded in BTreeMap")
            }
            (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
                if s > e =>
            {
                panic!("range start is greater than range end in BTreeMap")
            }
            _ => {}
        }
        let mut lower_bound = SearchBound::from_range(start);
        let mut upper_bound = SearchBound::from_range(end);
        loop {
            let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
            let (upper_edge_idx, upper_child_bound) = self.find_upper_bound_index(upper_bound);
            if lower_edge_idx > upper_edge_idx {
                panic!("Ord is ill-defined in BTreeMap range")
            }
            if lower_edge_idx < upper_edge_idx {
                return Ok((
                    self,
                    lower_edge_idx,
                    upper_edge_idx,
                    lower_child_bound,
                    upper_child_bound,
                ));
            }
            let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) };
            match common_edge.force() {
                Leaf(common_edge) => return Err(common_edge),
                Internal(common_edge) => {
                    self = common_edge.descend();
                    lower_bound = lower_child_bound;
                    upper_bound = upper_child_bound;
                }
            }
        }
    }

    /// Finds an edge in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn find_lower_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_lower_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }

    /// Clone of `find_lower_bound_edge` for the upper bound.
    pub fn find_upper_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_upper_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }
}

impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
    /// Looks up a given key in the node, without recursion.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the edge where the key might be found
    /// (if the node is internal) or where the key can be inserted.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_node<Q: ?Sized>(self, key: &Q) -> SearchResult<BorrowType, K, V, Type, Type>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        match self.find_key_index(key) {
            IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
            IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }),
        }
    }

    /// Returns either the KV index in the node at which the key (or an equivalent)
    /// exists, or the edge index where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    fn find_key_index<Q: ?Sized>(&self, key: &Q) -> IndexResult
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        let node = self.reborrow();
        let keys = node.keys();
        for (i, k) in keys.iter().enumerate() {
            match key.cmp(k.borrow()) {
                Ordering::Greater => {}
                Ordering::Equal => return IndexResult::KV(i),
                Ordering::Less => return IndexResult::Edge(i),
            }
        }
        IndexResult::Edge(keys.len())
    }

    /// Finds an edge index in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    fn find_lower_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (0, AllIncluded),
            AllExcluded => (self.len(), AllExcluded),
        }
    }

    /// Clone of `find_lower_bound_index` for the upper bound.
    fn find_upper_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (self.len(), AllIncluded),
            AllExcluded => (0, AllExcluded),
        }
    }
}
<commit_msg>Clarify BTree range searching comments<commit_after>use core::borrow::Borrow;
use core::cmp::Ordering;
use core::ops::{Bound, RangeBounds};

use super::node::{marker, ForceResult::*, Handle, NodeRef};

use SearchBound::*;
use SearchResult::*;

pub enum SearchBound<T> {
    /// An inclusive bound to look for, just like `Bound::Included(T)`.
    Included(T),
    /// An exclusive bound to look for, just like `Bound::Excluded(T)`.
    Excluded(T),
    /// An unconditional inclusive bound, just like `Bound::Unbounded`.
    AllIncluded,
    /// An unconditional exclusive bound.
    AllExcluded,
}

impl<T> SearchBound<T> {
    pub fn from_range(range_bound: Bound<T>) -> Self {
        match range_bound {
            Bound::Included(t) => Included(t),
            Bound::Excluded(t) => Excluded(t),
            Bound::Unbounded => AllIncluded,
        }
    }
}

pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
    Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
    GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
}

pub enum IndexResult {
    KV(usize),
    Edge(usize),
}

impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
    /// Looks up a given key in a (sub)tree headed by the node, recursively.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the leaf edge where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_tree<Q: ?Sized>(
        mut self,
        key: &Q,
    ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        loop {
            self = match self.search_node(key) {
                Found(handle) => return Found(handle),
                GoDown(handle) => match handle.force() {
                    Leaf(leaf) => return GoDown(leaf),
                    Internal(internal) => internal.descend(),
                },
            }
        }
    }

    /// Descends to the nearest node where the edge matching the lower bound
    /// of the range is different from the edge matching the upper bound, i.e.,
    /// the nearest node that has at least one key contained in the range.
    ///
    /// If found, returns an `Ok` with that node, the pair of edge indices in it
    /// delimiting the range, and the corresponding pair of bounds for
    /// continuing the search in the child nodes, in case the node is internal.
    ///
    /// If not found, returns an `Err` with the leaf edge matching the entire
    /// range.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
        mut self,
        range: &'r R,
    ) -> Result<
        (
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
            usize,
            usize,
            SearchBound<&'r Q>,
            SearchBound<&'r Q>,
        ),
        Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
    >
    where
        Q: Ord,
        K: Borrow<Q>,
        R: RangeBounds<Q>,
    {
        // It might be unsound to inline these variables if this logic changes (#81138).
        // We assume the bounds reported by `range` remain the same, but
        // an adversarial implementation could change between calls
        let (start, end) = (range.start_bound(), range.end_bound());
        match (start, end) {
            (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
                panic!("range start and end are equal and excluded in BTreeMap")
            }
            (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
                if s > e =>
            {
                panic!("range start is greater than range end in BTreeMap")
            }
            _ => {}
        }
        let mut lower_bound = SearchBound::from_range(start);
        let mut upper_bound = SearchBound::from_range(end);
        loop {
            let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
            let (upper_edge_idx, upper_child_bound) = self.find_upper_bound_index(upper_bound);
            // SAFETY: This panic is used for safety, so external impls can't be called here. The
            // comparison is done with integers for that reason.
            if lower_edge_idx > upper_edge_idx {
                panic!("Ord is ill-defined in BTreeMap range")
            }
            if lower_edge_idx < upper_edge_idx {
                return Ok((
                    self,
                    lower_edge_idx,
                    upper_edge_idx,
                    lower_child_bound,
                    upper_child_bound,
                ));
            }
            let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) };
            match common_edge.force() {
                Leaf(common_edge) => return Err(common_edge),
                Internal(common_edge) => {
                    self = common_edge.descend();
                    lower_bound = lower_child_bound;
                    upper_bound = upper_child_bound;
                }
            }
        }
    }

    /// Finds an edge in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn find_lower_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_lower_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }

    /// Clone of `find_lower_bound_edge` for the upper bound.
    pub fn find_upper_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_upper_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }
}

impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
    /// Looks up a given key in the node, without recursion.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the edge where the key might be found
    /// (if the node is internal) or where the key can be inserted.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_node<Q: ?Sized>(self, key: &Q) -> SearchResult<BorrowType, K, V, Type, Type>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        match self.find_key_index(key) {
            IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
            IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }),
        }
    }

    /// Returns either the KV index in the node at which the key (or an equivalent)
    /// exists, or the edge index where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    fn find_key_index<Q: ?Sized>(&self, key: &Q) -> IndexResult
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        let node = self.reborrow();
        let keys = node.keys();
        for (i, k) in keys.iter().enumerate() {
            match key.cmp(k.borrow()) {
                Ordering::Greater => {}
                Ordering::Equal => return IndexResult::KV(i),
                Ordering::Less => return IndexResult::Edge(i),
            }
        }
        IndexResult::Edge(keys.len())
    }

    /// Finds an edge index in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    fn find_lower_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (0, AllIncluded),
            AllExcluded => (self.len(), AllExcluded),
        }
    }

    /// Clone of `find_lower_bound_index` for the upper bound.
    fn find_upper_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (self.len(), AllIncluded),
            AllExcluded => (0, AllExcluded),
        }
    }
}
<|endoftext|>


<commit_before>use gl;
use std;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::ops::Drop;

#[derive(Debug)]
pub enum ShaderType {
    Vertex,
    Fragment,
    Geometry,
    Compute
}

#[derive(Debug, Default)]
pub struct Shader {
    source_file: String,
    gl_handle: u32,
    shader_type: ShaderType,
}

#[derive(Debug, Default)]
pub struct ShaderProgram {
    gl_handle: u32
}

impl ShaderProgram {
    pub fn new() -> ShaderProgram {
        ShaderProgram {
            gl_handle: unsafe{ gl::CreateProgram() }
        }
    }

    pub fn attach_shader(&mut self, shader: &Shader) {
        unsafe {
            let t = get_gl_shader_type(&shader.shader_type);
            println!("Attaching shader of type {}, handle:{} to program {}",
                t, shader.gl_handle, self.gl_handle);
            gl::AttachShader(self.gl_handle, shader.gl_handle);
        }
    }

    pub fn link(&self) {
        unsafe {
            gl::LinkProgram(self.gl_handle);

            let mut success = gl::FALSE as gl::types::GLint;
            gl::GetProgramiv(self.gl_handle, gl::LINK_STATUS, &mut success);
            if success != gl::TRUE as gl::types::GLint {
                let mut info_log = String::with_capacity(256);
                let mut error_size = 0i32;
                gl::GetShaderInfoLog(self.gl_handle, 512, &mut error_size, info_log.as_ptr() as _);
                println!("Error link failed with error: {:?} for: {:?}",
                    info_log, self.gl_handle);
                panic!();
            }
            else {
                println!("Linked successfully {}", self.gl_handle);
            }
        }
    }

    pub fn start_use(&self) {
        unsafe {
            gl::UseProgram(self.gl_handle);
        }
    }

    pub fn stop_use(&self) {
        unsafe { gl::UseProgram(0); }
    }

    pub fn set_uniform4f(&self, name: &str, values: &[f32; 4]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform4f(location, values[0], values[1], values[2], values[3]);
        }
    }

    pub fn set_uniform_matrix4(&self, name: &str, values: &[f32; 16]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::UniformMatrix4fv(location, 1, gl::FALSE, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_3fv(&self, name: &str, count: i32, values: &[f32]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform3fv(location, count, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_1fv(&self, name: &str, count: i32, values: &[f32]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1fv(location, count, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_1i(&self, name: &str, value: i32) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1i(location, value);
        }
    }

    pub fn set_uniform_1f(&self, name: &str, value: f32) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1f(location, value);
        }
    }

    fn get_uniform_location(&self, name: &str) -> i32 {
        unsafe {
            let c_name = std::ffi::CString::new(name).unwrap();
            gl::GetUniformLocation(self.gl_handle, c_name.as_ptr())
        }
    }
}

impl Shader {
    pub fn new (shader_type: ShaderType, source_file: &str) -> Shader {
        Shader {
            source_file: source_file.to_string(),
            gl_handle: 0,
            shader_type: shader_type,
        }
    }

    pub fn compile(&mut self) {
        unsafe {
            let shader_type = get_gl_shader_type(&self.shader_type);
            println!("Creating shader of type: {} Vtx={} Fragment={}", shader_type, gl::VERTEX_SHADER, gl::FRAGMENT_SHADER);
            self.gl_handle = gl::CreateShader(shader_type);

            let file_buf = self.read_shader_file();

            let shader_str = CString::new(file_buf).unwrap();
            gl::ShaderSource(self.gl_handle, 1, &shader_str.as_ptr(), std::ptr::null());

            gl::CompileShader(self.gl_handle);

            let mut success = gl::FALSE as gl::types::GLint;
            gl::GetShaderiv(self.gl_handle, gl::COMPILE_STATUS, &mut success);
            if success != gl::TRUE as gl::types::GLint {
                let info_log = String::with_capacity(256);
                let mut error_size = 0i32;
                gl::GetShaderInfoLog(self.gl_handle, 512, &mut error_size, info_log.as_ptr() as _);
                println!("Error compile failed with error: {:?} for: {:?}",
                    info_log, self.gl_handle);
                panic!();
            }
        }
    }

    fn read_shader_file(&self) -> Vec<u8> {
        let mut file = File::open(&self.source_file)
            .expect("ERROR: Shader file not found!");

        let mut file_buf = Vec::new();
        file.read_to_end(&mut file_buf).unwrap();

        file_buf
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_handle);
        }
    }
}

fn get_gl_shader_type(shader_type: &ShaderType) -> gl::types::GLenum {
    match *shader_type {
        ShaderType::Vertex => gl::VERTEX_SHADER,
        ShaderType::Fragment => gl::FRAGMENT_SHADER,
        ShaderType::Geometry => gl::GEOMETRY_SHADER,
        ShaderType::Compute => gl::COMPUTE_SHADER,
    }
}

impl Default for ShaderType {
    fn default() -> Self {
        ShaderType::Vertex
    }
}<commit_msg>More warnings<commit_after>use gl;
use std;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::ops::Drop;

#[derive(Debug)]
pub enum ShaderType {
    Vertex,
    Fragment,
    Geometry,
    Compute
}

#[derive(Debug, Default)]
pub struct Shader {
    source_file: String,
    gl_handle: u32,
    shader_type: ShaderType,
}

#[derive(Debug, Default)]
pub struct ShaderProgram {
    gl_handle: u32
}

impl ShaderProgram {
    pub fn new() -> ShaderProgram {
        ShaderProgram {
            gl_handle: unsafe{ gl::CreateProgram() }
        }
    }

    pub fn attach_shader(&mut self, shader: &Shader) {
        unsafe {
            let t = get_gl_shader_type(&shader.shader_type);
            println!("Attaching shader of type {}, handle:{} to program {}",
                t, shader.gl_handle, self.gl_handle);
            gl::AttachShader(self.gl_handle, shader.gl_handle);
        }
    }

    pub fn link(&self) {
        unsafe {
            gl::LinkProgram(self.gl_handle);

            let mut success = gl::FALSE as gl::types::GLint;
            gl::GetProgramiv(self.gl_handle, gl::LINK_STATUS, &mut success);
            if success != gl::TRUE as gl::types::GLint {
                let info_log = String::with_capacity(256);
                let mut error_size = 0i32;
                gl::GetShaderInfoLog(self.gl_handle, 512, &mut error_size, info_log.as_ptr() as _);
                println!("Error link failed with error: {:?} for: {:?}",
                    info_log, self.gl_handle);
                panic!();
            }
            else {
                println!("Linked successfully {}", self.gl_handle);
            }
        }
    }

    pub fn start_use(&self) {
        unsafe {
            gl::UseProgram(self.gl_handle);
        }
    }

    pub fn stop_use(&self) {
        unsafe { gl::UseProgram(0); }
    }

    pub fn set_uniform4f(&self, name: &str, values: &[f32; 4]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform4f(location, values[0], values[1], values[2], values[3]);
        }
    }

    pub fn set_uniform_matrix4(&self, name: &str, values: &[f32; 16]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::UniformMatrix4fv(location, 1, gl::FALSE, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_3fv(&self, name: &str, count: i32, values: &[f32]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform3fv(location, count, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_1fv(&self, name: &str, count: i32, values: &[f32]) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1fv(location, count, values.as_ptr() as *const _);
        }
    }

    pub fn set_uniform_1i(&self, name: &str, value: i32) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1i(location, value);
        }
    }

    pub fn set_uniform_1f(&self, name: &str, value: f32) {
        let location = self.get_uniform_location(name);
        unsafe {
            gl::Uniform1f(location, value);
        }
    }

    fn get_uniform_location(&self, name: &str) -> i32 {
        unsafe {
            let c_name = std::ffi::CString::new(name).unwrap();
            gl::GetUniformLocation(self.gl_handle, c_name.as_ptr())
        }
    }
}

impl Shader {
    pub fn new (shader_type: ShaderType, source_file: &str) -> Shader {
        Shader {
            source_file: source_file.to_string(),
            gl_handle: 0,
            shader_type: shader_type,
        }
    }

    pub fn compile(&mut self) {
        unsafe {
            let shader_type = get_gl_shader_type(&self.shader_type);
            println!("Creating shader of type: {} Vtx={} Fragment={}", shader_type, gl::VERTEX_SHADER, gl::FRAGMENT_SHADER);
            self.gl_handle = gl::CreateShader(shader_type);

            let file_buf = self.read_shader_file();

            let shader_str = CString::new(file_buf).unwrap();
            gl::ShaderSource(self.gl_handle, 1, &shader_str.as_ptr(), std::ptr::null());

            gl::CompileShader(self.gl_handle);

            let mut success = gl::FALSE as gl::types::GLint;
            gl::GetShaderiv(self.gl_handle, gl::COMPILE_STATUS, &mut success);
            if success != gl::TRUE as gl::types::GLint {
                let info_log = String::with_capacity(256);
                let mut error_size = 0i32;
                gl::GetShaderInfoLog(self.gl_handle, 512, &mut error_size, info_log.as_ptr() as _);
                println!("Error compile failed with error: {:?} for: {:?}",
                    info_log, self.gl_handle);
                panic!();
            }
        }
    }

    fn read_shader_file(&self) -> Vec<u8> {
        let mut file = File::open(&self.source_file)
            .expect("ERROR: Shader file not found!");

        let mut file_buf = Vec::new();
        file.read_to_end(&mut file_buf).unwrap();

        file_buf
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_handle);
        }
    }
}

fn get_gl_shader_type(shader_type: &ShaderType) -> gl::types::GLenum {
    match *shader_type {
        ShaderType::Vertex => gl::VERTEX_SHADER,
        ShaderType::Fragment => gl::FRAGMENT_SHADER,
        ShaderType::Geometry => gl::GEOMETRY_SHADER,
        ShaderType::Compute => gl::COMPUTE_SHADER,
    }
}

impl Default for ShaderType {
    fn default() -> Self {
        ShaderType::Vertex
    }
}<|endoftext|>


<commit_before>#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]
extern crate phf_shared;
extern crate rand;

use phf_shared::PhfHash;
use rand::{SeedableRng, XorShiftRng, Rng};

const DEFAULT_LAMBDA: usize = 5;

const FIXED_SEED: [u32; 4] = [3141592653, 589793238, 462643383, 2795028841];

pub struct HashState {
    pub key: u64,
    pub disps: Vec<(u32, u32)>,
    pub map: Vec<usize>,
}

pub fn generate_hash<H: PhfHash>(entries: &[H]) -> HashState {
    let mut rng: XorShiftRng = SeedableRng::from_seed(FIXED_SEED);
    loop {
        if let Some(s) = try_generate_hash(entries, &mut rng) {
            return s;
        }
    }
}

fn try_generate_hash<H: PhfHash>(entries: &[H], rng: &mut XorShiftRng) -> Option<HashState> {
    struct Bucket {
        idx: usize,
        keys: Vec<usize>,
    }

    struct Hashes {
        g: u32,
        f1: u32,
        f2: u32,
    }

    let key = rng.gen();

    let hashes: Vec<_> = entries.iter().map(|entry| {
        let (g, f1, f2) = entry.phf_hash(key);
        Hashes {
            g: g,
            f1: f1,
            f2: f2
        }
    }).collect();

    let buckets_len = (entries.len() + DEFAULT_LAMBDA - 1) / DEFAULT_LAMBDA;
    let mut buckets = (0..buckets_len)
        .map(|i| Bucket { idx: i, keys: vec![] })
        .collect::<Vec<_>>();

    for (i, hash) in hashes.iter().enumerate() {
        buckets[(hash.g % (buckets_len as u32)) as usize].keys.push(i);
    }

    // Sort descending
    buckets.sort_by(|a, b| a.keys.len().cmp(&b.keys.len()).reverse());

    let table_len = entries.len();
    let mut map = vec![None; table_len];
    let mut disps = vec![(0u32, 0u32); buckets_len];

    // store whether an element from the bucket being placed is
    // located at a certain position, to allow for efficient overlap
    // checks. It works by storing the generation in each cell and
    // each new placement-attempt is a new generation, so you can tell
    // if this is legitimately full by checking that the generations
    // are equal. (A u64 is far too large to overflow in a reasonable
    // time for current hardware.)
    let mut try_map = vec![0u64; table_len];
    let mut generation = 0u64;

    // the actual values corresponding to the markers above, as
    // (index, key) pairs, for adding to the main map once we've
    // chosen the right disps.
    let mut values_to_add = vec![];

    'buckets: for bucket in buckets.iter() {
        for d1 in 0..(table_len as u32) {
            'disps: for d2 in 0..(table_len as u32) {
                values_to_add.clear();
                generation += 1;

                for &key in bucket.keys.iter() {
                    let idx = (phf_shared::displace(hashes[key].f1, hashes[key].f2, d1, d2)
                                % (table_len as u32)) as usize;
                    if map[idx].is_some() || try_map[idx] == generation {
                        continue 'disps;
                    }
                    try_map[idx] = generation;
                    values_to_add.push((idx, key));
                }

                // We've picked a good set of disps
                disps[bucket.idx] = (d1, d2);
                for &(idx, key) in values_to_add.iter() {
                    map[idx] = Some(key);
                }
                continue 'buckets;
            }
        }

        // Unable to find displacements for a bucket
        return None;
    }

    Some(HashState {
        key: key,
        disps: disps,
        map: map.into_iter().map(|i| i.unwrap()).collect(),
    })
}

<commit_msg>Minor generator cleanup<commit_after>#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]
extern crate phf_shared;
extern crate rand;

use phf_shared::PhfHash;
use rand::{SeedableRng, XorShiftRng, Rng};

const DEFAULT_LAMBDA: usize = 5;

const FIXED_SEED: [u32; 4] = [3141592653, 589793238, 462643383, 2795028841];

pub struct HashState {
    pub key: u64,
    pub disps: Vec<(u32, u32)>,
    pub map: Vec<usize>,
}

pub fn generate_hash<H: PhfHash>(entries: &[H]) -> HashState {
    let mut rng = XorShiftRng::from_seed(FIXED_SEED);
    loop {
        if let Some(s) = try_generate_hash(entries, &mut rng) {
            return s;
        }
    }
}

fn try_generate_hash<H: PhfHash>(entries: &[H], rng: &mut XorShiftRng) -> Option<HashState> {
    struct Bucket {
        idx: usize,
        keys: Vec<usize>,
    }

    struct Hashes {
        g: u32,
        f1: u32,
        f2: u32,
    }

    let key = rng.gen();

    let hashes: Vec<_> = entries.iter().map(|entry| {
        let (g, f1, f2) = entry.phf_hash(key);
        Hashes {
            g: g,
            f1: f1,
            f2: f2
        }
    }).collect();

    let buckets_len = (entries.len() + DEFAULT_LAMBDA - 1) / DEFAULT_LAMBDA;
    let mut buckets = (0..buckets_len)
        .map(|i| Bucket { idx: i, keys: vec![] })
        .collect::<Vec<_>>();

    for (i, hash) in hashes.iter().enumerate() {
        buckets[(hash.g % (buckets_len as u32)) as usize].keys.push(i);
    }

    // Sort descending
    buckets.sort_by(|a, b| a.keys.len().cmp(&b.keys.len()).reverse());

    let table_len = entries.len();
    let mut map = vec![None; table_len];
    let mut disps = vec![(0u32, 0u32); buckets_len];

    // store whether an element from the bucket being placed is
    // located at a certain position, to allow for efficient overlap
    // checks. It works by storing the generation in each cell and
    // each new placement-attempt is a new generation, so you can tell
    // if this is legitimately full by checking that the generations
    // are equal. (A u64 is far too large to overflow in a reasonable
    // time for current hardware.)
    let mut try_map = vec![0u64; table_len];
    let mut generation = 0u64;

    // the actual values corresponding to the markers above, as
    // (index, key) pairs, for adding to the main map once we've
    // chosen the right disps.
    let mut values_to_add = vec![];

    'buckets: for bucket in &buckets {
        for d1 in 0..(table_len as u32) {
            'disps: for d2 in 0..(table_len as u32) {
                values_to_add.clear();
                generation += 1;

                for &key in &bucket.keys {
                    let idx = (phf_shared::displace(hashes[key].f1, hashes[key].f2, d1, d2)
                               % (table_len as u32)) as usize;
                    if map[idx].is_some() || try_map[idx] == generation {
                        continue 'disps;
                    }
                    try_map[idx] = generation;
                    values_to_add.push((idx, key));
                }

                // We've picked a good set of disps
                disps[bucket.idx] = (d1, d2);
                for &(idx, key) in &values_to_add {
                    map[idx] = Some(key);
                }
                continue 'buckets;
            }
        }

        // Unable to find displacements for a bucket
        return None;
    }

    Some(HashState {
        key: key,
        disps: disps,
        map: map.into_iter().map(|i| i.unwrap()).collect(),
    })
}

<|endoftext|>


<commit_before>fn filter_sequence(l: Vec<u32>) -> Vec<u32> {
    let length = l.len();
    let mut re: Vec<u32> = vec![];
    for i in (1..length - 1).step_by(2) {
        re.push(l[i]);
    }
    re
}

fn main() {
    println!("{:?}", filter_sequence(vec![1, 2, 3, 4, 5, 6, 7]));
}
<commit_msg>a bit<commit_after>fn filter_sequence(l: Vec<u32>) -> Vec<u32> {
    let length = l.len();
    let mut re: Vec<u32> = vec![];
    for i in (1..length - 1).step_by(2) {
        re.push(l[i]);
    }
    re
}

fn last_remaining(n: u32) -> u32 {
    let a: Vec<u32> = (1..n).collect();
    fn temp_func(ll: Vec<u32>) -> u32 {
        if ll.len() != 1 {
            let mut temp = filter_sequence(ll);
            temp.reverse();
            temp_func(temp)
        } else {
            *ll.first().unwrap()
        }
    }
    temp_func(a)
}

fn main() {
    //println!("{:?}", filter_sequence(vec![1, 2, 3, 4, 5, 6, 7]));
    println!("{:?}", last_remaining(10));
}
<|endoftext|>


<commit_before>//! Common types for [encryption] related tasks.
//!
//! [encryption]: https://spec.matrix.org/v1.2/client-server-api/#end-to-end-encryption

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use crate::{
    serde::{Base64, StringEnum},
    DeviceId, DeviceKeyId, EventEncryptionAlgorithm, PrivOwnedStr, UserId,
};

/// Identity keys for a device.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct DeviceKeys {
    /// The ID of the user the device belongs to.
    ///
    /// Must match the user ID used when logging in.
    pub user_id: Box<UserId>,

    /// The ID of the device these keys belong to.
    ///
    /// Must match the device ID used when logging in.
    pub device_id: Box<DeviceId>,

    /// The encryption algorithms supported by this device.
    pub algorithms: Vec<EventEncryptionAlgorithm>,

    /// Public identity keys.
    pub keys: BTreeMap<Box<DeviceKeyId>, String>,

    /// Signatures for the device key object.
    pub signatures: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>,

    /// Additional data added to the device key information by intermediate servers, and
    /// not covered by the signatures.
    #[serde(default, skip_serializing_if = "UnsignedDeviceInfo::is_empty")]
    pub unsigned: UnsignedDeviceInfo,
}

impl DeviceKeys {
    /// Creates a new `DeviceKeys` from the given user id, device id, algorithms, keys and
    /// signatures.
    pub fn new(
        user_id: Box<UserId>,
        device_id: Box<DeviceId>,
        algorithms: Vec<EventEncryptionAlgorithm>,
        keys: BTreeMap<Box<DeviceKeyId>, String>,
        signatures: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>,
    ) -> Self {
        Self { user_id, device_id, algorithms, keys, signatures, unsigned: Default::default() }
    }
}

/// Additional data added to device key information by intermediate servers.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct UnsignedDeviceInfo {
    /// The display name which the user set on the device.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub device_display_name: Option<String>,
}

impl UnsignedDeviceInfo {
    /// Creates an empty `UnsignedDeviceInfo`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Checks whether all fields are empty / `None`.
    pub fn is_empty(&self) -> bool {
        self.device_display_name.is_none()
    }
}

/// Signatures for a `SignedKey` object.
pub type SignedKeySignatures = BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>;

/// A key for the SignedCurve25519 algorithm
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct SignedKey {
    /// Base64-encoded 32-byte Curve25519 public key.
    pub key: Base64,

    /// Signatures for the key object.
    pub signatures: SignedKeySignatures,

    /// Is this key considered to be a fallback key, defaults to false.
    #[serde(default, skip_serializing_if = "crate::serde::is_default")]
    pub fallback: bool,
}

impl SignedKey {
    /// Creates a new `SignedKey` with the given key and signatures.
    pub fn new(key: Base64, signatures: SignedKeySignatures) -> Self {
        Self { key, signatures, fallback: false }
    }

    /// Creates a new fallback `SignedKey` with the given key and signatures.
    pub fn new_fallback(key: Base64, signatures: SignedKeySignatures) -> Self {
        Self { key, signatures, fallback: true }
    }
}

/// A one-time public key for "pre-key" messages.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum OneTimeKey {
    /// A key containing signatures, for the SignedCurve25519 algorithm.
    SignedKey(SignedKey),

    /// A string-valued key, for the Ed25519 and Curve25519 algorithms.
    Key(String),
}

/// Signatures for a `CrossSigningKey` object.
pub type CrossSigningKeySignatures = BTreeMap<Box<UserId>, BTreeMap<String, String>>;

/// A cross signing key.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct CrossSigningKey {
    /// The ID of the user the key belongs to.
    pub user_id: Box<UserId>,

    /// What the key is used for.
    pub usage: Vec<KeyUsage>,

    /// The public key.
    ///
    /// The object must have exactly one property.
    pub keys: BTreeMap<String, String>,

    /// Signatures of the key.
    ///
    /// Only optional for master key.
    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
    pub signatures: CrossSigningKeySignatures,
}

impl CrossSigningKey {
    /// Creates a new `CrossSigningKey` with the given user ID, usage, keys and signatures.
    pub fn new(
        user_id: Box<UserId>,
        usage: Vec<KeyUsage>,
        keys: BTreeMap<String, String>,
        signatures: CrossSigningKeySignatures,
    ) -> Self {
        Self { user_id, usage, keys, signatures }
    }
}

/// The usage of a cross signing key.
#[derive(Clone, Debug, StringEnum)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_enum(rename_all = "snake_case")]
pub enum KeyUsage {
    /// Master key.
    Master,

    /// Self-signing key.
    SelfSigning,

    /// User-signing key.
    UserSigning,

    #[doc(hidden)]
    _Custom(PrivOwnedStr),
}
<commit_msg>common: Use DeviceKeyId in more places for the CrossSigningKey type<commit_after>//! Common types for [encryption] related tasks.
//!
//! [encryption]: https://spec.matrix.org/v1.2/client-server-api/#end-to-end-encryption

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use crate::{
    serde::{Base64, StringEnum},
    DeviceId, DeviceKeyId, EventEncryptionAlgorithm, PrivOwnedStr, UserId,
};

/// Identity keys for a device.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct DeviceKeys {
    /// The ID of the user the device belongs to.
    ///
    /// Must match the user ID used when logging in.
    pub user_id: Box<UserId>,

    /// The ID of the device these keys belong to.
    ///
    /// Must match the device ID used when logging in.
    pub device_id: Box<DeviceId>,

    /// The encryption algorithms supported by this device.
    pub algorithms: Vec<EventEncryptionAlgorithm>,

    /// Public identity keys.
    pub keys: BTreeMap<Box<DeviceKeyId>, String>,

    /// Signatures for the device key object.
    pub signatures: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>,

    /// Additional data added to the device key information by intermediate servers, and
    /// not covered by the signatures.
    #[serde(default, skip_serializing_if = "UnsignedDeviceInfo::is_empty")]
    pub unsigned: UnsignedDeviceInfo,
}

impl DeviceKeys {
    /// Creates a new `DeviceKeys` from the given user id, device id, algorithms, keys and
    /// signatures.
    pub fn new(
        user_id: Box<UserId>,
        device_id: Box<DeviceId>,
        algorithms: Vec<EventEncryptionAlgorithm>,
        keys: BTreeMap<Box<DeviceKeyId>, String>,
        signatures: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>,
    ) -> Self {
        Self { user_id, device_id, algorithms, keys, signatures, unsigned: Default::default() }
    }
}

/// Additional data added to device key information by intermediate servers.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct UnsignedDeviceInfo {
    /// The display name which the user set on the device.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub device_display_name: Option<String>,
}

impl UnsignedDeviceInfo {
    /// Creates an empty `UnsignedDeviceInfo`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Checks whether all fields are empty / `None`.
    pub fn is_empty(&self) -> bool {
        self.device_display_name.is_none()
    }
}

/// Signatures for a `SignedKey` object.
pub type SignedKeySignatures = BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>;

/// A key for the SignedCurve25519 algorithm
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct SignedKey {
    /// Base64-encoded 32-byte Curve25519 public key.
    pub key: Base64,

    /// Signatures for the key object.
    pub signatures: SignedKeySignatures,

    /// Is this key considered to be a fallback key, defaults to false.
    #[serde(default, skip_serializing_if = "crate::serde::is_default")]
    pub fallback: bool,
}

impl SignedKey {
    /// Creates a new `SignedKey` with the given key and signatures.
    pub fn new(key: Base64, signatures: SignedKeySignatures) -> Self {
        Self { key, signatures, fallback: false }
    }

    /// Creates a new fallback `SignedKey` with the given key and signatures.
    pub fn new_fallback(key: Base64, signatures: SignedKeySignatures) -> Self {
        Self { key, signatures, fallback: true }
    }
}

/// A one-time public key for "pre-key" messages.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum OneTimeKey {
    /// A key containing signatures, for the SignedCurve25519 algorithm.
    SignedKey(SignedKey),

    /// A string-valued key, for the Ed25519 and Curve25519 algorithms.
    Key(String),
}

/// Signatures for a `CrossSigningKey` object.
pub type CrossSigningKeySignatures = BTreeMap<Box<UserId>, BTreeMap<Box<DeviceKeyId>, String>>;

/// A cross signing key.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct CrossSigningKey {
    /// The ID of the user the key belongs to.
    pub user_id: Box<UserId>,

    /// What the key is used for.
    pub usage: Vec<KeyUsage>,

    /// The public key.
    ///
    /// The object must have exactly one property.
    pub keys: BTreeMap<Box<DeviceKeyId>, String>,

    /// Signatures of the key.
    ///
    /// Only optional for master key.
    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
    pub signatures: CrossSigningKeySignatures,
}

impl CrossSigningKey {
    /// Creates a new `CrossSigningKey` with the given user ID, usage, keys and signatures.
    pub fn new(
        user_id: Box<UserId>,
        usage: Vec<KeyUsage>,
        keys: BTreeMap<Box<DeviceKeyId>, String>,
        signatures: CrossSigningKeySignatures,
    ) -> Self {
        Self { user_id, usage, keys, signatures }
    }
}

/// The usage of a cross signing key.
#[derive(Clone, Debug, StringEnum)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_enum(rename_all = "snake_case")]
pub enum KeyUsage {
    /// Master key.
    Master,

    /// Self-signing key.
    SelfSigning,

    /// User-signing key.
    UserSigning,

    #[doc(hidden)]
    _Custom(PrivOwnedStr),
}
<|endoftext|>