<commit_before>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::cmp;
use std::io::{self, Cursor, Error, ErrorKind, Read, Write};

use super::icontype::{Encoding, IconType, OSType};
use super::image::{Image, PixelFormat};

/// The length of an icon element header, in bytes:
const ICON_ELEMENT_HEADER_LENGTH: u32 = 8;

/// The first twelve bytes of a JPEG 2000 file are always this:
const JPEG_2000_FILE_MAGIC_NUMBER: [u8; 12] = [0x00, 0x00, 0x00, 0x0C, 0x6A,
                                               0x50, 0x20, 0x20, 0x0D, 0x0A,
                                               0x87, 0x0A];

/// One entry in an ICNS file.  Depending on the resource type, this may
/// represent an icon, or part of an icon (such as an alpha mask, or color
/// data without the mask).
pub struct IconElement {
    ostype: OSType,
    data: Vec<u8>,
}

impl IconElement {
    /// Creates an icon element with the given OSType and data payload.
    pub fn new(ostype: OSType, data: Vec<u8>) -> IconElement {
        IconElement {
            ostype: ostype,
            data: data,
        }
    }

    /// Creates an icon element that encodes the given image as the given icon
    /// type.  Returns an error if the image has the wrong dimensions for that
    /// icon type.
    pub fn encode_image_with_type(image: &Image,
                                  icon_type: IconType)
                                  -> io::Result<IconElement> {
        let width = icon_type.pixel_width();
        let height = icon_type.pixel_height();
        if image.width() != width || image.height() != height {
            let msg = format!("image has wrong dimensions for {:?} ({}x{} \
                               instead of {}x{}))",
                              icon_type,
                              image.width(),
                              image.height(),
                              width,
                              height);
            return Err(Error::new(ErrorKind::InvalidInput, msg));
        }
        let mut data: Vec<u8>;
        match icon_type.encoding() {
            Encoding::JP2PNG => {
                data = Vec::new();
                try!(image.write_png(&mut data));
            }
            Encoding::RLE24 => {
                let num_pixels = (width * height) as usize;
                match image.pixel_format() {
                    PixelFormat::RGBA => {
                        data = encode_rle(image.data(), 4, num_pixels);
                    }
                    PixelFormat::RGB => {
                        data = encode_rle(image.data(), 3, num_pixels);
                    }
                    // Convert to RGB if the image isn't already RGB or RGBA.
                    _ => {
                        let image = image.convert_to(PixelFormat::RGB);
                        data = encode_rle(image.data(), 3, num_pixels);
                    }
                }
            }
            Encoding::Mask8 => {
                // Convert to Alpha format unconditionally -- if the image is
                // already Alpha format, this will simply clone its data array,
                // which we'd need to do anyway.
                let image = image.convert_to(PixelFormat::Alpha);
                data = image.into_data().into_vec();
            }
        }
        Ok(IconElement::new(icon_type.ostype(), data))
    }

    /// Decodes the icon element into an image.  Returns an error if this
    /// element does not represent an icon type supported by this library, or
    /// if the data is malformed.
    pub fn decode_image(&self) -> io::Result<Image> {
        let icon_type = try!(self.icon_type().ok_or_else(|| {
            Error::new(ErrorKind::InvalidInput,
                       format!("unsupported OSType: {}", self.ostype()))
        }));
        let width = icon_type.pixel_width();
        let height = icon_type.pixel_width();
        match icon_type.encoding() {
            Encoding::JP2PNG => {
                if self.data.starts_with(&JPEG_2000_FILE_MAGIC_NUMBER) {
                    let msg = "element to be decoded contains JPEG 2000 \
                               data, which is not yet supported";
                    return Err(Error::new(ErrorKind::InvalidInput, msg));
                }
                let image = try!(Image::read_png(Cursor::new(&self.data)));
                if image.width() != width || image.height() != height {
                    let msg = format!("decoded PNG has wrong dimensions \
                                       ({}x{} instead of {}x{})",
                                      image.width(),
                                      image.height(),
                                      width,
                                      height);
                    return Err(Error::new(ErrorKind::InvalidData, msg));
                }
                Ok(image)
            }
            Encoding::RLE24 => {
                let mut image = Image::new(PixelFormat::RGB, width, height);
                try!(decode_rle(&self.data, image.data_mut()));
                Ok(image)
            }
            Encoding::Mask8 => {
                let num_pixels = width * height;
                if self.data.len() as u32 != num_pixels {
                    let msg = format!("wrong data payload length ({} \
                                       instead of {})",
                                      self.data.len(),
                                      num_pixels);
                    return Err(Error::new(ErrorKind::InvalidData, msg));
                }
                let mut image = Image::new(PixelFormat::Alpha, width, height);
                image.data_mut().clone_from_slice(&self.data);
                Ok(image)
            }
        }
    }

    /// Returns the OSType for this element (e.g. `it32` or `t8mk`).
    pub fn ostype(&self) -> OSType {
        self.ostype
    }

    /// Returns the type of icon encoded by this element, or `None` if this
    /// element does not encode a supported icon type.
    pub fn icon_type(&self) -> Option<IconType> {
        IconType::from_ostype(self.ostype)
    }

    /// Returns the encoded data for this element.
    pub fn data(&self) -> &[u8] {
        &self.data
    }

    /// Returns the encoded length of the element, in bytes, including the
    /// length of the header.
    pub fn total_length(&self) -> u32 {
        ICON_ELEMENT_HEADER_LENGTH + (self.data.len() as u32)
    }

    /// Reads an icon element from within an ICNS file.
    pub fn read<R: Read>(mut reader: R) -> io::Result<IconElement> {
        let mut raw_ostype = [0u8; 4];
        try!(reader.read_exact(&mut raw_ostype));
        let element_length = try!(reader.read_u32::<BigEndian>());
        if element_length < ICON_ELEMENT_HEADER_LENGTH {
            return Err(Error::new(ErrorKind::InvalidData,
                                  "invalid element length"));
        }
        let data_length = element_length - ICON_ELEMENT_HEADER_LENGTH;
        let mut data = vec![0u8; data_length as usize];
        try!(reader.read_exact(&mut data));
        Ok(IconElement::new(OSType(raw_ostype), data))
    }

    /// Writes the icon element to within an ICNS file.
    pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
        let OSType(ref raw_ostype) = self.ostype;
        try!(writer.write_all(raw_ostype));
        try!(writer.write_u32::<BigEndian>(self.total_length()));
        try!(writer.write_all(&self.data));
        Ok(())
    }
}

fn encode_rle(input: &[u8],
              num_input_channels: usize,
              num_pixels: usize)
              -> Vec<u8> {
    assert!(num_input_channels == 3 || num_input_channels == 4);
    let mut output = Vec::with_capacity(num_pixels);
    for channel in 0..3 {
        let mut pixel: usize = 0;
        let mut literal_start: usize = 0;
        while pixel < num_pixels {
            let value = input[num_input_channels * pixel + channel];
            let mut run_length = 1;
            while pixel + run_length < num_pixels &&
                  input[num_input_channels * (pixel + run_length) +
                        channel] == value &&
                  run_length < 130 {
                run_length += 1;
            }
            if run_length >= 3 {
                while literal_start < pixel {
                    let literal_length = cmp::min(256, pixel - literal_start);
                    output.push((literal_length - 1) as u8);
                    for i in 0..literal_length {
                        output.push(input[num_input_channels *
                                          (literal_start + i) +
                                          channel]);
                    }
                    literal_start += literal_length;
                }
                output.push((run_length + 125) as u8);
                output.push(value);
                pixel += run_length;
                literal_start = pixel;
            } else {
                pixel += run_length;
            }
        }
        while literal_start < pixel {
            let literal_length = cmp::min(256, pixel - literal_start);
            output.push((literal_length - 1) as u8);
            for i in 0..literal_length {
                output.push(input[num_input_channels * (literal_start + i) +
                                  channel]);
            }
            literal_start += literal_length;
        }
    }
    output
}

fn decode_rle(input: &[u8], output: &mut [u8]) -> io::Result<()> {
    assert_eq!(output.len() % 3, 0);
    let num_pixels = output.len() / 3;
    let mut iter = input.iter();
    let mut remaining: usize = 0;
    let mut within_run = false;
    let mut run_value: u8 = 0;
    for channel in 0..3 {
        for pixel in 0..num_pixels {
            if remaining == 0 {
                let next: u8 = *try!(iter.next().ok_or_else(rle_error));
                if next < 128 {
                    remaining = (next as usize) + 1;
                    within_run = false;
                } else {
                    remaining = (next as usize) - 125;
                    within_run = true;
                    run_value = *try!(iter.next().ok_or_else(rle_error));
                }
            }
            output[3 * pixel + channel] = if within_run {
                run_value
            } else {
                *try!(iter.next().ok_or_else(rle_error))
            };
            remaining -= 1;
        }
        if remaining != 0 {
            return Err(rle_error());
        }
    }
    if iter.next().is_some() {
        Err(rle_error())
    } else {
        Ok(())
    }
}

fn rle_error() -> Error {
    Error::new(ErrorKind::InvalidData, "invalid RLE-compressed data")
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::icontype::{IconType, OSType};
    use super::super::image::{Image, PixelFormat};

    #[test]
    fn encode_rle() {
        let mut image = Image::new(PixelFormat::Gray, 16, 16);
        image.data_mut()[0] = 44;
        image.data_mut()[1] = 55;
        image.data_mut()[2] = 66;
        image.data_mut()[3] = 66;
        image.data_mut()[4] = 66;
        let element =
            IconElement::encode_image_with_type(&image, IconType::RGB24_16x16)
                .expect("failed to encode image");
        assert_eq!(element.ostype(), OSType(*b"is32"));
        assert_eq!(element.data()[0..5], [1, 44, 55, 128, 66]);
    }

    #[test]
    fn decode_rle() {
        let data: Vec<u8> = vec![0, 12, 255, 0, 250, 0, 128, 34, 255, 0, 248,
                                 0, 1, 56, 99, 255, 0, 249, 0];
        let element = IconElement::new(OSType(*b"is32"), data);
        let image = element.decode_image().expect("failed to decode image");
        assert_eq!(image.pixel_format(), PixelFormat::RGB);
        assert_eq!(image.width(), 16);
        assert_eq!(image.height(), 16);
        assert_eq!(image.data()[0], 12);
        assert_eq!(image.data()[1], 34);
        assert_eq!(image.data()[2], 56);
    }

    #[test]
    fn encode_mask() {
        let mut image = Image::new(PixelFormat::Alpha, 16, 16);
        image.data_mut()[2] = 127;
        let element =
            IconElement::encode_image_with_type(&image, IconType::Mask8_16x16)
                .expect("failed to encode image");
        assert_eq!(element.ostype(), OSType(*b"s8mk"));
        assert_eq!(element.data()[2], 127);
    }

    #[test]
    fn decode_mask() {
        let mut data = vec![0u8; 256];
        data[2] = 127;
        let element = IconElement::new(OSType(*b"s8mk"), data);
        let image = element.decode_image().expect("failed to decode image");
        assert_eq!(image.pixel_format(), PixelFormat::Alpha);
        assert_eq!(image.width(), 16);
        assert_eq!(image.height(), 16);
        assert_eq!(image.data()[2], 127);
    }
}
<commit_msg>Skip extra four zeros at start of some RLE-encoded elements<commit_after>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::cmp;
use std::io::{self, Cursor, Error, ErrorKind, Read, Write};

use super::icontype::{Encoding, IconType, OSType};
use super::image::{Image, PixelFormat};

/// The length of an icon element header, in bytes:
const ICON_ELEMENT_HEADER_LENGTH: u32 = 8;

/// The first twelve bytes of a JPEG 2000 file are always this:
const JPEG_2000_FILE_MAGIC_NUMBER: [u8; 12] = [0x00, 0x00, 0x00, 0x0C, 0x6A,
                                               0x50, 0x20, 0x20, 0x0D, 0x0A,
                                               0x87, 0x0A];

/// One entry in an ICNS file.  Depending on the resource type, this may
/// represent an icon, or part of an icon (such as an alpha mask, or color
/// data without the mask).
pub struct IconElement {
    ostype: OSType,
    data: Vec<u8>,
}

impl IconElement {
    /// Creates an icon element with the given OSType and data payload.
    pub fn new(ostype: OSType, data: Vec<u8>) -> IconElement {
        IconElement {
            ostype: ostype,
            data: data,
        }
    }

    /// Creates an icon element that encodes the given image as the given icon
    /// type.  Returns an error if the image has the wrong dimensions for that
    /// icon type.
    pub fn encode_image_with_type(image: &Image,
                                  icon_type: IconType)
                                  -> io::Result<IconElement> {
        let width = icon_type.pixel_width();
        let height = icon_type.pixel_height();
        if image.width() != width || image.height() != height {
            let msg = format!("image has wrong dimensions for {:?} ({}x{} \
                               instead of {}x{}))",
                              icon_type,
                              image.width(),
                              image.height(),
                              width,
                              height);
            return Err(Error::new(ErrorKind::InvalidInput, msg));
        }
        let mut data: Vec<u8>;
        match icon_type.encoding() {
            Encoding::JP2PNG => {
                data = Vec::new();
                try!(image.write_png(&mut data));
            }
            Encoding::RLE24 => {
                let num_pixels = (width * height) as usize;
                match image.pixel_format() {
                    PixelFormat::RGBA => {
                        data = encode_rle(image.data(), 4, num_pixels);
                    }
                    PixelFormat::RGB => {
                        data = encode_rle(image.data(), 3, num_pixels);
                    }
                    // Convert to RGB if the image isn't already RGB or RGBA.
                    _ => {
                        let image = image.convert_to(PixelFormat::RGB);
                        data = encode_rle(image.data(), 3, num_pixels);
                    }
                }
            }
            Encoding::Mask8 => {
                // Convert to Alpha format unconditionally -- if the image is
                // already Alpha format, this will simply clone its data array,
                // which we'd need to do anyway.
                let image = image.convert_to(PixelFormat::Alpha);
                data = image.into_data().into_vec();
            }
        }
        Ok(IconElement::new(icon_type.ostype(), data))
    }

    /// Decodes the icon element into an image.  Returns an error if this
    /// element does not represent an icon type supported by this library, or
    /// if the data is malformed.
    pub fn decode_image(&self) -> io::Result<Image> {
        let icon_type = try!(self.icon_type().ok_or_else(|| {
            Error::new(ErrorKind::InvalidInput,
                       format!("unsupported OSType: {}", self.ostype()))
        }));
        let width = icon_type.pixel_width();
        let height = icon_type.pixel_width();
        match icon_type.encoding() {
            Encoding::JP2PNG => {
                if self.data.starts_with(&JPEG_2000_FILE_MAGIC_NUMBER) {
                    let msg = "element to be decoded contains JPEG 2000 \
                               data, which is not yet supported";
                    return Err(Error::new(ErrorKind::InvalidInput, msg));
                }
                let image = try!(Image::read_png(Cursor::new(&self.data)));
                if image.width() != width || image.height() != height {
                    let msg = format!("decoded PNG has wrong dimensions \
                                       ({}x{} instead of {}x{})",
                                      image.width(),
                                      image.height(),
                                      width,
                                      height);
                    return Err(Error::new(ErrorKind::InvalidData, msg));
                }
                Ok(image)
            }
            Encoding::RLE24 => {
                let mut image = Image::new(PixelFormat::RGB, width, height);
                try!(decode_rle(&self.data, image.data_mut()));
                Ok(image)
            }
            Encoding::Mask8 => {
                let num_pixels = width * height;
                if self.data.len() as u32 != num_pixels {
                    let msg = format!("wrong data payload length ({} \
                                       instead of {})",
                                      self.data.len(),
                                      num_pixels);
                    return Err(Error::new(ErrorKind::InvalidData, msg));
                }
                let mut image = Image::new(PixelFormat::Alpha, width, height);
                image.data_mut().clone_from_slice(&self.data);
                Ok(image)
            }
        }
    }

    /// Returns the OSType for this element (e.g. `it32` or `t8mk`).
    pub fn ostype(&self) -> OSType {
        self.ostype
    }

    /// Returns the type of icon encoded by this element, or `None` if this
    /// element does not encode a supported icon type.
    pub fn icon_type(&self) -> Option<IconType> {
        IconType::from_ostype(self.ostype)
    }

    /// Returns the encoded data for this element.
    pub fn data(&self) -> &[u8] {
        &self.data
    }

    /// Returns the encoded length of the element, in bytes, including the
    /// length of the header.
    pub fn total_length(&self) -> u32 {
        ICON_ELEMENT_HEADER_LENGTH + (self.data.len() as u32)
    }

    /// Reads an icon element from within an ICNS file.
    pub fn read<R: Read>(mut reader: R) -> io::Result<IconElement> {
        let mut raw_ostype = [0u8; 4];
        try!(reader.read_exact(&mut raw_ostype));
        let element_length = try!(reader.read_u32::<BigEndian>());
        if element_length < ICON_ELEMENT_HEADER_LENGTH {
            return Err(Error::new(ErrorKind::InvalidData,
                                  "invalid element length"));
        }
        let data_length = element_length - ICON_ELEMENT_HEADER_LENGTH;
        let mut data = vec![0u8; data_length as usize];
        try!(reader.read_exact(&mut data));
        Ok(IconElement::new(OSType(raw_ostype), data))
    }

    /// Writes the icon element to within an ICNS file.
    pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
        let OSType(ref raw_ostype) = self.ostype;
        try!(writer.write_all(raw_ostype));
        try!(writer.write_u32::<BigEndian>(self.total_length()));
        try!(writer.write_all(&self.data));
        Ok(())
    }
}

fn encode_rle(input: &[u8],
              num_input_channels: usize,
              num_pixels: usize)
              -> Vec<u8> {
    assert!(num_input_channels == 3 || num_input_channels == 4);
    let mut output = Vec::with_capacity(num_pixels);
    for channel in 0..3 {
        let mut pixel: usize = 0;
        let mut literal_start: usize = 0;
        while pixel < num_pixels {
            let value = input[num_input_channels * pixel + channel];
            let mut run_length = 1;
            while pixel + run_length < num_pixels &&
                  input[num_input_channels * (pixel + run_length) +
                        channel] == value &&
                  run_length < 130 {
                run_length += 1;
            }
            if run_length >= 3 {
                while literal_start < pixel {
                    let literal_length = cmp::min(256, pixel - literal_start);
                    output.push((literal_length - 1) as u8);
                    for i in 0..literal_length {
                        output.push(input[num_input_channels *
                                          (literal_start + i) +
                                          channel]);
                    }
                    literal_start += literal_length;
                }
                output.push((run_length + 125) as u8);
                output.push(value);
                pixel += run_length;
                literal_start = pixel;
            } else {
                pixel += run_length;
            }
        }
        while literal_start < pixel {
            let literal_length = cmp::min(256, pixel - literal_start);
            output.push((literal_length - 1) as u8);
            for i in 0..literal_length {
                output.push(input[num_input_channels * (literal_start + i) +
                                  channel]);
            }
            literal_start += literal_length;
        }
    }
    output
}

fn decode_rle(input: &[u8], output: &mut [u8]) -> io::Result<()> {
    assert_eq!(output.len() % 3, 0);
    let num_pixels = output.len() / 3;
    // Sometimes, RLE-encoded data starts with four extra zeros that must be
    // skipped.  The internet doesn't seem to know why.
    let skip: usize = if input.starts_with(&[0, 0, 0, 0]) {
        4
    } else {
        0
    };
    let input = &input[skip..input.len()];
    let mut iter = input.iter();
    let mut remaining: usize = 0;
    let mut within_run = false;
    let mut run_value: u8 = 0;
    for channel in 0..3 {
        for pixel in 0..num_pixels {
            if remaining == 0 {
                let next: u8 = *try!(iter.next().ok_or_else(rle_error));
                if next < 128 {
                    remaining = (next as usize) + 1;
                    within_run = false;
                } else {
                    remaining = (next as usize) - 125;
                    within_run = true;
                    run_value = *try!(iter.next().ok_or_else(rle_error));
                }
            }
            output[3 * pixel + channel] = if within_run {
                run_value
            } else {
                *try!(iter.next().ok_or_else(rle_error))
            };
            remaining -= 1;
        }
        if remaining != 0 {
            return Err(rle_error());
        }
    }
    if iter.next().is_some() {
        Err(rle_error())
    } else {
        Ok(())
    }
}

fn rle_error() -> Error {
    Error::new(ErrorKind::InvalidData, "invalid RLE-compressed data")
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::icontype::{IconType, OSType};
    use super::super::image::{Image, PixelFormat};

    #[test]
    fn encode_rle() {
        let mut image = Image::new(PixelFormat::Gray, 16, 16);
        image.data_mut()[0] = 44;
        image.data_mut()[1] = 55;
        image.data_mut()[2] = 66;
        image.data_mut()[3] = 66;
        image.data_mut()[4] = 66;
        let element =
            IconElement::encode_image_with_type(&image, IconType::RGB24_16x16)
                .expect("failed to encode image");
        assert_eq!(element.ostype(), OSType(*b"is32"));
        assert_eq!(element.data()[0..5], [1, 44, 55, 128, 66]);
    }

    #[test]
    fn decode_rle() {
        let data: Vec<u8> = vec![0, 12, 255, 0, 250, 0, 128, 34, 255, 0, 248,
                                 0, 1, 56, 99, 255, 0, 249, 0];
        let element = IconElement::new(OSType(*b"is32"), data);
        let image = element.decode_image().expect("failed to decode image");
        assert_eq!(image.pixel_format(), PixelFormat::RGB);
        assert_eq!(image.width(), 16);
        assert_eq!(image.height(), 16);
        assert_eq!(image.data()[0], 12);
        assert_eq!(image.data()[1], 34);
        assert_eq!(image.data()[2], 56);
    }

    #[test]
    fn decode_rle_skip_extra_zeros() {
        let data: Vec<u8> = vec![0, 0, 0, 0, 0, 12, 255, 0, 250, 0, 128, 34,
                                 255, 0, 248, 0, 1, 56, 99, 255, 0, 249, 0];
        let element = IconElement::new(OSType(*b"is32"), data);
        let image = element.decode_image().expect("failed to decode image");
        assert_eq!(image.data()[0], 12);
        assert_eq!(image.data()[1], 34);
        assert_eq!(image.data()[2], 56);
    }

    #[test]
    fn encode_mask() {
        let mut image = Image::new(PixelFormat::Alpha, 16, 16);
        image.data_mut()[2] = 127;
        let element =
            IconElement::encode_image_with_type(&image, IconType::Mask8_16x16)
                .expect("failed to encode image");
        assert_eq!(element.ostype(), OSType(*b"s8mk"));
        assert_eq!(element.data()[2], 127);
    }

    #[test]
    fn decode_mask() {
        let mut data = vec![0u8; 256];
        data[2] = 127;
        let element = IconElement::new(OSType(*b"s8mk"), data);
        let image = element.decode_image().expect("failed to decode image");
        assert_eq!(image.pixel_format(), PixelFormat::Alpha);
        assert_eq!(image.width(), 16);
        assert_eq!(image.height(), 16);
        assert_eq!(image.data()[2], 127);
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Encoder

use std::io::{self, Write};
use std::{mem, error, fmt};

use byteorder::{self, LittleEndian, WriteBytesExt};

use bson::{Array, Document, Bson};

#[derive(Debug)]
pub enum EncoderError {
    IoError(io::Error),
}

impl From<io::Error> for EncoderError {
    fn from(err: io::Error) -> EncoderError {
        EncoderError::IoError(err)
    }
}

impl From<byteorder::Error> for EncoderError {
    fn from(err: byteorder::Error) -> EncoderError {
        EncoderError::IoError(From::from(err))
    }
}

impl fmt::Display for EncoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &EncoderError::IoError(ref inner) => inner.fmt(fmt)
        }
    }
}

impl error::Error for EncoderError {
    fn description(&self) -> &str {
        match self {
            &EncoderError::IoError(ref inner) => inner.description(),
        }
    }
    fn cause(&self) -> Option<&error::Error> {
        match self {
            &EncoderError::IoError(ref inner) => Some(inner)
        }
    }
}

pub type EncoderResult<T> = Result<T, EncoderError>;

fn write_string<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_i32::<LittleEndian>(s.len() as i32 + 1));
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

fn write_cstring<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

#[inline]
fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> EncoderResult<()> {
    writer.write_i32::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> EncoderResult<()> {
    writer.write_i64::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> EncoderResult<()> {
    writer.write_f64::<LittleEndian>(val).map_err(From::from)
}

fn encode_array<W: Write + ?Sized>(writer: &mut W, arr: &Array) -> EncoderResult<()> {
    let mut buf = Vec::new();
    for (key, val) in arr.iter().enumerate() {
        try!(encode_bson(&mut buf, &key.to_string(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

pub fn encode_document<'a, W: Write + ?Sized>(writer: &mut W, doc: &Document) -> EncoderResult<()> {
    let mut buf = Vec::new();
    for (key, val) in doc.iter() {
        try!(encode_bson(&mut buf, key, val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

fn encode_bson<W: Write + ?Sized>(writer: &mut W, key: &str, val: &Bson) -> EncoderResult<()> {
    try!(writer.write_u8(val.element_type() as u8));
    try!(write_cstring(writer, key));

    match val {
        &Bson::FloatingPoint(v) => write_f64(writer, v),
        &Bson::String(ref v) => write_string(writer, &v),
        &Bson::Array(ref v) => encode_array(writer, &v),
        &Bson::Document(ref v) => encode_document(writer, &v),
        &Bson::Boolean(v) => writer.write_u8(if v { 0x00 } else { 0x01 }).map_err(From::from),
        &Bson::RegExp(ref pat, ref opt) => {
            try!(write_cstring(writer, pat));
            write_cstring(writer, opt)
        },
        &Bson::JavaScriptCode(ref code) => write_string(writer, &code),
        &Bson::ObjectId(id) => writer.write_all(&id).map_err(From::from),
        &Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
            let mut buf = Vec::new();
            try!(write_string(&mut buf, code));
            try!(encode_document(&mut buf, scope));

            try!(write_i32(writer, buf.len() as i32 + 1));
            writer.write_all(&buf).map_err(From::from)
        },
        &Bson::I32(v) => write_i32(writer, v),
        &Bson::I64(v) => write_i64(writer, v),
        &Bson::TimeStamp(v) => write_i64(writer, v),
        &Bson::Binary(subtype, ref data) => {
            try!(write_i32(writer, data.len() as i32));
            try!(writer.write_u8(From::from(subtype)));
            writer.write_all(data).map_err(From::from)
        },
        &Bson::UtcDatetime(ref v) => write_i64(writer, v.timestamp()),
        &Bson::Null |
        &Bson::Deprecated => Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::encode_document;
    use bson::{Document, Bson};

    #[test]
    fn test_encode_floating_point() {
        let src = 1020.123;
        let dst = [18, 0, 0, 0, 1, 107, 101, 121, 0, 68, 139, 108, 231, 251, 224, 143, 64, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::FloatingPoint(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_utf8_string() {
        let src = "test你好吗".to_owned();
        let dst = [28, 0, 0, 0, 2, 107, 101, 121, 0, 14, 0, 0, 0, 116, 101, 115, 116, 228, 189, 160, 229, 165, 189, 229, 144, 151, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::String(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_array() {
        let src = vec![Bson::FloatingPoint(1.01), Bson::String("xyz".to_owned())];
        let dst = [37, 0, 0, 0, 4, 107, 101, 121, 0, 27, 0, 0, 0, 1, 48, 0, 41, 92, 143, 194, 245, 40, 240, 63, 2, 49, 0, 4, 0, 0, 0, 120, 121, 122, 0, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::Array(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf[..], &dst[..]);
    }
}
<commit_msg>Made encode_document generic for any map type.<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Encoder

use std::io::{self, Write};
use std::iter::IntoIterator;
use std::{mem, error, fmt};

use byteorder::{self, LittleEndian, WriteBytesExt};

use bson::Bson;

#[derive(Debug)]
pub enum EncoderError {
    IoError(io::Error),
}

impl From<io::Error> for EncoderError {
    fn from(err: io::Error) -> EncoderError {
        EncoderError::IoError(err)
    }
}

impl From<byteorder::Error> for EncoderError {
    fn from(err: byteorder::Error) -> EncoderError {
        EncoderError::IoError(From::from(err))
    }
}

impl fmt::Display for EncoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &EncoderError::IoError(ref inner) => inner.fmt(fmt)
        }
    }
}

impl error::Error for EncoderError {
    fn description(&self) -> &str {
        match self {
            &EncoderError::IoError(ref inner) => inner.description(),
        }
    }
    fn cause(&self) -> Option<&error::Error> {
        match self {
            &EncoderError::IoError(ref inner) => Some(inner)
        }
    }
}

pub type EncoderResult<T> = Result<T, EncoderError>;

fn write_string<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_i32::<LittleEndian>(s.len() as i32 + 1));
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

fn write_cstring<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

#[inline]
fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> EncoderResult<()> {
    writer.write_i32::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> EncoderResult<()> {
    writer.write_i64::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> EncoderResult<()> {
    writer.write_f64::<LittleEndian>(val).map_err(From::from)
}

fn encode_array<W: Write + ?Sized>(writer: &mut W, arr: &[Bson]) -> EncoderResult<()> {
    let mut buf = Vec::new();
    for (key, val) in arr.iter().enumerate() {
        try!(encode_bson(&mut buf, &key.to_string(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

pub fn encode_document
    <'a, W: Write + ?Sized, D: IntoIterator<Item=(&'a String, &'a Bson)>>
    (writer: &mut W, doc: D) -> EncoderResult<()>
{
    let mut buf = Vec::new();
    for (key, val) in doc.into_iter() {
        try!(encode_bson(&mut buf, key, val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

fn encode_bson<W: Write + ?Sized>(writer: &mut W, key: &str, val: &Bson) -> EncoderResult<()> {
    try!(writer.write_u8(val.element_type() as u8));
    try!(write_cstring(writer, key));

    match val {
        &Bson::FloatingPoint(v) => write_f64(writer, v),
        &Bson::String(ref v) => write_string(writer, &v),
        &Bson::Array(ref v) => encode_array(writer, &v),
        &Bson::Document(ref v) => encode_document(writer, v),
        &Bson::Boolean(v) => writer.write_u8(if v { 0x00 } else { 0x01 }).map_err(From::from),
        &Bson::RegExp(ref pat, ref opt) => {
            try!(write_cstring(writer, pat));
            write_cstring(writer, opt)
        },
        &Bson::JavaScriptCode(ref code) => write_string(writer, &code),
        &Bson::ObjectId(id) => writer.write_all(&id).map_err(From::from),
        &Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
            let mut buf = Vec::new();
            try!(write_string(&mut buf, code));
            try!(encode_document(&mut buf, scope));

            try!(write_i32(writer, buf.len() as i32 + 1));
            writer.write_all(&buf).map_err(From::from)
        },
        &Bson::I32(v) => write_i32(writer, v),
        &Bson::I64(v) => write_i64(writer, v),
        &Bson::TimeStamp(v) => write_i64(writer, v),
        &Bson::Binary(subtype, ref data) => {
            try!(write_i32(writer, data.len() as i32));
            try!(writer.write_u8(From::from(subtype)));
            writer.write_all(data).map_err(From::from)
        },
        &Bson::UtcDatetime(ref v) => write_i64(writer, v.timestamp()),
        &Bson::Null |
        &Bson::Deprecated => Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::encode_document;
    use bson::{Document, Bson};

    #[test]
    fn test_encode_floating_point() {
        let src = 1020.123;
        let dst = [18, 0, 0, 0, 1, 107, 101, 121, 0, 68, 139, 108, 231, 251, 224, 143, 64, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::FloatingPoint(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_utf8_string() {
        let src = "test你好吗".to_owned();
        let dst = [28, 0, 0, 0, 2, 107, 101, 121, 0, 14, 0, 0, 0, 116, 101, 115, 116, 228, 189, 160, 229, 165, 189, 229, 144, 151, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::String(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_array() {
        let src = vec![Bson::FloatingPoint(1.01), Bson::String("xyz".to_owned())];
        let dst = [37, 0, 0, 0, 4, 107, 101, 121, 0, 27, 0, 0, 0, 1, 48, 0, 41, 92, 143, 194, 245, 40, 240, 63, 2, 49, 0, 4, 0, 0, 0, 120, 121, 122, 0, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::Array(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf[..], &dst[..]);
    }
}
<|endoftext|>


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

// xfail-test

pub fn main() {
// This is ok
    match &[(~5,~7)] {
        ps => {
           let (ref y, _) = ps[0];
           println!("1. y = {}", **y);
           assert!(**y == 5);
        }
    }

// This is not entirely ok
    match Some(&[(~5,)]) {
        Some(ps) => {
           let (ref y,) = ps[0];
           println!("2. y = {}", **y);
           if **y != 5 { println!("sadness"); }
        }
        None => ()
    }

// This is not ok
    match Some(&[(~5,~7)]) {
        Some(ps) => {
           let (ref y, ref z) = ps[0];
           println!("3. y = {} z = {}", **y, **z);
           assert!(**y == 5);
        }
        None => ()
    }
}

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

pub fn main() {
    match &[(~5,~7)] {
        ps => {
           let (ref y, _) = ps[0];
           assert!(**y == 5);
        }
    }

    match Some(&[(~5,)]) {
        Some(ps) => {
           let (ref y,) = ps[0];
           assert!(**y == 5);
        }
        None => ()
    }

    match Some(&[(~5,~7)]) {
        Some(ps) => {
           let (ref y, ref z) = ps[0];
           assert!(**y == 5);
           assert!(**z == 7);
        }
        None => ()
    }
}
<|endoftext|>


<commit_before>use tokio_core::io::{Io, Codec, EasyBuf, Framed};
use std::io;

use futures::sync::mpsc;
use futures::{Future, Stream, Poll};

use tokio_proto::streaming::{Body, Message};
use tokio_proto::streaming::multiplex::{Frame, ClientProto, RequestId};

use asnom::common;
use asnom::IResult;
use asnom::structures::{Tag, Integer, Sequence, ASNTag};
use asnom::structure::StructureTag;

use asnom::parse::{parse_tag, parse_uint};
use asnom::write;

pub struct LdapCodec;

impl Codec for LdapCodec {
    type In = Frame<Tag, Tag, io::Error>;
    type Out = Frame<Tag, Tag, io::Error>;

    fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, io::Error> {
        match parse_tag(buf.as_slice()) {
            IResult::Incomplete(_) => { Ok(None)},
            IResult::Error(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
            IResult::Done(_, i) => {
                if let Some(mut tags) = i.match_id(16u64).and_then(|x| x.expect_constructed()) {
                    let protoop = tags.pop().unwrap();
                    let msgid: Vec<u8> = tags.pop().unwrap()
                                    .match_class(common::TagClass::Universal)
                                    .and_then(|x| x.match_id(2u64))
                                    .and_then(|x| x.expect_primitive()).unwrap();
                    if let IResult::Done(_, id) = parse_uint(msgid.as_slice()) {
                        match protoop.id {
                            // SearchResultEntry
                            4 => Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: Some(Tag::StructureTag(protoop)),
                            })),
                            // SearchResultDone
                            5 => Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: None,
                            })),
                            // Any other Message
                            _ => Ok(Some(Frame::Message {
                                id: id as u64,
                                message: Tag::StructureTag(protoop),
                                body: false,
                                solo: false,
                            })),
                        }
                    }
                }
                return Err(io::Error::new(io::ErrorKind::Other, "Invalid (RequestId, Tag) received."));
            }
        }
    }

    fn encode(&mut self, msg: Self::Out, into: &mut Vec<u8>) -> io::Result<()> {
        match msg {
            Frame::Message {message, id, body, solo} => {
                let outtag = Tag::Sequence(Sequence {
                    inner: vec![
                        Tag::Integer(Integer {
                            inner: id as i64,
                            .. Default::default()
                        }),
                        message,
                    ],
                    .. Default::default()
                });

                let outstruct = outtag.into_structure();
                try!(write::encode_into(into, outstruct));
                Ok(())
            },
            _ => unimplemented!(),
        }
    }
}

pub struct LdapProto;

impl<T: Io + 'static> ClientProto<T> for LdapProto {
    type Request = Tag;
    type RequestBody = Tag;
    type Response = Tag;
    type ResponseBody = Tag;
    type Error = io::Error;

    /// `Framed<T, LineCodec>` is the return value of `io.framed(LineCodec)`
    type Transport = Framed<T, LdapCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(LdapCodec))
    }
}
<commit_msg>Fixes typo<commit_after>use tokio_core::io::{Io, Codec, EasyBuf, Framed};
use std::io;

use futures::sync::mpsc;
use futures::{Future, Stream, Poll};

use tokio_proto::streaming::{Body, Message};
use tokio_proto::streaming::multiplex::{Frame, ClientProto, RequestId};

use asnom::common;
use asnom::IResult;
use asnom::structures::{Tag, Integer, Sequence, ASNTag};
use asnom::structure::StructureTag;

use asnom::parse::{parse_tag, parse_uint};
use asnom::write;

pub struct LdapCodec;

impl Codec for LdapCodec {
    type In = Frame<Tag, Tag, io::Error>;
    type Out = Frame<Tag, Tag, io::Error>;

    fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, io::Error> {
        match parse_tag(buf.as_slice()) {
            IResult::Incomplete(_) => { Ok(None)},
            IResult::Error(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
            IResult::Done(_, i) => {
                if let Some(mut tags) = i.match_id(16u64).and_then(|x| x.expect_constructed()) {
                    let protoop = tags.pop().unwrap();
                    let msgid: Vec<u8> = tags.pop().unwrap()
                                    .match_class(common::TagClass::Universal)
                                    .and_then(|x| x.match_id(2u64))
                                    .and_then(|x| x.expect_primitive()).unwrap();
                    if let IResult::Done(_, id) = parse_uint(msgid.as_slice()) {
                        return match protoop.id {
                            // SearchResultEntry
                            4 => Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: Some(Tag::StructureTag(protoop)),
                            })),
                            // SearchResultDone
                            5 => Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: None,
                            })),
                            // Any other Message
                            _ => Ok(Some(Frame::Message {
                                id: id as u64,
                                message: Tag::StructureTag(protoop),
                                body: false,
                                solo: false,
                            })),
                        }
                    }
                }
                return Err(io::Error::new(io::ErrorKind::Other, "Invalid (RequestId, Tag) received."));
            }
        }
    }

    fn encode(&mut self, msg: Self::Out, into: &mut Vec<u8>) -> io::Result<()> {
        match msg {
            Frame::Message {message, id, body, solo} => {
                let outtag = Tag::Sequence(Sequence {
                    inner: vec![
                        Tag::Integer(Integer {
                            inner: id as i64,
                            .. Default::default()
                        }),
                        message,
                    ],
                    .. Default::default()
                });

                let outstruct = outtag.into_structure();
                try!(write::encode_into(into, outstruct));
                Ok(())
            },
            _ => unimplemented!(),
        }
    }
}

pub struct LdapProto;

impl<T: Io + 'static> ClientProto<T> for LdapProto {
    type Request = Tag;
    type RequestBody = Tag;
    type Response = Tag;
    type ResponseBody = Tag;
    type Error = io::Error;

    /// `Framed<T, LineCodec>` is the return value of `io.framed(LineCodec)`
    type Transport = Framed<T, LdapCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(LdapCodec))
    }
}
<|endoftext|>


<commit_before>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for c in coeffs[1..].iter_mut() {
        *c /= ac_quant;
    }
    // workaround for bug in token coder
    *coeffs.last_mut().unwrap() = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for i in 1..coeffs.len() {
        rcoeffs[i] = coeffs[i] * ac_quant;
    }
}
<commit_msg>Use iterators in dequantize<commit_after>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for c in coeffs[1..].iter_mut() {
        *c /= ac_quant;
    }
    // workaround for bug in token coder
    *coeffs.last_mut().unwrap() = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for (r, &c) in rcoeffs.iter_mut().zip(coeffs.iter()).skip(1) {
        *r = c * ac_quant;
    }
}
<|endoftext|>


<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME,
                                  "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without
        // blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<commit_msg>More TODO comments for failing on_close call<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME,
                                  "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        // We don't get to here because our stdin thread doesn't pass
        // the SIGINT to the main thread when closing. This should work
        // as a library without a CLI.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without
        // blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;

use common;
use glium::backend::glutin_backend::GlutinFacade;
use glium::Program;
use glium::Surface;
use self::nalgebra::{Matrix4, PerspectiveMatrix3};

use common::{Scene, Vertex8f32};
implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub modelview_matrix_array: [[f32; 4]; 4],
	pub program: Program,
	pub projection_matrix: Matrix4<f32>,
    pub scene: Scene,
    pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
    pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
    pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

    let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> = Vec::with_capacity(scene.meshes.len());

    for i in 0..scene.meshes.len() {
        vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
    }

    let index_buffer: glium::index::NoIndices =
        glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    if scene.shaders.len() == 0 {
        panic!("No shaders loaded");
    }

	let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

	for i in 0..scene.images.len() {
		//TODO: determine image format by name extension if nessisary
		//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
		let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

	    let image_dimensions = image.dimensions();
	    let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
	                                                                   image_dimensions);
	    let opengl_texture: glium::texture::CompressedSrgbTexture2d = glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
		textures.insert(scene.images[i].name.clone(), opengl_texture);
	}

    // Load the first shader in the database by default
    // TODO: load from config settings table?
    let shader_index = 0;

    // println!("Using glsl version {}", glsl_version);

    let program: Program = program!(display,
    	/*
			110 => {
				vertex: &scene.shaders[shader_index].vertex_source_110,
				fragment: &scene.shaders[shader_index].fragment_source_110,
			},
			120 => {
				vertex: &scene.shaders[shader_index].vertex_source_120,
				fragment: &scene.shaders[shader_index].fragment_source_120,
			},
			130 => {
				vertex: &scene.shaders[shader_index].vertex_source_130,
				fragment: &scene.shaders[shader_index].fragment_source_130,
			},
			*/
			140 => {
				vertex: &scene.shaders[shader_index].vertex_source_140,
				fragment: &scene.shaders[shader_index].fragment_source_140,
			},
			/*
			150 => {
				vertex: &scene.shaders[shader_index].vertex_source_150,
				fragment: &scene.shaders[shader_index].fragment_source_150,
			},
			300 => {
				vertex: &scene.shaders[shader_index].vertex_source_300,
				fragment: &scene.shaders[shader_index].fragment_source_300,
			},
			330 => {
				vertex: &scene.shaders[shader_index].vertex_source_330,
				fragment: &scene.shaders[shader_index].fragment_source_330,
			},
			400 => {
				vertex: &scene.shaders[shader_index].vertex_source_400,
				fragment: &scene.shaders[shader_index].fragment_source_400,
			},
			410 => {
				vertex: &scene.shaders[shader_index].vertex_source_410,
				fragment: &scene.shaders[shader_index].fragment_source_410,
			},
			420 => {
				vertex: &scene.shaders[shader_index].vertex_source_420,
				fragment: &scene.shaders[shader_index].fragment_source_420,
			},
			430 => {
				vertex: &scene.shaders[shader_index].vertex_source_430,
				fragment: &scene.shaders[shader_index].fragment_source_430,
			},
			100 es => {
				vertex: &scene.shaders[shader_index].vertex_source_100es,
				fragment: &scene.shaders[shader_index].fragment_source_100es,
			},
			300 es => {
				vertex: &scene.shaders[shader_index].vertex_source_300es,
				fragment: &scene.shaders[shader_index].fragment_source_300es,
			}, */
		)
        .unwrap();

    // Shader compilation no longer required
    display.release_shader_compiler();

    //TODO get width and height from display
    let screen_width = 400;
    let screen_height = 300;

    // Set up camera
    let projection_matrix = PerspectiveMatrix3::new(screen_width as f32 / screen_height as f32,
                                              45.0,
                                              0.1,
                                              1000.0);
    let projection_matrix_array: Matrix4<f32> = projection_matrix.to_matrix();

    let modelview_matrix_array = [[1.0f32, -0.0f32, -0.0f32, 0.0f32],
                                  [0.0f32, 1.0f32, -0.0f32, 0.0f32],
                                  [0.0f32, 0.0f32, 1.0f32, 0.0f32],
                                  [-5.0f32, -3.0f32, -12.0f32, 1.0f32]];
        Renderer {
        	index_buffer: index_buffer,
        	modelview_matrix_array: modelview_matrix_array,
        	program: program,
        	projection_matrix: projection_matrix_array,
        	scene: scene,
        	textures: textures,
        	vertex_buffers: vertex_buffers,
        }
    }

    pub fn render(&self, display: &GlutinFacade) {
		 let mut target = display.draw();
	 	// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        for i in 0..self.vertex_buffers.len() as usize {
            let material_index: usize = self.scene.meshes[i].material_index.clone();
            let diffuse = self.scene.materials[material_index].diffuse.clone();
            let diffuse_texname: String =
                self.scene.materials[material_index as usize].diffuse_texname.clone();
            let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
            if diffuse_texname.len() == 0 {
                opengl_texture = &default_blank_texture;
            } else {
                opengl_texture = &self.textures[&diffuse_texname];
            }
            let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
		        projection: *self.projection_matrix.as_ref(),
		        modelview: self.modelview_matrix_array,
		        light_position_worldspace: [2.0, 10.0, 1.0f32],
		        diffuse: diffuse,
		        diffuse_texture: opengl_texture,
		    };

            target.draw(&self.vertex_buffers[i],
                      &self.index_buffer,
                      &self.program,
                      &uniforms,
                      &Default::default())
                .unwrap();
        }
        target.finish().unwrap();
    }
}
<commit_msg>Added error checking to diffuse_texname hashmap lookup.<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;

use common;
use glium::backend::glutin_backend::GlutinFacade;
use glium::Program;
use glium::Surface;
use self::nalgebra::{Matrix4, PerspectiveMatrix3};

use common::{Scene, Vertex8f32};
implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub modelview_matrix_array: [[f32; 4]; 4],
	pub program: Program,
	pub projection_matrix: Matrix4<f32>,
    pub scene: Scene,
    pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
    pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
    pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

    let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> = Vec::with_capacity(scene.meshes.len());

    for i in 0..scene.meshes.len() {
        vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
    }

    let index_buffer: glium::index::NoIndices =
        glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    if scene.shaders.len() == 0 {
        panic!("No shaders loaded");
    }

	let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

	for i in 0..scene.images.len() {
		//TODO: determine image format by name extension if nessisary
		//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
		let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

	    let image_dimensions = image.dimensions();
	    let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
	                                                                   image_dimensions);
	    let opengl_texture: glium::texture::CompressedSrgbTexture2d = glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
		textures.insert(scene.images[i].name.clone(), opengl_texture);
	}

    // Load the first shader in the database by default
    // TODO: load from config settings table?
    let shader_index = 0;

    // println!("Using glsl version {}", glsl_version);

    let program: Program = program!(display,
    	/*
			110 => {
				vertex: &scene.shaders[shader_index].vertex_source_110,
				fragment: &scene.shaders[shader_index].fragment_source_110,
			},
			120 => {
				vertex: &scene.shaders[shader_index].vertex_source_120,
				fragment: &scene.shaders[shader_index].fragment_source_120,
			},
			130 => {
				vertex: &scene.shaders[shader_index].vertex_source_130,
				fragment: &scene.shaders[shader_index].fragment_source_130,
			},
			*/
			140 => {
				vertex: &scene.shaders[shader_index].vertex_source_140,
				fragment: &scene.shaders[shader_index].fragment_source_140,
			},
			/*
			150 => {
				vertex: &scene.shaders[shader_index].vertex_source_150,
				fragment: &scene.shaders[shader_index].fragment_source_150,
			},
			300 => {
				vertex: &scene.shaders[shader_index].vertex_source_300,
				fragment: &scene.shaders[shader_index].fragment_source_300,
			},
			330 => {
				vertex: &scene.shaders[shader_index].vertex_source_330,
				fragment: &scene.shaders[shader_index].fragment_source_330,
			},
			400 => {
				vertex: &scene.shaders[shader_index].vertex_source_400,
				fragment: &scene.shaders[shader_index].fragment_source_400,
			},
			410 => {
				vertex: &scene.shaders[shader_index].vertex_source_410,
				fragment: &scene.shaders[shader_index].fragment_source_410,
			},
			420 => {
				vertex: &scene.shaders[shader_index].vertex_source_420,
				fragment: &scene.shaders[shader_index].fragment_source_420,
			},
			430 => {
				vertex: &scene.shaders[shader_index].vertex_source_430,
				fragment: &scene.shaders[shader_index].fragment_source_430,
			},
			100 es => {
				vertex: &scene.shaders[shader_index].vertex_source_100es,
				fragment: &scene.shaders[shader_index].fragment_source_100es,
			},
			300 es => {
				vertex: &scene.shaders[shader_index].vertex_source_300es,
				fragment: &scene.shaders[shader_index].fragment_source_300es,
			}, */
		)
        .unwrap();

    // Shader compilation no longer required
    display.release_shader_compiler();

    //TODO get width and height from display
    let screen_width = 400;
    let screen_height = 300;

    // Set up camera
    let projection_matrix = PerspectiveMatrix3::new(screen_width as f32 / screen_height as f32,
                                              45.0,
                                              0.1,
                                              1000.0);
    let projection_matrix_array: Matrix4<f32> = projection_matrix.to_matrix();

    let modelview_matrix_array = [[1.0f32, -0.0f32, -0.0f32, 0.0f32],
                                  [0.0f32, 1.0f32, -0.0f32, 0.0f32],
                                  [0.0f32, 0.0f32, 1.0f32, 0.0f32],
                                  [-5.0f32, -3.0f32, -12.0f32, 1.0f32]];
        Renderer {
        	index_buffer: index_buffer,
        	modelview_matrix_array: modelview_matrix_array,
        	program: program,
        	projection_matrix: projection_matrix_array,
        	scene: scene,
        	textures: textures,
        	vertex_buffers: vertex_buffers,
        }
    }

    pub fn render(&self, display: &GlutinFacade) {
		 let mut target = display.draw();
	 	// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        for i in 0..self.vertex_buffers.len() as usize {
            let material_index: usize = self.scene.meshes[i].material_index.clone();
            let diffuse = self.scene.materials[material_index].diffuse.clone();
            let diffuse_texname: String =
                self.scene.materials[material_index].diffuse_texname.clone();
            let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
            if diffuse_texname.len() == 0 {
                opengl_texture = &default_blank_texture;
            } else {
                match self.textures.get(&diffuse_texname) {
                	Some(t) => {
                		 opengl_texture = &t;
                	},
                	None => {
                		println!("Unable to load {}, using blank texture instead.", diffuse_texname);
                		opengl_texture = &default_blank_texture;
                	},
                }
            }
            let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
		        projection: *self.projection_matrix.as_ref(),
		        modelview: self.modelview_matrix_array,
		        light_position_worldspace: [2.0, 10.0, 1.0f32],
		        diffuse: diffuse,
		        diffuse_texture: opengl_texture,
		    };

            target.draw(&self.vertex_buffers[i],
                      &self.index_buffer,
                      &self.program,
                      &uniforms,
                      &Default::default())
                .unwrap();
        }
        target.finish().unwrap();
    }
}
<|endoftext|>