<commit_before>//! Decode pixel data using GDCM when the default features are enabled.

use crate::*;
use dicom_encoding::adapters::DecodeError;
use dicom_encoding::transfer_syntax::TransferSyntaxIndex;
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
use gdcm_rs::{
    decode_multi_frame_compressed, decode_single_frame_compressed, Error as GDCMError,
    GDCMPhotometricInterpretation, GDCMTransferSyntax,
};
use std::{convert::TryFrom, str::FromStr};

impl<D> PixelDecoder for FileDicomObject<InMemDicomObject<D>>
where
    D: DataDictionary + Clone,
{
    fn decode_pixel_data(&self) -> Result<DecodedPixelData> {
        use super::attribute::*;

        let pixel_data = pixel_data(self).context(GetAttributeSnafu)?;
        let cols = cols(self).context(GetAttributeSnafu)?;
        let rows = rows(self).context(GetAttributeSnafu)?;

        let photometric_interpretation =
            photometric_interpretation(self).context(GetAttributeSnafu)?;
        let pi_type = GDCMPhotometricInterpretation::from_str(photometric_interpretation.as_str())
            .map_err(|_| {
                UnsupportedPhotometricInterpretationSnafu {
                    pi: photometric_interpretation.clone(),
                }
                .build()
            })?;

        let transfer_syntax = &self.meta().transfer_syntax;
        let registry =
            TransferSyntaxRegistry
                .get(&&transfer_syntax)
                .context(UnknownTransferSyntaxSnafu {
                    ts_uid: transfer_syntax,
                })?;
        let ts_type = GDCMTransferSyntax::from_str(&registry.uid()).map_err(|_| {
            UnsupportedTransferSyntaxSnafu {
                ts: transfer_syntax.clone(),
            }
            .build()
        })?;

        let samples_per_pixel = samples_per_pixel(self).context(GetAttributeSnafu)?;
        let bits_allocated = bits_allocated(self).context(GetAttributeSnafu)?;
        let bits_stored = bits_stored(self).context(GetAttributeSnafu)?;
        let high_bit = high_bit(self).context(GetAttributeSnafu)?;
        let pixel_representation = pixel_representation(self).context(GetAttributeSnafu)?;
        let rescale_intercept = rescale_intercept(self);
        let rescale_slope = rescale_slope(self);
        let number_of_frames = number_of_frames(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function.and_then(|v| VoiLutFunction::try_from(&*v).ok());

        let decoded_pixel_data = match pixel_data.value() {
            Value::PixelSequence {
                fragments,
                offset_table: _,
            } => {
                let gdcm_error_mapper = |source: GDCMError| DecodeError::Custom {
                    message: source.to_string(),
                    source: Some(Box::new(source)),
                };
                if fragments.len() > 1 {
                    // Bundle fragments and decode multi-frame dicoms
                    let dims = [cols.into(), rows.into(), number_of_frames.into()];
                    let fragments: Vec<_> = fragments.iter().map(|frag| frag.as_slice()).collect();
                    decode_multi_frame_compressed(
                        fragments.as_slice(),
                        &dims,
                        pi_type,
                        ts_type,
                        samples_per_pixel,
                        bits_allocated,
                        bits_stored,
                        high_bit,
                        pixel_representation as u16,
                    )
                    .map_err(gdcm_error_mapper)
                    .context(DecodePixelDataSnafu)?
                    .to_vec()
                } else {
                    decode_single_frame_compressed(
                        &fragments[0],
                        cols.into(),
                        rows.into(),
                        pi_type,
                        ts_type,
                        samples_per_pixel,
                        bits_allocated,
                        bits_stored,
                        high_bit,
                        pixel_representation as u16,
                    )
                    .map_err(gdcm_error_mapper)
                    .context(DecodePixelDataSnafu)?
                    .to_vec()
                }
            }
            Value::Primitive(p) => {
                // Non-encoded, just return the pixel data of the first frame
                let total_bytes = rows as usize
                    * cols as usize
                    * samples_per_pixel as usize
                    * (bits_allocated as usize / 8);
                p.to_bytes()[0..total_bytes].to_vec()
            }
            Value::Sequence { items: _, size: _ } => InvalidPixelDataSnafu.fail()?,
        };

        // pixels are already interpreted,
        // set new photometric interpretation
        let new_pi = match samples_per_pixel {
            1 => PhotometricInterpretation::Monochrome2,
            3 => PhotometricInterpretation::Rgb,
            _ => photometric_interpretation,
        };

        let window = if let Some(window_center) = window_center(self).context(GetAttributeSnafu)? {
            let window_width = window_width(self).context(GetAttributeSnafu)?;

            window_width.map(|width| WindowLevel {
                center: window_center,
                width,
            })
        } else {
            None
        };

        Ok(DecodedPixelData {
            data: Cow::from(decoded_pixel_data),
            cols: cols.into(),
            rows: rows.into(),
            number_of_frames,
            photometric_interpretation: new_pi,
            samples_per_pixel,
            planar_configuration: PlanarConfiguration::Standard,
            bits_allocated,
            bits_stored,
            high_bit,
            pixel_representation,
            rescale_intercept,
            rescale_slope,
            voi_lut_function,
            window,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use dicom_object::open_file;
    use dicom_test_files;
    use rstest::rstest;
    use std::fs;
    use std::path::Path;

    #[rstest(value => [
        "pydicom/693_J2KI.dcm",
        "pydicom/693_J2KR.dcm",
        "pydicom/693_UNCI.dcm",
        "pydicom/693_UNCR.dcm",
        "pydicom/CT_small.dcm",
        "pydicom/JPEG-lossy.dcm",
        "pydicom/JPEG2000.dcm",
        "pydicom/JPEG2000_UNC.dcm",
        "pydicom/JPGLosslessP14SV1_1s_1f_8b.dcm",
        "pydicom/MR_small.dcm",
        "pydicom/MR_small_RLE.dcm",
        "pydicom/MR_small_implicit.dcm",
        "pydicom/MR_small_jp2klossless.dcm",
        "pydicom/MR_small_jpeg_ls_lossless.dcm",
        "pydicom/explicit_VR-UN.dcm",
        "pydicom/MR_small_bigendian.dcm",
        "pydicom/MR_small_expb.dcm",
        "pydicom/SC_rgb.dcm",
        "pydicom/SC_rgb_16bit.dcm",
        "pydicom/SC_rgb_dcmtk_+eb+cr.dcm",
        "pydicom/SC_rgb_expb.dcm",
        "pydicom/SC_rgb_expb_16bit.dcm",
        "pydicom/SC_rgb_gdcm2k_uncompressed.dcm",
        "pydicom/SC_rgb_gdcm_KY.dcm",
        "pydicom/SC_rgb_jpeg_gdcm.dcm",
        "pydicom/SC_rgb_jpeg_lossy_gdcm.dcm",
        "pydicom/SC_rgb_rle.dcm",
        "pydicom/SC_rgb_rle_16bit.dcm",
        "pydicom/color-pl.dcm",
        "pydicom/color-px.dcm",
        "pydicom/SC_ybr_full_uncompressed.dcm",
        "pydicom/color3d_jpeg_baseline.dcm",
        "pydicom/emri_small_jpeg_ls_lossless.dcm",
])]
    fn test_parse_dicom_pixel_data(value: &str) {
        let test_file = dicom_test_files::path(value).unwrap();
        println!("Parsing pixel data for {}", test_file.display());
        let obj = open_file(test_file).unwrap();
        let pixel_data = obj.decode_pixel_data().unwrap();
        let output_dir =
            Path::new("../target/dicom_test_files/_out/test_gdcm_parse_dicom_pixel_data");
        fs::create_dir_all(output_dir).unwrap();

        for i in 0..pixel_data.number_of_frames {
            let image = pixel_data.to_dynamic_image(i).unwrap();
            let image_path = output_dir.join(format!(
                "{}-{}.png",
                Path::new(value).file_stem().unwrap().to_str().unwrap(),
                i,
            ));
            image.save(image_path).unwrap();
        }
    }

    #[test]
    fn test_to_ndarray_signed_word_no_lut() {
        let test_file = dicom_test_files::path("pydicom/JPEG2000.dcm").unwrap();
        let obj = open_file(test_file).unwrap();
        let options = ConvertOptions::new().with_modality_lut(ModalityLutOption::None);
        let ndarray = obj
            .decode_pixel_data()
            .unwrap()
            .to_ndarray_with_options::<i16>(&options)
            .unwrap();
        assert_eq!(ndarray.shape(), &[1, 1024, 256, 1]);
        assert_eq!(ndarray.len(), 262144);
        assert_eq!(ndarray[[0, 260, 0, 0]], -3);
    }
}
<commit_msg>Remove slicing of primitive pixel data<commit_after>//! Decode pixel data using GDCM when the default features are enabled.

use crate::*;
use dicom_encoding::adapters::DecodeError;
use dicom_encoding::transfer_syntax::TransferSyntaxIndex;
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
use gdcm_rs::{
    decode_multi_frame_compressed, decode_single_frame_compressed, Error as GDCMError,
    GDCMPhotometricInterpretation, GDCMTransferSyntax,
};
use std::{convert::TryFrom, str::FromStr};

impl<D> PixelDecoder for FileDicomObject<InMemDicomObject<D>>
where
    D: DataDictionary + Clone,
{
    fn decode_pixel_data(&self) -> Result<DecodedPixelData> {
        use super::attribute::*;

        let pixel_data = pixel_data(self).context(GetAttributeSnafu)?;
        let cols = cols(self).context(GetAttributeSnafu)?;
        let rows = rows(self).context(GetAttributeSnafu)?;

        let photometric_interpretation =
            photometric_interpretation(self).context(GetAttributeSnafu)?;
        let pi_type = GDCMPhotometricInterpretation::from_str(photometric_interpretation.as_str())
            .map_err(|_| {
                UnsupportedPhotometricInterpretationSnafu {
                    pi: photometric_interpretation.clone(),
                }
                .build()
            })?;

        let transfer_syntax = &self.meta().transfer_syntax;
        let registry =
            TransferSyntaxRegistry
                .get(&&transfer_syntax)
                .context(UnknownTransferSyntaxSnafu {
                    ts_uid: transfer_syntax,
                })?;
        let ts_type = GDCMTransferSyntax::from_str(&registry.uid()).map_err(|_| {
            UnsupportedTransferSyntaxSnafu {
                ts: transfer_syntax.clone(),
            }
            .build()
        })?;

        let samples_per_pixel = samples_per_pixel(self).context(GetAttributeSnafu)?;
        let bits_allocated = bits_allocated(self).context(GetAttributeSnafu)?;
        let bits_stored = bits_stored(self).context(GetAttributeSnafu)?;
        let high_bit = high_bit(self).context(GetAttributeSnafu)?;
        let pixel_representation = pixel_representation(self).context(GetAttributeSnafu)?;
        let rescale_intercept = rescale_intercept(self);
        let rescale_slope = rescale_slope(self);
        let number_of_frames = number_of_frames(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function.and_then(|v| VoiLutFunction::try_from(&*v).ok());

        let decoded_pixel_data = match pixel_data.value() {
            Value::PixelSequence {
                fragments,
                offset_table: _,
            } => {
                let gdcm_error_mapper = |source: GDCMError| DecodeError::Custom {
                    message: source.to_string(),
                    source: Some(Box::new(source)),
                };
                if fragments.len() > 1 {
                    // Bundle fragments and decode multi-frame dicoms
                    let dims = [cols.into(), rows.into(), number_of_frames.into()];
                    let fragments: Vec<_> = fragments.iter().map(|frag| frag.as_slice()).collect();
                    decode_multi_frame_compressed(
                        fragments.as_slice(),
                        &dims,
                        pi_type,
                        ts_type,
                        samples_per_pixel,
                        bits_allocated,
                        bits_stored,
                        high_bit,
                        pixel_representation as u16,
                    )
                    .map_err(gdcm_error_mapper)
                    .context(DecodePixelDataSnafu)?
                    .to_vec()
                } else {
                    decode_single_frame_compressed(
                        &fragments[0],
                        cols.into(),
                        rows.into(),
                        pi_type,
                        ts_type,
                        samples_per_pixel,
                        bits_allocated,
                        bits_stored,
                        high_bit,
                        pixel_representation as u16,
                    )
                    .map_err(gdcm_error_mapper)
                    .context(DecodePixelDataSnafu)?
                    .to_vec()
                }
            }
            Value::Primitive(p) => {
                // Non-encoded, just return the pixel data of the first frame
                p.to_bytes().to_vec()
            }
            Value::Sequence { items: _, size: _ } => InvalidPixelDataSnafu.fail()?,
        };

        // pixels are already interpreted,
        // set new photometric interpretation
        let new_pi = match samples_per_pixel {
            1 => PhotometricInterpretation::Monochrome2,
            3 => PhotometricInterpretation::Rgb,
            _ => photometric_interpretation,
        };

        let window = if let Some(window_center) = window_center(self).context(GetAttributeSnafu)? {
            let window_width = window_width(self).context(GetAttributeSnafu)?;

            window_width.map(|width| WindowLevel {
                center: window_center,
                width,
            })
        } else {
            None
        };

        Ok(DecodedPixelData {
            data: Cow::from(decoded_pixel_data),
            cols: cols.into(),
            rows: rows.into(),
            number_of_frames,
            photometric_interpretation: new_pi,
            samples_per_pixel,
            planar_configuration: PlanarConfiguration::Standard,
            bits_allocated,
            bits_stored,
            high_bit,
            pixel_representation,
            rescale_intercept,
            rescale_slope,
            voi_lut_function,
            window,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use dicom_object::open_file;
    use dicom_test_files;
    use rstest::rstest;
    use std::fs;
    use std::path::Path;

    #[rstest(value => [
        "pydicom/693_J2KI.dcm",
        "pydicom/693_J2KR.dcm",
        "pydicom/693_UNCI.dcm",
        "pydicom/693_UNCR.dcm",
        "pydicom/CT_small.dcm",
        "pydicom/JPEG-lossy.dcm",
        "pydicom/JPEG2000.dcm",
        "pydicom/JPEG2000_UNC.dcm",
        "pydicom/JPGLosslessP14SV1_1s_1f_8b.dcm",
        "pydicom/MR_small.dcm",
        "pydicom/MR_small_RLE.dcm",
        "pydicom/MR_small_implicit.dcm",
        "pydicom/MR_small_jp2klossless.dcm",
        "pydicom/MR_small_jpeg_ls_lossless.dcm",
        "pydicom/explicit_VR-UN.dcm",
        "pydicom/MR_small_bigendian.dcm",
        "pydicom/MR_small_expb.dcm",
        "pydicom/SC_rgb.dcm",
        "pydicom/SC_rgb_16bit.dcm",
        "pydicom/SC_rgb_dcmtk_+eb+cr.dcm",
        "pydicom/SC_rgb_expb.dcm",
        "pydicom/SC_rgb_expb_16bit.dcm",
        "pydicom/SC_rgb_gdcm2k_uncompressed.dcm",
        "pydicom/SC_rgb_gdcm_KY.dcm",
        "pydicom/SC_rgb_jpeg_gdcm.dcm",
        "pydicom/SC_rgb_jpeg_lossy_gdcm.dcm",
        "pydicom/SC_rgb_rle.dcm",
        "pydicom/SC_rgb_rle_16bit.dcm",
        "pydicom/color-pl.dcm",
        "pydicom/color-px.dcm",
        "pydicom/SC_ybr_full_uncompressed.dcm",
        "pydicom/color3d_jpeg_baseline.dcm",
        "pydicom/emri_small_jpeg_ls_lossless.dcm",
])]
    fn test_parse_dicom_pixel_data(value: &str) {
        let test_file = dicom_test_files::path(value).unwrap();
        println!("Parsing pixel data for {}", test_file.display());
        let obj = open_file(test_file).unwrap();
        let pixel_data = obj.decode_pixel_data().unwrap();
        let output_dir =
            Path::new("../target/dicom_test_files/_out/test_gdcm_parse_dicom_pixel_data");
        fs::create_dir_all(output_dir).unwrap();

        for i in 0..pixel_data.number_of_frames {
            let image = pixel_data.to_dynamic_image(i).unwrap();
            let image_path = output_dir.join(format!(
                "{}-{}.png",
                Path::new(value).file_stem().unwrap().to_str().unwrap(),
                i,
            ));
            image.save(image_path).unwrap();
        }
    }

    #[test]
    fn test_to_ndarray_signed_word_no_lut() {
        let test_file = dicom_test_files::path("pydicom/JPEG2000.dcm").unwrap();
        let obj = open_file(test_file).unwrap();
        let options = ConvertOptions::new().with_modality_lut(ModalityLutOption::None);
        let ndarray = obj
            .decode_pixel_data()
            .unwrap()
            .to_ndarray_with_options::<i16>(&options)
            .unwrap();
        assert_eq!(ndarray.shape(), &[1, 1024, 256, 1]);
        assert_eq!(ndarray.len(), 262144);
        assert_eq!(ndarray[[0, 260, 0, 0]], -3);
    }
}
<|endoftext|>


<commit_before>use std::{
    collections::BTreeMap,
    convert::{TryFrom, TryInto},
    fmt,
};

use js_int::Int;
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
use serde_json::{to_string as to_json_string, Value as JsonValue};

use super::Error;

/// The inner type of `CanonicalJsonValue::Object`.
pub type Object = BTreeMap<String, CanonicalJsonValue>;

/// Represents a canonical JSON value as per the Matrix specification.
#[derive(Clone, Eq, PartialEq)]
pub enum CanonicalJsonValue {
    /// Represents a JSON null value.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(null).try_into().unwrap();
    /// ```
    Null,

    /// Represents a JSON boolean.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(true).try_into().unwrap();
    /// ```
    Bool(bool),

    /// Represents a JSON integer.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(12).try_into().unwrap();
    /// ```
    Integer(Int),

    /// Represents a JSON string.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!("a string").try_into().unwrap();
    /// ```
    String(String),

    /// Represents a JSON array.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(["an", "array"]).try_into().unwrap();
    /// ```
    Array(Vec<CanonicalJsonValue>),

    /// Represents a JSON object.
    ///
    /// The map is backed by a BTreeMap to guarantee the sorting of keys.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
    /// ```
    Object(Object),
}

impl CanonicalJsonValue {
    /// If the `CanonicalJsonValue` is a `Bool`, return the inner value.
    pub fn as_bool(&self) -> Option<bool> {
        match self {
            Self::Bool(b) => Some(*b),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Integer`, return the inner value.
    pub fn as_integer(&self) -> Option<Int> {
        match self {
            Self::Integer(i) => Some(*i),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is a `String`, return a reference to the inner value.
    pub fn as_str(&self) -> Option<&str> {
        match self {
            Self::String(s) => Some(s),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Array`, return a reference to the inner value.
    pub fn as_array(&self) -> Option<&[CanonicalJsonValue]> {
        match self {
            Self::Array(a) => Some(a),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Object`, return a reference to the inner value.
    pub fn as_object(&self) -> Option<&Object> {
        match self {
            Self::Object(o) => Some(o),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Array`, return a mutable reference to the inner value.
    pub fn as_array_mut(&mut self) -> Option<&mut Vec<CanonicalJsonValue>> {
        match self {
            Self::Array(a) => Some(a),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Object`, return a mutable reference to the inner value.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match self {
            Self::Object(o) => Some(o),
            _ => None,
        }
    }
}

impl Default for CanonicalJsonValue {
    fn default() -> Self {
        Self::Null
    }
}

impl fmt::Debug for CanonicalJsonValue {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Self::Null => formatter.debug_tuple("Null").finish(),
            Self::Bool(v) => formatter.debug_tuple("Bool").field(&v).finish(),
            Self::Integer(ref v) => fmt::Debug::fmt(v, formatter),
            Self::String(ref v) => formatter.debug_tuple("String").field(v).finish(),
            Self::Array(ref v) => {
                formatter.write_str("Array(")?;
                fmt::Debug::fmt(v, formatter)?;
                formatter.write_str(")")
            }
            Self::Object(ref v) => {
                formatter.write_str("Object(")?;
                fmt::Debug::fmt(v, formatter)?;
                formatter.write_str(")")
            }
        }
    }
}

impl fmt::Display for CanonicalJsonValue {
    /// Display this value as a string.
    ///
    /// This `Display` implementation is intentionally unaffected by any formatting parameters,
    /// because adding extra whitespace or otherwise pretty-printing it would make it not the
    /// canonical form anymore.
    ///
    /// If you want to pretty-print a `CanonicalJsonValue` for debugging purposes, use
    /// one of `serde_json::{to_string_pretty, to_vec_pretty, to_writer_pretty}`.
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", to_json_string(&self).map_err(|_| fmt::Error)?)
    }
}

impl TryFrom<JsonValue> for CanonicalJsonValue {
    type Error = Error;

    fn try_from(val: JsonValue) -> Result<Self, Self::Error> {
        Ok(match val {
            JsonValue::Bool(b) => Self::Bool(b),
            JsonValue::Number(num) => Self::Integer(
                Int::try_from(num.as_i64().ok_or(Error::IntConvert)?)
                    .map_err(|_| Error::IntConvert)?,
            ),
            JsonValue::Array(vec) => {
                Self::Array(vec.into_iter().map(TryInto::try_into).collect::<Result<Vec<_>, _>>()?)
            }
            JsonValue::String(string) => Self::String(string),
            JsonValue::Object(obj) => Self::Object(
                obj.into_iter()
                    .map(|(k, v)| Ok((k, v.try_into()?)))
                    .collect::<Result<Object, _>>()?,
            ),
            JsonValue::Null => Self::Null,
        })
    }
}

impl From<CanonicalJsonValue> for JsonValue {
    fn from(val: CanonicalJsonValue) -> Self {
        match val {
            CanonicalJsonValue::Bool(b) => Self::Bool(b),
            CanonicalJsonValue::Integer(int) => Self::Number(i64::from(int).into()),
            CanonicalJsonValue::String(string) => Self::String(string),
            CanonicalJsonValue::Array(vec) => {
                Self::Array(vec.into_iter().map(Into::into).collect())
            }
            CanonicalJsonValue::Object(obj) => {
                Self::Object(obj.into_iter().map(|(k, v)| (k, v.into())).collect())
            }
            CanonicalJsonValue::Null => Self::Null,
        }
    }
}

impl Serialize for CanonicalJsonValue {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Self::Null => serializer.serialize_unit(),
            Self::Bool(b) => serializer.serialize_bool(*b),
            Self::Integer(n) => n.serialize(serializer),
            Self::String(s) => serializer.serialize_str(s),
            Self::Array(v) => v.serialize(serializer),
            Self::Object(m) => {
                use serde::ser::SerializeMap;
                let mut map = serializer.serialize_map(Some(m.len()))?;
                for (k, v) in m {
                    map.serialize_entry(k, v)?;
                }
                map.end()
            }
        }
    }
}

impl<'de> Deserialize<'de> for CanonicalJsonValue {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<CanonicalJsonValue, D::Error>
    where
        D: Deserializer<'de>,
    {
        let val = JsonValue::deserialize(deserializer)?;
        val.try_into().map_err(serde::de::Error::custom)
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryInto;

    use serde_json::json;

    use super::CanonicalJsonValue;

    #[test]
    fn to_string() {
        const CANONICAL_STR: &str = r#"{"city":"London","street":"10 Downing Street"}"#;

        let json: CanonicalJsonValue =
            json!({ "city": "London", "street": "10 Downing Street" }).try_into().unwrap();

        assert_eq!(format!("{}", json), CANONICAL_STR);
        assert_eq!(format!("{:#}", json), CANONICAL_STR);
    }
}
<commit_msg>serde: Add `is_*` methods to CanonicalJsonValue<commit_after>use std::{
    collections::BTreeMap,
    convert::{TryFrom, TryInto},
    fmt,
};

use js_int::Int;
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
use serde_json::{to_string as to_json_string, Value as JsonValue};

use super::Error;

/// The inner type of `CanonicalJsonValue::Object`.
pub type Object = BTreeMap<String, CanonicalJsonValue>;

/// Represents a canonical JSON value as per the Matrix specification.
#[derive(Clone, Eq, PartialEq)]
pub enum CanonicalJsonValue {
    /// Represents a JSON null value.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(null).try_into().unwrap();
    /// ```
    Null,

    /// Represents a JSON boolean.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(true).try_into().unwrap();
    /// ```
    Bool(bool),

    /// Represents a JSON integer.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(12).try_into().unwrap();
    /// ```
    Integer(Int),

    /// Represents a JSON string.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!("a string").try_into().unwrap();
    /// ```
    String(String),

    /// Represents a JSON array.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!(["an", "array"]).try_into().unwrap();
    /// ```
    Array(Vec<CanonicalJsonValue>),

    /// Represents a JSON object.
    ///
    /// The map is backed by a BTreeMap to guarantee the sorting of keys.
    ///
    /// ```
    /// # use serde_json::json;
    /// # use std::convert::TryInto;
    /// # use ruma_serde::CanonicalJsonValue;
    /// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
    /// ```
    Object(Object),
}

impl CanonicalJsonValue {
    /// If the `CanonicalJsonValue` is a `Bool`, return the inner value.
    pub fn as_bool(&self) -> Option<bool> {
        match self {
            Self::Bool(b) => Some(*b),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Integer`, return the inner value.
    pub fn as_integer(&self) -> Option<Int> {
        match self {
            Self::Integer(i) => Some(*i),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is a `String`, return a reference to the inner value.
    pub fn as_str(&self) -> Option<&str> {
        match self {
            Self::String(s) => Some(s),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Array`, return a reference to the inner value.
    pub fn as_array(&self) -> Option<&[CanonicalJsonValue]> {
        match self {
            Self::Array(a) => Some(a),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Object`, return a reference to the inner value.
    pub fn as_object(&self) -> Option<&Object> {
        match self {
            Self::Object(o) => Some(o),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Array`, return a mutable reference to the inner value.
    pub fn as_array_mut(&mut self) -> Option<&mut Vec<CanonicalJsonValue>> {
        match self {
            Self::Array(a) => Some(a),
            _ => None,
        }
    }

    /// If the `CanonicalJsonValue` is an `Object`, return a mutable reference to the inner value.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match self {
            Self::Object(o) => Some(o),
            _ => None,
        }
    }

    /// Returns `true` if the `CanonicalJsonValue` is a `Bool`.
    pub fn is_bool(&self) -> bool {
        matches!(self, Self::Bool(_))
    }

    /// Returns `true` if the `CanonicalJsonValue` is an `Integer`.
    pub fn is_integer(&self) -> bool {
        matches!(self, Self::Integer(_))
    }

    /// Returns `true` if the `CanonicalJsonValue` is a `String`.
    pub fn is_string(&self) -> bool {
        matches!(self, Self::String(_))
    }

    /// Returns `true` if the `CanonicalJsonValue` is an `Array`.
    pub fn is_array(&self) -> bool {
        matches!(self, Self::Array(_))
    }

    /// Returns `true` if the `CanonicalJsonValue` is an `Object`.
    pub fn is_object(&self) -> bool {
        matches!(self, Self::Object(_))
    }
}

impl Default for CanonicalJsonValue {
    fn default() -> Self {
        Self::Null
    }
}

impl fmt::Debug for CanonicalJsonValue {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Self::Null => formatter.debug_tuple("Null").finish(),
            Self::Bool(v) => formatter.debug_tuple("Bool").field(&v).finish(),
            Self::Integer(ref v) => fmt::Debug::fmt(v, formatter),
            Self::String(ref v) => formatter.debug_tuple("String").field(v).finish(),
            Self::Array(ref v) => {
                formatter.write_str("Array(")?;
                fmt::Debug::fmt(v, formatter)?;
                formatter.write_str(")")
            }
            Self::Object(ref v) => {
                formatter.write_str("Object(")?;
                fmt::Debug::fmt(v, formatter)?;
                formatter.write_str(")")
            }
        }
    }
}

impl fmt::Display for CanonicalJsonValue {
    /// Display this value as a string.
    ///
    /// This `Display` implementation is intentionally unaffected by any formatting parameters,
    /// because adding extra whitespace or otherwise pretty-printing it would make it not the
    /// canonical form anymore.
    ///
    /// If you want to pretty-print a `CanonicalJsonValue` for debugging purposes, use
    /// one of `serde_json::{to_string_pretty, to_vec_pretty, to_writer_pretty}`.
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", to_json_string(&self).map_err(|_| fmt::Error)?)
    }
}

impl TryFrom<JsonValue> for CanonicalJsonValue {
    type Error = Error;

    fn try_from(val: JsonValue) -> Result<Self, Self::Error> {
        Ok(match val {
            JsonValue::Bool(b) => Self::Bool(b),
            JsonValue::Number(num) => Self::Integer(
                Int::try_from(num.as_i64().ok_or(Error::IntConvert)?)
                    .map_err(|_| Error::IntConvert)?,
            ),
            JsonValue::Array(vec) => {
                Self::Array(vec.into_iter().map(TryInto::try_into).collect::<Result<Vec<_>, _>>()?)
            }
            JsonValue::String(string) => Self::String(string),
            JsonValue::Object(obj) => Self::Object(
                obj.into_iter()
                    .map(|(k, v)| Ok((k, v.try_into()?)))
                    .collect::<Result<Object, _>>()?,
            ),
            JsonValue::Null => Self::Null,
        })
    }
}

impl From<CanonicalJsonValue> for JsonValue {
    fn from(val: CanonicalJsonValue) -> Self {
        match val {
            CanonicalJsonValue::Bool(b) => Self::Bool(b),
            CanonicalJsonValue::Integer(int) => Self::Number(i64::from(int).into()),
            CanonicalJsonValue::String(string) => Self::String(string),
            CanonicalJsonValue::Array(vec) => {
                Self::Array(vec.into_iter().map(Into::into).collect())
            }
            CanonicalJsonValue::Object(obj) => {
                Self::Object(obj.into_iter().map(|(k, v)| (k, v.into())).collect())
            }
            CanonicalJsonValue::Null => Self::Null,
        }
    }
}

impl Serialize for CanonicalJsonValue {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Self::Null => serializer.serialize_unit(),
            Self::Bool(b) => serializer.serialize_bool(*b),
            Self::Integer(n) => n.serialize(serializer),
            Self::String(s) => serializer.serialize_str(s),
            Self::Array(v) => v.serialize(serializer),
            Self::Object(m) => {
                use serde::ser::SerializeMap;
                let mut map = serializer.serialize_map(Some(m.len()))?;
                for (k, v) in m {
                    map.serialize_entry(k, v)?;
                }
                map.end()
            }
        }
    }
}

impl<'de> Deserialize<'de> for CanonicalJsonValue {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<CanonicalJsonValue, D::Error>
    where
        D: Deserializer<'de>,
    {
        let val = JsonValue::deserialize(deserializer)?;
        val.try_into().map_err(serde::de::Error::custom)
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryInto;

    use serde_json::json;

    use super::CanonicalJsonValue;

    #[test]
    fn to_string() {
        const CANONICAL_STR: &str = r#"{"city":"London","street":"10 Downing Street"}"#;

        let json: CanonicalJsonValue =
            json!({ "city": "London", "street": "10 Downing Street" }).try_into().unwrap();

        assert_eq!(format!("{}", json), CANONICAL_STR);
        assert_eq!(format!("{:#}", json), CANONICAL_STR);
    }
}
<|endoftext|>


<commit_before>use self::WhichLine::*;

use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
use std::str::FromStr;

use log::*;

#[derive(Clone, Debug, PartialEq)]
pub enum ErrorKind {
    Help,
    Error,
    Note,
    Suggestion,
    Warning,
}

impl FromStr for ErrorKind {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.to_uppercase();
        let part0: &str = s.split(':').next().unwrap();
        match part0 {
            "HELP" => Ok(ErrorKind::Help),
            "ERROR" => Ok(ErrorKind::Error),
            "NOTE" => Ok(ErrorKind::Note),
            "SUGGESTION" => Ok(ErrorKind::Suggestion),
            "WARN" | "WARNING" => Ok(ErrorKind::Warning),
            _ => Err(()),
        }
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ErrorKind::Help => write!(f, "help message"),
            ErrorKind::Error => write!(f, "error"),
            ErrorKind::Note => write!(f, "note"),
            ErrorKind::Suggestion => write!(f, "suggestion"),
            ErrorKind::Warning => write!(f, "warning"),
        }
    }
}

#[derive(Debug)]
pub struct Error {
    pub line_num: usize,
    /// What kind of message we expect (e.g., warning, error, suggestion).
    /// `None` if not specified or unknown message kind.
    pub kind: Option<ErrorKind>,
    pub msg: String,
}

#[derive(PartialEq, Debug)]
enum WhichLine {
    ThisLine,
    FollowPrevious(usize),
    AdjustBackward(usize),
}

/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
/// The former is a "follow" that inherits its target from the preceding line;
/// the latter is an "adjusts" that goes that many lines up.
///
/// Goal is to enable tests both like: //~^^^ ERROR go up three
/// and also //~^ ERROR message one for the preceding line, and
///          //~| ERROR message two for that same line.
///
/// If cfg is not None (i.e., in an incremental test), then we look
/// for `//[X]~` instead, where `X` is the current `cfg`.
pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
    let rdr = BufReader::new(File::open(testfile).unwrap());

    // `last_nonfollow_error` tracks the most recently seen
    // line with an error template that did not use the
    // follow-syntax, "//~| ...".
    //
    // (pnkfelix could not find an easy way to compose Iterator::scan
    // and Iterator::filter_map to pass along this information into
    // `parse_expected`. So instead I am storing that state here and
    // updating it in the map callback below.)
    let mut last_nonfollow_error = None;

    let tag = match cfg {
        Some(rev) => format!("//[{}]~", rev),
        None => "//~".to_string(),
    };

    rdr.lines()
        .enumerate()
        .filter_map(|(line_num, line)| {
            parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag).map(
                |(which, error)| {
                    match which {
                        FollowPrevious(_) => {}
                        _ => last_nonfollow_error = Some(error.line_num),
                    }
                    error
                },
            )
        })
        .collect()
}

fn parse_expected(
    last_nonfollow_error: Option<usize>,
    line_num: usize,
    line: &str,
    tag: &str,
) -> Option<(WhichLine, Error)> {
    let start = line.find(tag)?;
    let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' {
        (true, 0)
    } else {
        (
            false,
            line[start + tag.len()..]
                .chars()
                .take_while(|c| *c == '^')
                .count(),
        )
    };
    let kind_start = start + tag.len() + adjusts + (follow as usize);
    let (kind, msg);
    match line[kind_start..]
        .split_whitespace()
        .next()
        .expect("Encountered unexpected empty comment")
        .parse::<ErrorKind>()
    {
        Ok(k) => {
            // If we find `//~ ERROR foo` or something like that:
            kind = Some(k);
            let letters = line[kind_start..].chars();
            msg = letters
                .skip_while(|c| c.is_whitespace())
                .skip_while(|c| !c.is_whitespace())
                .collect::<String>();
        }
        Err(_) => {
            // Otherwise we found `//~ foo`:
            kind = None;
            let letters = line[kind_start..].chars();
            msg = letters
                .skip_while(|c| c.is_whitespace())
                .collect::<String>();
        }
    }
    let msg = msg.trim().to_owned();

    let (which, line_num) = if follow {
        assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
        let line_num = last_nonfollow_error.expect(
            "encountered //~| without \
             preceding //~^ line.",
        );
        (FollowPrevious(line_num), line_num)
    } else {
        let which = if adjusts > 0 {
            AdjustBackward(adjusts)
        } else {
            ThisLine
        };
        let line_num = line_num - adjusts;
        (which, line_num)
    };

    debug!(
        "line={} tag={:?} which={:?} kind={:?} msg={:?}",
        line_num, tag, which, kind, msg
    );
    Some((
        which,
        Error {
            line_num,
            kind,
            msg,
        },
    ))
}
<commit_msg>Allow multiple cfgs per comment in "revisions:" tests<commit_after>use self::WhichLine::*;

use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
use std::str::FromStr;

use lazy_static::lazy_static;
use log::*;
use regex::Regex;

#[derive(Clone, Debug, PartialEq)]
pub enum ErrorKind {
    Help,
    Error,
    Note,
    Suggestion,
    Warning,
}

impl FromStr for ErrorKind {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.to_uppercase();
        let part0: &str = s.split(':').next().unwrap();
        match part0 {
            "HELP" => Ok(ErrorKind::Help),
            "ERROR" => Ok(ErrorKind::Error),
            "NOTE" => Ok(ErrorKind::Note),
            "SUGGESTION" => Ok(ErrorKind::Suggestion),
            "WARN" | "WARNING" => Ok(ErrorKind::Warning),
            _ => Err(()),
        }
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ErrorKind::Help => write!(f, "help message"),
            ErrorKind::Error => write!(f, "error"),
            ErrorKind::Note => write!(f, "note"),
            ErrorKind::Suggestion => write!(f, "suggestion"),
            ErrorKind::Warning => write!(f, "warning"),
        }
    }
}

#[derive(Debug)]
pub struct Error {
    pub line_num: usize,
    /// What kind of message we expect (e.g., warning, error, suggestion).
    /// `None` if not specified or unknown message kind.
    pub kind: Option<ErrorKind>,
    pub msg: String,
}

#[derive(PartialEq, Debug)]
enum WhichLine {
    ThisLine,
    FollowPrevious(usize),
    AdjustBackward(usize),
}

/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
/// The former is a "follow" that inherits its target from the preceding line;
/// the latter is an "adjusts" that goes that many lines up.
///
/// Goal is to enable tests both like: //~^^^ ERROR go up three
/// and also //~^ ERROR message one for the preceding line, and
///          //~| ERROR message two for that same line.
///
/// If cfg is not None (i.e., in an incremental test), then we look
/// for `//[X]~` instead, where `X` is the current `cfg`.
pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
    let rdr = BufReader::new(File::open(testfile).unwrap());

    // `last_nonfollow_error` tracks the most recently seen
    // line with an error template that did not use the
    // follow-syntax, "//~| ...".
    //
    // (pnkfelix could not find an easy way to compose Iterator::scan
    // and Iterator::filter_map to pass along this information into
    // `parse_expected`. So instead I am storing that state here and
    // updating it in the map callback below.)
    let mut last_nonfollow_error = None;

    rdr.lines()
        .enumerate()
        .filter_map(|(line_num, line)| {
            parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), cfg).map(
                |(which, error)| {
                    match which {
                        FollowPrevious(_) => {}
                        _ => last_nonfollow_error = Some(error.line_num),
                    }

                    error
                },
            )
        })
        .collect()
}

fn parse_expected(
    last_nonfollow_error: Option<usize>,
    line_num: usize,
    line: &str,
    cfg: Option<&str>,
) -> Option<(WhichLine, Error)> {
    // Matches comments like:
    //     //~
    //     //~|
    //     //~^
    //     //~^^^^^
    //     //[cfg1]~
    //     //[cfg1,cfg2]~^^
    lazy_static! {
        static ref RE: Regex =
            Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap();
    }

    let captures = RE.captures(line)?;

    match (cfg, captures.name("cfgs")) {
        // Only error messages that contain our `cfg` betweeen the square brackets apply to us.
        (Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg)
            => return None,
        (Some(_), Some(_)) => {}

        (None, Some(_)) => panic!("Only tests with revisions should use `//[X]~`"),

        // If an error has no list of revisions, it applies to all revisions.
        (Some(_), None) | (None, None) => {}
    }

    let (follow, adjusts) = match &captures["adjust"] {
        "|" => (true, 0),
        circumflexes => (false, circumflexes.len()),
    };

    // Get the part of the comment after the sigil (e.g. `~^^` or ~|).
    let (_, mut msg) = line.split_at(captures.get(0).unwrap().end());

    let first_word = msg
        .split_whitespace()
        .next()
        .expect("Encountered unexpected empty comment");

    // If we find `//~ ERROR foo` or something like that, skip the first word.
    let kind = first_word.parse::<ErrorKind>().ok();
    if let Some(_) = kind {
        msg = &msg.trim_start().split_at(first_word.len()).1;
    }

    let msg = msg.trim().to_owned();

    let (which, line_num) = if follow {
        assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
        let line_num = last_nonfollow_error.expect(
            "encountered //~| without \
             preceding //~^ line.",
        );
        (FollowPrevious(line_num), line_num)
    } else {
        let which = if adjusts > 0 {
            AdjustBackward(adjusts)
        } else {
            ThisLine
        };
        let line_num = line_num - adjusts;
        (which, line_num)
    };

    debug!(
        "line={} tag={:?} which={:?} kind={:?} msg={:?}",
        line_num, &captures[0], which, kind, msg
    );
    Some((
        which,
        Error {
            line_num,
            kind,
            msg,
        },
    ))
}
<|endoftext|>


<commit_before>use std::io::{BufferedReader, File};

fn read_tar() {
    let file = File::open(&Path::new("tar_test.tar"));
    let mut reader = BufferedReader::new(file);

    let mut buf = [0, ..512];
    match reader.read(buf) {
        Ok(nread) => println!("Read {} bytes", nread),
        Err(e) => println!("Error reading: {}", e),
    }
}

fn main() {
    read_tar();
}
<commit_msg>adding static block size, using a channel to send the buffer, and looping through the file<commit_after>use std::io::{BufferedReader, File};

fn read_tar(chan: Sender<Vec<u8>>) {
    static BLOCK_SIZE: uint = 512;
    let file = File::open(&Path::new("tar_test.tar"));
    let mut reader = BufferedReader::new(file);

    loop {
        let mut buf = vec!();
        match reader.push(BLOCK_SIZE, &mut buf) {
            Ok(_) => chan.send(buf),
            Err(e) => return,
        }

    }
}

fn main() {
    let (chan, port) = channel();
    read_tar(chan);
    println!("{:s}", port.recv().to_string());
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use aster::AstBuilder;

use syntax::ast;
use syntax::ptr::P;
use syntax::visit;

use internals::ast::Item;
use internals::attr;

// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &ast::Generics) -> ast::Generics {
    ast::Generics {
        ty_params: generics.ty_params.iter().map(|ty_param| {
            ast::TyParam {
                default: None,
                .. ty_param.clone()
            }}).collect(),
        .. generics.clone()
    }
}

pub fn with_where_predicates(
    builder: &AstBuilder,
    generics: &ast::Generics,
    predicates: &[ast::WherePredicate],
) -> ast::Generics {
    builder.from_generics(generics.clone())
        .with_predicates(predicates.to_vec())
        .build()
}

pub fn with_where_predicates_from_fields<F>(
    builder: &AstBuilder,
    item: &Item,
    generics: &ast::Generics,
    from_field: F,
) -> ast::Generics
    where F: Fn(&attr::Field) -> Option<&[ast::WherePredicate]>,
{
    builder.from_generics(generics.clone())
        .with_predicates(
            item.body.all_fields()
                .flat_map(|field| from_field(&field.attrs))
                .flat_map(|predicates| predicates.to_vec()))
        .build()
}

pub fn with_bound<F>(
    builder: &AstBuilder,
    item: &Item,
    generics: &ast::Generics,
    filter: F,
    bound: &ast::Path,
) -> ast::Generics
    where F: Fn(&attr::Field) -> bool,
{
    builder.from_generics(generics.clone())
        .with_predicates(
            item.body.all_fields()
                .filter(|&field| filter(&field.attrs))
                .map(|field| &field.ty)
                // TODO this filter can be removed later, see comment on function
                .filter(|ty| contains_generic(ty, generics))
                .filter(|ty| !contains_recursion(ty, item.ident))
                .map(|ty| strip_reference(ty))
                .map(|ty| builder.where_predicate()
                    // the type that is being bounded e.g. T
                    .bound().build(ty.clone())
                    // the bound e.g. Serialize
                    .bound().trait_(bound.clone()).build()
                    .build()))
        .build()
}

// Rust <1.7 enforces that `where` clauses involve generic type parameters. The
// corresponding compiler error is E0193. It is no longer enforced in Rust >=1.7
// so this filtering can be removed in the future when we stop supporting <1.7.
//
// E0193 means we must not generate a `where` clause like `i32: Serialize`
// because even though i32 implements Serialize, i32 is not a generic type
// parameter. Clauses like `T: Serialize` and `Option<T>: Serialize` are okay.
// This function decides whether a given type references any of the generic type
// parameters in the input `Generics`.
fn contains_generic(ty: &ast::Ty, generics: &ast::Generics) -> bool {
    struct FindGeneric<'a> {
        generic_names: &'a HashSet<ast::Name>,
        found_generic: bool,
    }
    impl<'a, 'v> visit::Visitor<'v> for FindGeneric<'a> {
        fn visit_path(&mut self, path: &'v ast::Path, _id: ast::NodeId) {
            if !path.global
                    && path.segments.len() == 1
                    && self.generic_names.contains(&path.segments[0].identifier.name) {
                self.found_generic = true;
            } else {
                visit::walk_path(self, path);
            }
        }
    }

    let generic_names: HashSet<_> = generics.ty_params.iter()
        .map(|ty_param| ty_param.ident.name)
        .collect();

    let mut visitor = FindGeneric {
        generic_names: &generic_names,
        found_generic: false,
    };
    visit::walk_ty(&mut visitor, ty);
    visitor.found_generic
}

// We do not attempt to generate any bounds based on field types that are
// directly recursive, as in:
//
//    struct Test<D> {
//        next: Box<Test<D>>,
//    }
//
// This does not catch field types that are mutually recursive with some other
// type. For those, we require bounds to be specified by a `bound` attribute if
// the inferred ones are not correct.
//
//    struct Test<D> {
//        #[serde(bound="D: Serialize + Deserialize")]
//        next: Box<Other<D>>,
//    }
//    struct Other<D> {
//        #[serde(bound="D: Serialize + Deserialize")]
//        next: Box<Test<D>>,
//    }
fn contains_recursion(ty: &ast::Ty, ident: ast::Ident) -> bool {
    struct FindRecursion {
        ident: ast::Ident,
        found_recursion: bool,
    }
    impl<'v> visit::Visitor<'v> for FindRecursion {
        fn visit_path(&mut self, path: &'v ast::Path, _id: ast::NodeId) {
            if !path.global
                    && path.segments.len() == 1
                    && path.segments[0].identifier == self.ident {
                self.found_recursion = true;
            } else {
                visit::walk_path(self, path);
            }
        }
    }

    let mut visitor = FindRecursion {
        ident: ident,
        found_recursion: false,
    };
    visit::walk_ty(&mut visitor, ty);
    visitor.found_recursion
}

// This is required to handle types that use both a reference and a value of
// the same type, as in:
//
//    enum Test<'a, T> where T: 'a {
//        Lifetime(&'a T),
//        NoLifetime(T),
//    }
//
// Preserving references, we would generate an impl like:
//
//    impl<'a, T> Serialize for Test<'a, T>
//        where &'a T: Serialize,
//              T: Serialize { ... }
//
// And taking a reference to one of the elements would fail with:
//
//    error: cannot infer an appropriate lifetime for pattern due
//    to conflicting requirements [E0495]
//        Test::NoLifetime(ref v) => { ... }
//                         ^~~~~
//
// Instead, we strip references before adding `T: Serialize` bounds in order to
// generate:
//
//    impl<'a, T> Serialize for Test<'a, T>
//        where T: Serialize { ... }
fn strip_reference(mut ty: &P<ast::Ty>) -> &P<ast::Ty> {
    while let ast::TyKind::Rptr(_, ref mut_ty) = ty.node {
        ty = &mut_ty.ty;
    }
    ty
}
<commit_msg>Remove filter no longer necessary for rustc >=1.7<commit_after>use aster::AstBuilder;

use syntax::ast;
use syntax::ptr::P;
use syntax::visit;

use internals::ast::Item;
use internals::attr;

// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &ast::Generics) -> ast::Generics {
    ast::Generics {
        ty_params: generics.ty_params.iter().map(|ty_param| {
            ast::TyParam {
                default: None,
                .. ty_param.clone()
            }}).collect(),
        .. generics.clone()
    }
}

pub fn with_where_predicates(
    builder: &AstBuilder,
    generics: &ast::Generics,
    predicates: &[ast::WherePredicate],
) -> ast::Generics {
    builder.from_generics(generics.clone())
        .with_predicates(predicates.to_vec())
        .build()
}

pub fn with_where_predicates_from_fields<F>(
    builder: &AstBuilder,
    item: &Item,
    generics: &ast::Generics,
    from_field: F,
) -> ast::Generics
    where F: Fn(&attr::Field) -> Option<&[ast::WherePredicate]>,
{
    builder.from_generics(generics.clone())
        .with_predicates(
            item.body.all_fields()
                .flat_map(|field| from_field(&field.attrs))
                .flat_map(|predicates| predicates.to_vec()))
        .build()
}

pub fn with_bound<F>(
    builder: &AstBuilder,
    item: &Item,
    generics: &ast::Generics,
    filter: F,
    bound: &ast::Path,
) -> ast::Generics
    where F: Fn(&attr::Field) -> bool,
{
    builder.from_generics(generics.clone())
        .with_predicates(
            item.body.all_fields()
                .filter(|&field| filter(&field.attrs))
                .map(|field| &field.ty)
                .filter(|ty| !contains_recursion(ty, item.ident))
                .map(|ty| strip_reference(ty))
                .map(|ty| builder.where_predicate()
                    // the type that is being bounded e.g. T
                    .bound().build(ty.clone())
                    // the bound e.g. Serialize
                    .bound().trait_(bound.clone()).build()
                    .build()))
        .build()
}

// We do not attempt to generate any bounds based on field types that are
// directly recursive, as in:
//
//    struct Test<D> {
//        next: Box<Test<D>>,
//    }
//
// This does not catch field types that are mutually recursive with some other
// type. For those, we require bounds to be specified by a `bound` attribute if
// the inferred ones are not correct.
//
//    struct Test<D> {
//        #[serde(bound="D: Serialize + Deserialize")]
//        next: Box<Other<D>>,
//    }
//    struct Other<D> {
//        #[serde(bound="D: Serialize + Deserialize")]
//        next: Box<Test<D>>,
//    }
fn contains_recursion(ty: &ast::Ty, ident: ast::Ident) -> bool {
    struct FindRecursion {
        ident: ast::Ident,
        found_recursion: bool,
    }
    impl<'v> visit::Visitor<'v> for FindRecursion {
        fn visit_path(&mut self, path: &'v ast::Path, _id: ast::NodeId) {
            if !path.global
                    && path.segments.len() == 1
                    && path.segments[0].identifier == self.ident {
                self.found_recursion = true;
            } else {
                visit::walk_path(self, path);
            }
        }
    }

    let mut visitor = FindRecursion {
        ident: ident,
        found_recursion: false,
    };
    visit::walk_ty(&mut visitor, ty);
    visitor.found_recursion
}

// This is required to handle types that use both a reference and a value of
// the same type, as in:
//
//    enum Test<'a, T> where T: 'a {
//        Lifetime(&'a T),
//        NoLifetime(T),
//    }
//
// Preserving references, we would generate an impl like:
//
//    impl<'a, T> Serialize for Test<'a, T>
//        where &'a T: Serialize,
//              T: Serialize { ... }
//
// And taking a reference to one of the elements would fail with:
//
//    error: cannot infer an appropriate lifetime for pattern due
//    to conflicting requirements [E0495]
//        Test::NoLifetime(ref v) => { ... }
//                         ^~~~~
//
// Instead, we strip references before adding `T: Serialize` bounds in order to
// generate:
//
//    impl<'a, T> Serialize for Test<'a, T>
//        where T: Serialize { ... }
fn strip_reference(mut ty: &P<ast::Ty>) -> &P<ast::Ty> {
    while let ast::TyKind::Rptr(_, ref mut_ty) = ty.node {
        ty = &mut_ty.ty;
    }
    ty
}
<|endoftext|>


<commit_before>use std::rand::{task_rng, Rng, SeedableRng, Isaac64Rng};
use std::sync::Arc;
use std::sync::deque::{BufferPool, Data, Empty, Abort};

use raytracer::compositor::{
    Surface,
    SurfaceFactory,
    ColorRGBA
};
use raytracer::Ray;
use scene::{Camera, Scene};
use vec3::Vec3;

pub struct Renderer {
    pub reflect_depth: uint,  // Maximum reflection recursions.
    pub refract_depth: uint,  // Maximum refraction recursions. A sphere takes up 2 recursions.
    pub shadow_samples: uint, // Number of samples for soft shadows and area lights.
    pub pixel_samples: uint,  // The square of this is the number of samples per pixel.
    pub tasks: uint           // Minimum number of tasks to spawn.
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Surface {

        let mut surface = Surface::new(camera.image_width as uint,
                                   camera.image_height as uint,
                                   ColorRGBA::new_rgb(0, 0, 0));

        let shared_scene = Arc::new(scene);
        let (worker, stealer) = BufferPool::new().deque();
        let (tx, rx) = channel();  // Responses

        let mut jobs = 0;
        for subsurface_factory in surface.divide(128, 8) {
            jobs += 1;
            worker.push(subsurface_factory);
        }

        for _ in range(0, self.tasks) {
            let renderer = *self.clone();
            let child_tx = tx.clone();
            let child_stealer = stealer.clone();
            let scene_local = shared_scene.clone();

            spawn(proc() {
                loop {
                    match child_stealer.steal() {
                        Data(factory) => {
                            child_tx.send(renderer.render_tile(camera,
                                                               scene_local.deref(),
                                                               factory))
                        },
                        Empty => break,
                        Abort => (),
                    }
                }
            });
        }

        let start_time = ::time::get_time();

        for i in range(0, jobs) {
            surface.merge(rx.recv());
            ::util::print_progress("Tile", start_time, (i + 1) as uint, jobs);
        }

        surface
    }

    fn render_tile(&self, camera: Camera, scene: &Scene,
                   tile_factory: SurfaceFactory) -> Box<Surface> {

        let shadow_samples = self.shadow_samples;
        let pixel_samples = self.pixel_samples;
        let reflect_depth = self.reflect_depth;
        let refract_depth = self.refract_depth;

        let mut tile = tile_factory.create();

        let mut random_data = [0u64, ..64];
        for i in range(0u, 64u) {
            random_data[i] = task_rng().next_u64();
        }
        let mut rng: Isaac64Rng = SeedableRng::from_seed(random_data.clone());

        for rel_y in range(0u, tile.height) {
            let abs_y = (camera.image_height as uint) - (tile.y_off + rel_y) - 1;
            for rel_x in range(0u, tile.width) {
                let abs_x = tile.x_off + rel_x;

                let mut color = Vec3::zero();

                // Supersampling, jitter algorithm
                let pixel_width = 1.0 / pixel_samples as f64;

                for y_subpixel in range(0, pixel_samples) {
                    for x_subpixel in range(0, pixel_samples) {
                        let mut j_x = abs_x as f64;
                        let mut j_y = abs_y as f64;

                        // Don't jitter if not antialiasing
                        if pixel_samples > 1 {
                            j_x = j_x + x_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                            j_y = j_y + y_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                        }

                        let ray = camera.get_ray(j_x, j_y);
                        let result = Renderer::trace(scene, &ray, shadow_samples, reflect_depth, refract_depth, false);
                        color = color + result.scale(1.0 / (pixel_samples * pixel_samples) as f64);
                    }
                }
                *tile.get_mut(rel_x, rel_y) =
                    ColorRGBA::new_rgb_clamped(color.x, color.y, color.z);
            }
        }

        box tile
    }

    fn trace(scene: &Scene,
             ray: &Ray,
             shadow_samples: uint,
             reflect_depth: uint,
             refract_depth: uint,
             inside: bool)
             -> Vec3 {
        if reflect_depth <= 0 || refract_depth <= 0 { return Vec3::zero() }
        let epsilon = ::std::f64::EPSILON * 10000.0;

        match ray.get_nearest_hit(scene) {
            Some(nearest_hit) => {
                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                let mut result = scene.lights.iter().fold(Vec3::zero(), |color_acc, light| {
                    let mut shadow = Vec3::zero();

                    if shadow_samples > 0 {
                        // Point light speedup
                        let shadow_sample_tries = if light.is_point() { 1 } else { shadow_samples };

                        // Take average shadow color after jittering/sampling light position
                        for _ in range(0, shadow_sample_tries) {
                            // L has to be a unit vector for t_max 1:1 correspondence to
                            // distance to light to work. Shadow feelers only search up
                            // until light source.
                            let sampled_light_position = light.position();
                            let shadow_l = (sampled_light_position - nearest_hit.position).unit();
                            let shadow_ray = Ray {origin: nearest_hit.position, direction: shadow_l};
                            let distance_to_light = (sampled_light_position - nearest_hit.position).len();

                            // Check against candidate primitives in scene for occlusion
                            // and multiply shadow color by occluders' shadow colors
                            // TODO: Clean up
                            match scene.octree {
                                Some(ref octree) => {
                                    let candidate_nodes = octree.get_intersection_objects(&shadow_ray);
                                    let mut sample_shadow = Vec3::one();

                                    for node in candidate_nodes.iter() {
                                        let ref prim = scene.prims[node.index];
                                        let occlusion = prim.intersects(&shadow_ray, epsilon, distance_to_light);

                                        match occlusion {
                                            Some(occlusion) => {
                                                sample_shadow = sample_shadow * occlusion.material.transmission()
                                            }
                                            None => {}
                                        }

                                        // Exit early if we are already black; we can't any go darker than black
                                        // How much more black could this be? None more black.
                                        if sample_shadow.x + sample_shadow.y + sample_shadow.z <= epsilon { break; }
                                    }

                                    shadow = shadow + sample_shadow;
                                }
                                None => {
                                    shadow = shadow + scene.prims.iter().fold(Vec3::one(), |shadow_acc, prim| {
                                        let occlusion = prim.intersects(&shadow_ray, epsilon, distance_to_light);
                                        match occlusion {
                                            Some(occlusion) => shadow_acc * occlusion.material.transmission(),
                                            None => shadow_acc
                                        }
                                    });
                                }
                            }
                        }

                        shadow = shadow.scale(1.0 / shadow_sample_tries as f64);
                    } else {
                        shadow = Vec3::one();
                    }

                    let l = (light.center() - nearest_hit.position).unit();

                    let u = nearest_hit.u;
                    let v = nearest_hit.v;

                    color_acc + light.color() * nearest_hit.material.sample(n, i, l, u, v) * shadow
                });

                // Global reflection
                if nearest_hit.material.is_reflective() {
                    let r = Vec3::reflect(&i, &n);
                    let reflect_ray = Ray {origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadow_samples, reflect_depth - 1, refract_depth, inside);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                // Global refraction
                if nearest_hit.material.is_refractive() {
                    let t = Vec3::refract(&i, &n, nearest_hit.material.ior(), inside);
                    let refract_ray = Ray {origin: nearest_hit.position + t.scale(epsilon), direction: t};
                    let refraction = Renderer::trace(scene, &refract_ray, shadow_samples, reflect_depth, refract_depth, !inside);

                    result = result + nearest_hit.material.global_transmissive(&refraction);
                }

                result
            }

            None => {
                match scene.skybox {
                    Some(ref skybox) => skybox.color(ray.direction),
                    None => scene.background
                }
            }
        }
    }
}
<commit_msg>Move shadow code in renderer.rs into a function.<commit_after>use std::rand::{task_rng, Rng, SeedableRng, Isaac64Rng};
use std::sync::Arc;
use std::sync::deque::{BufferPool, Data, Empty, Abort};

use raytracer::compositor::{
    Surface,
    SurfaceFactory,
    ColorRGBA
};
use raytracer::{Intersection, Ray};
use light::Light;
use scene::{Camera, Scene};
use vec3::Vec3;

pub static EPSILON: f64 = ::std::f64::EPSILON * 10000.0;

pub struct Renderer {
    pub reflect_depth: uint,  // Maximum reflection recursions.
    pub refract_depth: uint,  // Maximum refraction recursions. A sphere takes up 2 recursions.
    pub shadow_samples: uint, // Number of samples for soft shadows and area lights.
    pub pixel_samples: uint,  // The square of this is the number of samples per pixel.
    pub tasks: uint           // Minimum number of tasks to spawn.
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Surface {

        let mut surface = Surface::new(camera.image_width as uint,
                                       camera.image_height as uint,
                                       ColorRGBA::new_rgb(0, 0, 0));

        let shared_scene = Arc::new(scene);
        let (worker, stealer) = BufferPool::new().deque();
        let (tx, rx) = channel();  // Responses

        let mut jobs = 0;
        for subsurface_factory in surface.divide(128, 8) {
            jobs += 1;
            worker.push(subsurface_factory);
        }

        for _ in range(0, self.tasks) {
            let renderer = *self.clone();
            let child_tx = tx.clone();
            let child_stealer = stealer.clone();
            let scene_local = shared_scene.clone();

            spawn(proc() {
                loop {
                    match child_stealer.steal() {
                        Data(factory) => {
                            child_tx.send(renderer.render_tile(camera,
                                                               scene_local.deref(),
                                                               factory))
                        },
                        Empty => break,
                        Abort => ()
                    }
                }
            });
        }

        let start_time = ::time::get_time();

        for i in range(0, jobs) {
            surface.merge(rx.recv());
            ::util::print_progress("Tile", start_time, (i + 1) as uint, jobs);
        }

        surface
    }

    fn render_tile(&self, camera: Camera, scene: &Scene,
                   tile_factory: SurfaceFactory) -> Box<Surface> {

        let shadow_samples = self.shadow_samples;
        let pixel_samples = self.pixel_samples;
        let reflect_depth = self.reflect_depth;
        let refract_depth = self.refract_depth;

        let mut tile = tile_factory.create();

        let mut random_data = [0u64, ..64];
        for i in range(0u, 64u) {
            random_data[i] = task_rng().next_u64();
        }
        let mut rng: Isaac64Rng = SeedableRng::from_seed(random_data.clone());

        for rel_y in range(0u, tile.height) {
            let abs_y = (camera.image_height as uint) - (tile.y_off + rel_y) - 1;
            for rel_x in range(0u, tile.width) {
                let abs_x = tile.x_off + rel_x;

                let mut color = Vec3::zero();

                // Supersampling, jitter algorithm
                let pixel_width = 1.0 / pixel_samples as f64;

                for y_subpixel in range(0, pixel_samples) {
                    for x_subpixel in range(0, pixel_samples) {
                        let mut j_x = abs_x as f64;
                        let mut j_y = abs_y as f64;

                        // Don't jitter if not antialiasing
                        if pixel_samples > 1 {
                            j_x = j_x + x_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                            j_y = j_y + y_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                        }

                        let ray = camera.get_ray(j_x, j_y);
                        let result = Renderer::trace(scene, &ray, shadow_samples, reflect_depth, refract_depth, false);
                        color = color + result.scale(1.0 / (pixel_samples * pixel_samples) as f64);
                    }
                }
                *tile.get_mut(rel_x, rel_y) = ColorRGBA::new_rgb_clamped(color.x, color.y, color.z);
            }
        }

        box tile
    }

    fn trace(scene: &Scene, ray: &Ray, shadow_samples: uint,
             reflect_depth: uint, refract_depth: uint, inside: bool) -> Vec3 {

        if reflect_depth <= 0 || refract_depth <= 0 { return Vec3::zero() }

        match ray.get_nearest_hit(scene) {
            Some(nearest_hit) => {
                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                let mut result = scene.lights.iter().fold(Vec3::zero(), |color_acc, light| {
                    let shadow = Renderer::shadow_intensity(scene, &nearest_hit, light, shadow_samples);
                    let l = (light.center() - nearest_hit.position).unit();
                    let u = nearest_hit.u;
                    let v = nearest_hit.v;

                    color_acc + light.color() * nearest_hit.material.sample(n, i, l, u, v) * shadow
                });

                // Global reflection
                if nearest_hit.material.is_reflective() {
                    let r = Vec3::reflect(&i, &n);
                    let reflect_ray = Ray {origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadow_samples,
                                                     reflect_depth - 1, refract_depth, inside);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                // Global refraction
                if nearest_hit.material.is_refractive() {
                    let t = Vec3::refract(&i, &n, nearest_hit.material.ior(), inside);
                    let refract_ray = Ray {origin: nearest_hit.position + t.scale(EPSILON), direction: t};
                    let refraction = Renderer::trace(scene, &refract_ray, shadow_samples,
                                                     reflect_depth, refract_depth, !inside);

                    result = result + nearest_hit.material.global_transmissive(&refraction);
                }

                result
            }

            None => {
                match scene.skybox {
                    Some(ref skybox) => skybox.color(ray.direction),
                    None => scene.background
                }
            }
        }
    }

    fn shadow_intensity(scene: &Scene, nearest_hit: &Intersection,
                        light: &Box<Light+Send+Share>, shadow_samples: uint) -> Vec3 {

        if shadow_samples <= 0 { return Vec3::one(); }

        // Point light speedup (no point in sampling a point light multiple times)
        let shadow_sample_tries = if light.is_point() { 1 } else { shadow_samples };
        let mut shadow = Vec3::zero();

        // Take average shadow color after jittering/sampling light position
        for _ in range(0, shadow_sample_tries) {
            // L has to be a unit vector for t_max 1:1 correspondence to
            // distance to light to work. Shadow feelers only search up
            // until light source.
            let sampled_light_position = light.position();
            let shadow_l = (sampled_light_position - nearest_hit.position).unit();
            let shadow_ray = Ray {origin: nearest_hit.position, direction: shadow_l};
            let distance_to_light = (sampled_light_position - nearest_hit.position).len();

            // Check against candidate primitives in scene for occlusion
            // and multiply shadow color by occluders' shadow colors
            // TODO: Clean up
            match scene.octree {
                Some(ref octree) => {
                    let candidate_nodes = octree.get_intersection_objects(&shadow_ray);
                    let mut sample_shadow = Vec3::one();

                    for node in candidate_nodes.iter() {
                        let ref prim = scene.prims[node.index];
                        let occlusion = prim.intersects(&shadow_ray, EPSILON, distance_to_light);
                        match occlusion {
                            Some(occlusion) => sample_shadow = sample_shadow * occlusion.material.transmission(),
                            None => {}
                        }

                        // Exit early if we are already black; we can't any go darker than black
                        // How much more black could this be? None more black.
                        if sample_shadow.x + sample_shadow.y + sample_shadow.z <= EPSILON { break; }
                    }

                    shadow = shadow + sample_shadow;
                }
                None => {
                    shadow = shadow + scene.prims.iter().fold(Vec3::one(), |shadow_acc, prim| {
                        let occlusion = prim.intersects(&shadow_ray, EPSILON, distance_to_light);
                        match occlusion {
                            Some(occlusion) => shadow_acc * occlusion.material.transmission(),
                            None => shadow_acc
                        }
                    });
                }
            }
        }

        shadow.scale(1.0 / shadow_sample_tries as f64)
    }
}
<|endoftext|>


<commit_before>#[feature(globs)];
#[feature(macro_rules)];
#[feature(default_type_params)];
#[allow(dead_code)];

use r3d::gl::*;
use r3d::vecmath::*;
use std::vec_ng::Vec;
use std::io;
use std::intrinsics::{size_of,offset};
use std::libc::*;
use std::f32;
//use std::c_str::*;
mod r3d;

// graphical test main, immiediate debug lines

fn draw_line(&(x0,y0,z0):&(f32,f32,f32),&(x1,y1,z1):&(f32,f32,f32)) {
	unsafe {
		glBegin(GL_LINES);
		glVertex3f(x0,y0,z0); glVertex3f(x1,y1,z1);
		glEnd();
	}
}
fn v3isometric(&(x,y,z):&BspVec3)->BspVec3 {(x+y,z+(x-y)*0.5, z)}

fn draw_line_iso(v0:&BspVec3,v1:&BspVec3,scale:f32) {
	draw_line(&v3isometric(&v3scale(v0,scale)),&v3isometric(&v3scale(v1,scale)))
}

pub fn main()
{
	unsafe {
		let mut argc:c_int=0;
		let argv:Vec<*c_char> =Vec::new();
		glutInit((&mut argc) as *mut c_int,0 as **c_char );
		//::macros::test();

		glutInitDisplayMode(GLUT_RGBA);
		glutInitWindowSize(1024,1024);
		let win=glutCreateWindow("testbed".to_c_str().unwrap());

		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		let bsp=Blob::<BspHeader>::read(&Path::new("data/e1m1.bsp"));
//		bsp.dump();
		let mut a=0.0;

		bsp.draw_edges();
		glFlush();

		while true {
			use std::f32;
			glutMainLoopEvent();
		}
	}
}

struct Blob<HEADER> {
	data:~[u8],
}

impl<T> std::ops::Deref<T> for Blob<T> {
	fn deref<'s>(&'s self)->&'s T {
		unsafe {	&*(&self.data[0] as *u8 as *T)
		}
	}
}

impl<T> Blob<T> {
	fn num_bytes(&self) -> uint { self.data.len() }

	fn read(path:&Path)->Blob<T> {
		let data=
			match io::File::open(path).read_to_end() {
				Ok(data)=>{
					println!("read {} {} bytes", /*path_to_str*/path.as_str().unwrap_or(""), data.len());
					data
				},
				Err(E)=>{
					println!("failed to read {}", path.as_str().unwrap_or(""));
					//~[0,..intrinsics::size_of::<Header>()]		// still returns an empty object, hmmm.
					//vec::from_elem(0,intrinsics::size_of::<Header>())
					~[]
				}
			};
		Blob::<T>  {data:data}
	}
}

pub struct DEntry<Header, T> {
	// we got a nasty bug passing wrong base ptr without header typeinfo here
	// &self instead of self..
	offset:u32,
	size:u32
}
impl<Header,T> DEntry<Header,T> {
	fn len(&self)->uint { unsafe {self.size as uint /  size_of::<T>()} }
	fn get<'a>(&'a self, owner:&'a Header,i:uint) -> &'a T{
		unsafe {
			&*(((owner as *Header as *u8).offset(self.offset as int) as *T).offset(i as int))
		}
	}
}
pub type BspDEntry<T> =DEntry<BspHeader,T>;
pub struct BspHeader {
	version:u32,
	entities:BspDEntry<Entity>,
	planes:BspDEntry<Plane>,
	miptex:BspDEntry<MipTex>,
	vertices:BspDEntry<BspVec3>,
	visibility:BspDEntry<VisiList>,
	nodes:BspDEntry<BspNode>,
	texinfo:BspDEntry<TextureInfo>,
	faces:BspDEntry<i16>,
	lightmaps:BspDEntry<LightMap>,
	clipnodes:BspDEntry<ClipNode>,
	leafs:BspDEntry<BspLeaf>,
	lface:BspDEntry<Face>,
	edges:BspDEntry<Edge>,
	surfedges:BspDEntry<i16>,
	models:BspDEntry<Model>
}

impl BspHeader {
	fn dump_vertices(&self) {
		println!("{}",self.vertices.len());
		let mut i:uint=0;
		let vtlen=self.vertices.len();
		while i<vtlen {
			let vtref= self.vertices.get(self,i as uint);
			println!("vertex{}/{}:owner={:p} vertex= {:p} ,({},{},{})",
				i,vtlen, self, vtref,
				vtref.val0(),vtref.val1(),vtref.val2());
			i+=1;
			let v=*vtref;
		}
		println!("{:p}, {:p}, {:p}",
			self.vertices.get(self,0),
			self.vertices.get(self,1),
			self.vertices.get(self,2));

	}
	fn dump(&self) {
		println!("vertices: {:u}", self.vertices.len());
		self.dump_vertices();
	}
	fn draw_edges(&self) {
		let mut i=0u;
		while i < self.edges.len() {
			let e= self.edges.get(self,i);
			let v0 = self.vertices.get(self, e.vertex0 as uint);
			let v1 = self.vertices.get(self, e.vertex1 as uint);
			let scale=1.0f32/3000.0f32;
			draw_line_iso(v0,v1,scale);
			i+=1;
		}
	}
	fn draw_faces(&self) {
		for i in range(0,self.faces.len()) {
//			let face=
		}
	}
}

// minimal tuple vmath
pub fn v3scale(&(x,y,z):&BspVec3,s:f32)->BspVec3 {	(x*s,y*s,z*s)}
pub fn v3add(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 {	(x0+x1,y0+y1,z0+z1)}
pub fn v3sub(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 {	(x0-x1,y0-y1,z0-z1)}
pub fn v3mad(v0:&BspVec3,v1:&BspVec3,f:f32)->BspVec3 { v3add(v0,&v3scale(v1,f))}
pub fn v3lerp(v0:&BspVec3,v1:&BspVec3,f:f32)->BspVec3 { v3add(v0,&v3scale(&v3sub(v1,v0),f))}
pub fn v3dot(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->f32 {	x0*x1+y0*y1+z0*z1}
pub fn v3cross(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 { ((y0*z1-z0*y1),(z0*x1-z1*x0),(x0*y1-x1*y0)) }
pub fn v3norm(v0:&BspVec3)->BspVec3{ v3scale(v0,1.0/f32::sqrt(v3dot(v0,v0))) }

pub type Point3s=(i16,i16,i16);
pub type BBox=(Point3s,Point3s);
pub struct Entity;
pub struct Plane {
	normal:BspVec3,
	dist:f32,
	plane_type:u32	// 0,1,2 = axial planes x,y,z; 3,4,5 = x,y,z predominant..
}
pub struct MipTex {
	name:[c_char,..16],
	width:u32, height:u32, offset1:u32, offset2:u32, offset4:u32, offset8:u32
}
pub struct MipHeader {
	numtex:u32,
}
impl MipHeader {
	pub unsafe fn tex_offsets(&self)->*u32 {
		(self as *_).offset(1) as *u32
	}
	pub unsafe fn tex_offset(&self, i:int)->u32 {
		let ofs=self.tex_offsets();
		*ofs.offset(i)
	}
	pub fn get_texture(&self, i:int)->&MipTex {
		unsafe {
			&*((self as *_ as *u8).offset( self.tex_offset(i) as int ) as *MipTex)
		}
	}
}

pub type BspVec3=(f32,f32,f32);
pub struct VisiList;
pub struct BspNode {
	plane_id:u32,
	priv children:[i16,..2],
	bbox:BBox,
	firstface:u16,
	numfaces:u16
}
enum BspNodeChild {
	ChildNode(i16),ChildLeaf(i16)
}
impl BspNode {
	pub fn child_node(&self, i:int)->BspNodeChild {
		match self.children[i] {
			x if x>=0 => ChildNode(x),
			x  =>ChildLeaf(-(self.children[i]+1))
		}
	}
}

pub struct TextureInfo {
	axis_s:BspVec3, ofs_s:f32,
	axis_t:BspVec3, ofs_t:f32,
	miptex:int,
	flags:int
}
pub struct Faces;
pub struct LightMap; //{ 	texels:[u8]} ??
pub struct ClipNode {
	planenum:u32,
	front:u16, back:u16,
}
pub struct BspLeaf {
	contents:u32,
	visofs:u32,
	min:Point3s,
	max:Point3s,
	firstmarksurface:u16,
	nummarksurfaces:u16,
	ambient_level:[u8,..AmbientNum]
}

pub struct Edge {
	vertex0:u16,vertex1:u16
}

enum Max{
	MaxMapHulls=4
}
static AmbientNum:int = 4;
enum Ambient {
	AmbientWater=0,AmbientSky,AmbientSlime,AmbientLava
}

pub struct Model {
	bound:BBox,
	origin:BspVec3,
	headnode:[i32,..MaxMapHulls],
	visileafs:i32,
	firstface:i32,
	numfaces:i32

}
pub struct Face {
	plane:u16,
	side:u16,
	firstedge:i32,
	num_edges:u16,
	texinfo:u16,
//	typelight:u8,
//	baselight:u8,
	light:[u8,..2],
	lightmap_ofs:i32, // [styles*sursize] samples..
}

<commit_msg>got face triangle traversal ok<commit_after>#[feature(globs)];
#[feature(macro_rules)];
#[feature(default_type_params)];
#[allow(dead_code)];

use r3d::gl::*;
use r3d::vecmath::*;
use std::vec_ng::Vec;
use std::io;
use std::intrinsics::{size_of,offset};
use std::libc::*;
use std::f32;
//use std::c_str::*;
mod r3d;
//mod macros;

// graphical test main, immiediate debug lines

fn draw_line(&(x0,y0,z0):&(f32,f32,f32),&(x1,y1,z1):&(f32,f32,f32), color:u32) {
	unsafe {
		glBegin(GL_LINES);
		gl_color(color);
		glVertex3f(x0,y0,z0); glVertex3f(x1,y1,z1);
		glEnd();
	}
}
fn v3isometric(&(x,y,z):&BspVec3)->BspVec3 {(x+y,z+(x-y)*0.5, z)}

fn draw_line_iso(v0:&BspVec3,v1:&BspVec3,color:u32, scale:f32) {
	draw_line(&v3isometric(&v3scale(v0,scale)),&v3isometric(&v3scale(v1,scale)), color)
}
unsafe fn gl_vertex_v3(&(x,y,z):&BspVec3) {
	glVertex3f(x,y,z);
}
unsafe fn gl_color(color:u32) {
	let r=(color)&255;
	let g=(color>>8)&255;
	let b=(color>>16)&255;
	glColor3f(r as f32 *(1.0/255.0),g as f32 *(1.0/255.0),b as f32 *(1.0/255.0));
}
fn draw_tri_iso(v0:&BspVec3,v1:&BspVec3,v2:&BspVec3,color:u32, scale:f32 ) {
	let tv0=v3isometric(&v3scale(v0,scale));
	let tv1=v3isometric(&v3scale(v1,scale));
	let tv2=v3isometric(&v3scale(v2,scale));
	unsafe {
		glBegin(GL_TRIANGLES);
		gl_color(color);
		gl_vertex_v3(&tv0);
		gl_vertex_v3(&tv1);
		gl_vertex_v3(&tv2);
		glEnd();
	}

}

pub fn main()
{
	unsafe {
		let mut argc:c_int=0;
		let argv:Vec<*c_char> =Vec::new();
		glutInit((&mut argc) as *mut c_int,0 as **c_char );
		//::macros::test();

		glutInitDisplayMode(GLUT_RGBA);
		glutInitWindowSize(1024,1024);
		let win=glutCreateWindow("testbed".to_c_str().unwrap());

		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		let bsp=Blob::<BspHeader>::read(&Path::new("data/e1m1.bsp"));
//		bsp.dump();
		let mut a=0.0;

		bsp.draw_faces();
		bsp.draw_edges();
//		bsp.draw_all_surface_edges();
		glFlush();

		while true {
			use std::f32;
			glutMainLoopEvent();
		}
	}
}

struct Blob<HEADER> {
	data:~[u8],
}

impl<T> std::ops::Deref<T> for Blob<T> {
	fn deref<'s>(&'s self)->&'s T {
		unsafe {	&*(&self.data[0] as *u8 as *T)
		}
	}
}

impl<T> Blob<T> {
	fn num_bytes(&self) -> uint { self.data.len() }

	fn read(path:&Path)->Blob<T> {
		let data=
			match io::File::open(path).read_to_end() {
				Ok(data)=>{
					println!("read {} {} bytes", /*path_to_str*/path.as_str().unwrap_or(""), data.len());
					data
				},
				Err(E)=>{
					println!("failed to read {}", path.as_str().unwrap_or(""));
					//~[0,..intrinsics::size_of::<Header>()]		// still returns an empty object, hmmm.
					//vec::from_elem(0,intrinsics::size_of::<Header>())
					~[]
				}
			};
		Blob::<T>  {data:data}
	}
}

pub struct DEntry<Header, T> {
	// we got a nasty bug passing wrong base ptr without header typeinfo here
	// &self instead of self..
	offset:u32,
	size:u32
}
impl<Header,T> DEntry<Header,T> {
	fn len(&self)->uint { unsafe {self.size as uint /  size_of::<T>()} }
	fn get<'a>(&'a self, owner:&'a Header,i:uint) -> &'a T{
		unsafe {
			&*(((owner as *Header as *u8).offset(self.offset as int) as *T).offset(i as int))
		}
	}
}
pub type BspDEntry<T> =DEntry<BspHeader,T>;
pub struct BspHeader {
	version:u32,
	entities:BspDEntry<Entity>,
	planes:BspDEntry<Plane>,

	miptex:BspDEntry<MipTex>,
	vertices:BspDEntry<BspVec3>,

	visibility:BspDEntry<VisiList>,
	nodes:BspDEntry<BspNode>,

	texinfo:BspDEntry<TextureInfo>,

	faces:BspDEntry<Face>,

	lightmaps:BspDEntry<LightMap>,
	clipnodes:BspDEntry<ClipNode>,

	leafs:BspDEntry<BspLeaf>,

	marksurfaces:BspDEntry<i16>, //? no
	edges:BspDEntry<Edge>,

	surfedges:BspDEntry<i32>, // ? no
	models:BspDEntry<Model>
}

impl BspHeader {
	fn dump_vertices(&self) {
		println!("{}",self.vertices.len());
		let mut i:uint=0;
		let vtlen=self.vertices.len();
		while i<vtlen {
			let vtref= self.vertices.get(self,i as uint);
			println!("vertex{}/{}:owner={:p} vertex= {:p} ,({},{},{})",
				i,vtlen, self, vtref,
				vtref.val0(),vtref.val1(),vtref.val2());
			i+=1;
			let v=*vtref;
		}
		println!("{:p}, {:p}, {:p}",
			self.vertices.get(self,0),
			self.vertices.get(self,1),
			self.vertices.get(self,2));

	}
	fn dump(&self) {
		println!("vertices: {:u}", self.vertices.len());
		self.dump_vertices();
	}
	fn draw_edges(&self) {
		let scale=1.0f32/3000.0f32;
		let mut i=0u;
		while i < self.edges.len() {
			let e= self.edges.get(self,i);
			let v0 = self.vertices.get(self, e.vertex0 as uint);
			let v1 = self.vertices.get(self, e.vertex1 as uint);
			draw_line_iso(v0,v1,0xffffff, scale);
			i+=1;
		}
	}
	fn draw_faces(&self) {
		let scale=1.0f32/3000.0f32;

		for i in range(0,self.faces.len()) {
			let face=self.faces.get(self, i);
			let eii = face.firstedge;
			let first_ei= *self.surfedges.get(self, eii as uint);
			let first_edge=if first_ei>=0 {self.edges.get(self,first_ei as uint)} else {self.edges.get(self,-first_ei as uint)};
			let first_vertex=if first_ei>=0 {first_edge.vertex0}else{first_edge.vertex1};
			let vfirst = self.vertices.get(self, first_vertex as uint);

			for esubi in range(0, face.num_edges) {
				let ei = *self.surfedges.get(self, (eii+esubi as i32) as uint);
				let edge=self.edges.get(self, ei as uint);
				let (v0,v1)=if ei>0 {
					let edge=self.edges.get(self, ei as uint);
					(	self.vertices.get(self, edge.vertex0 as uint),
						self.vertices.get(self, edge.vertex1 as uint)
					)
				} else {
					let edge=self.edges.get(self, -ei as uint);
					(	self.vertices.get(self, edge.vertex1 as uint),
						self.vertices.get(self, edge.vertex0 as uint)
					)
				};
				draw_tri_iso(vfirst, v0,v1, (((i^ i <<13)*i)^(i<<13)) as u32, scale);
//				draw_line_iso(v0,v1,scale);
			}
		}
	}
	fn draw_all_surface_edges(&self)
	{
		for i in range(0, self.surfedges.len()) {
			//let mut ei=self.edgelist.get(self, i);

//			let edge = self.edges.get(self, ei);
			self.draw_edge(*(self.surfedges.get(self, i))  as int);
		}
	}
	fn draw_edge(&self, mut ei:int) {
		let scale=1.0f32/3000.0f32;
		if ei<0 {ei=-ei}
		let edge=self.edges.get(self, ei as uint);
		let v0 = self.vertices.get(self, edge.vertex0 as uint);
		let v1 = self.vertices.get(self, edge.vertex1 as uint);
		draw_line_iso(v0,v1,0xffffff, scale);
	}
}

// minimal tuple vmath
pub fn v3scale(&(x,y,z):&BspVec3,s:f32)->BspVec3 {	(x*s,y*s,z*s)}
pub fn v3add(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 {	(x0+x1,y0+y1,z0+z1)}
pub fn v3sub(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 {	(x0-x1,y0-y1,z0-z1)}
pub fn v3mad(v0:&BspVec3,v1:&BspVec3,f:f32)->BspVec3 { v3add(v0,&v3scale(v1,f))}
pub fn v3lerp(v0:&BspVec3,v1:&BspVec3,f:f32)->BspVec3 { v3add(v0,&v3scale(&v3sub(v1,v0),f))}
pub fn v3dot(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->f32 {	x0*x1+y0*y1+z0*z1}
pub fn v3cross(&(x0,y0,z0):&BspVec3,&(x1,y1,z1):&BspVec3)->BspVec3 { ((y0*z1-z0*y1),(z0*x1-z1*x0),(x0*y1-x1*y0)) }
pub fn v3norm(v0:&BspVec3)->BspVec3{ v3scale(v0,1.0/f32::sqrt(v3dot(v0,v0))) }

pub type Point3s=(i16,i16,i16);
pub type BBox=(Point3s,Point3s);
pub struct Entity;
pub struct Plane {
	normal:BspVec3,
	dist:f32,
	plane_type:u32	// 0,1,2 = axial planes x,y,z; 3,4,5 = x,y,z predominant..
}
pub struct MipTex {
	name:[c_char,..16],
	width:u32, height:u32, offset1:u32, offset2:u32, offset4:u32, offset8:u32
}
pub struct MipHeader {
	numtex:u32,
}
impl MipHeader {
	pub unsafe fn tex_offsets(&self)->*u32 {
		(self as *_).offset(1) as *u32
	}
	pub unsafe fn tex_offset(&self, i:int)->u32 {
		let ofs=self.tex_offsets();
		*ofs.offset(i)
	}
	pub fn get_texture(&self, i:int)->&MipTex {
		unsafe {
			&*((self as *_ as *u8).offset( self.tex_offset(i) as int ) as *MipTex)
		}
	}
}

pub type BspVec3=(f32,f32,f32);
pub struct VisiList;
pub struct BspNode {
	plane_id:u32,
	priv children:[i16,..2],
	bbox:BBox,
	firstface:u16,
	numfaces:u16
}
enum BspNodeChild {
	ChildNode(i16),ChildLeaf(i16)
}
impl BspNode {
	pub fn child_node(&self, i:int)->BspNodeChild {
		match self.children[i] {
			x if x>=0 => ChildNode(x),
			x  =>ChildLeaf(-(self.children[i]+1))
		}
	}
}

pub struct TextureInfo {
	axis_s:BspVec3, ofs_s:f32,
	axis_t:BspVec3, ofs_t:f32,
	miptex:int,
	flags:int
}
pub struct Faces;
pub struct LightMap; //{ 	texels:[u8]} ??
pub struct ClipNode {
	planenum:u32,
	front:u16, back:u16,
}
pub struct BspLeaf {
	contents:u32,
	visofs:u32,
	min:Point3s,
	max:Point3s,
	firstmarksurface:u16,
	nummarksurfaces:u16,
	ambient_level:[u8,..AmbientNum]
}

pub struct Edge {
	vertex0:u16,vertex1:u16
}

enum Max{
	MaxMapHulls=4
}
static AmbientNum:int = 4;
enum Ambient {
	AmbientWater=0,AmbientSky,AmbientSlime,AmbientLava
}

pub struct Model {
	bound:BBox,
	origin:BspVec3,
	headnode:[i32,..MaxMapHulls],
	visileafs:i32,
	firstface:i32,
	numfaces:i32

}
pub struct Face {
	plane:u16,
	side:u16,
	firstedge:i32,
	num_edges:u16,
	texinfo:u16,
//	typelight:u8,
//	baselight:u8,
	light:[u8,..2],
	lightmap_ofs:i32, // [styles*sursize] samples..
}

<|endoftext|>