<commit_before>//! Write las points.

use {Header, Point, Result};
use point::Format;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The point format has color, but the point doesn't.
        MissingColor(format: Format, point: Point) {
            description("the point format has color, but the point doesn't")
            display("point format {} has color, but point {:?} doesn't", format, point)
        }
        /// The point format has extra bytes, but the point doesn't.
        MissingExtraBytes(format: Format, point: Point) {
            description("the point format has extra bytes, but the point doesn't")
            display("point format {} has {} extra bytes, but point {:?} has {}", format, format.extra_bytes, point, point.extra_bytes.len())
        }
        /// The point format has gps time, but the point doesn't.
        MissingGpsTime(format: Format, point: Point) {
            description("the point format has gps time, but the point doesn't")
            display("point format {} has gps time, but point {:?} doesn't", format, point)
        }
        /// The point format has nir, but the point doesn't.
        MissingNir(format: Format, point: Point) {
            description("the point format has nir, but the point doesn't")
            display("point format {} has nir, but point {:?} doesn't", format, point)
        }
        /// The point format has waveform, but the point doesn't.
        MissingWaveform(format: Format, point: Point) {
            description("the point format has waveform, but the point doesn't")
            display("point format {} has waveform, but point {:?} doesn't", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// # use las::Writer;
/// {
///     let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        header.bounds = Default::default();
        header.number_of_points = 0;
        header.number_of_points_by_return = HashMap::new();
        if header.version.requires_point_data_start_signature() {
            // TODO we shouldn't overwrite the old vlr padding
            header.vlr_padding = ::raw::POINT_DATA_START_SIGNATURE.to_vec();
        }
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs().iter() {
            (*vlr).clone().into_raw(false).and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding.is_empty() {
            write.write_all(&header.vlr_padding)?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    ///
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        // TODO check if point has color but format doesn't
        if self.closed {
            return Err(Error::Closed.into());
        }
        if self.header.point_format.has_gps_time && point.gps_time.is_none() {
            return Err(
                Error::MissingGpsTime(self.header.point_format, point).into(),
            );
        }
        if self.header.point_format.has_color && point.color.is_none() {
            return Err(Error::MissingColor(self.header.point_format, point).into());
        }
        if self.header.point_format.has_nir && point.nir.is_none() {
            return Err(Error::MissingNir(self.header.point_format, point).into());
        }
        if self.header.point_format.has_waveform && point.waveform.is_none() {
            return Err(
                Error::MissingWaveform(self.header.point_format, point).into(),
            );
        }
        if self.header.point_format.extra_bytes as usize != point.extra_bytes.len() {
            return Err(
                Error::MissingExtraBytes(self.header.point_format, point).into(),
            );
        }
        self.header.number_of_points += 1;
        {
            let entry = self.header
                .number_of_points_by_return
                .entry(point.return_number)
                .or_insert(0);
            *entry += 1;
        }
        self.header.bounds.grow(&point);
        point.into_raw(self.header.transforms).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format)
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// A second call to close is a no-op.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.close().unwrap();
    /// writer.close().unwrap(); // <- no-op
    ///
    pub fn close(&mut self) -> Result<()> {
        if !self.closed {
            for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
                evlr.clone().into_raw(true)
            })
            {
                raw_evlr?.write_to(&mut self.write)?;
            }
            self.write.seek(SeekFrom::Start(0))?;
            self.header.clone().into_raw().and_then(|raw_header| {
                raw_header.write_to(&mut self.write)
            })?;
            self.closed = true;
        }
        Ok(())
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {Header, Version};
    use byteorder::{LittleEndian, ReadBytesExt};
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut header = Header::default();
        header.point_format = format;
        header.version = version;
        Writer::new(Cursor::new(Vec::new()), header).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut header = Header::default();
            header.version = (1, 0).into();
            header.push_vlr(Default::default());
            let mut writer = Writer::new(&mut cursor, header).unwrap();
            writer.write(Default::default()).unwrap();
        }
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
        writer.close().unwrap();
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }
}
<commit_msg>Writer documentation<commit_after>//! Write las points.
//!
//! A `Writer` uses a `Header` for its configuration:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header};
//! let mut header = Header::default();
//! header.version = (1, 4).into();
//! let writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//! ```
//!
//! The set of optional fields on the point format and the points must match exactly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header, Point};
//! use las::point::Format;
//! use las::Color;
//!
//! let mut header = Header::default();
//! header.point_format = Format::new(1).unwrap();
//! let mut writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//!
//! let mut point = Point::default(); // default points don't have any optional attributes
//! assert!(writer.write(point.clone()).is_err());
//!
//! point.gps_time = Some(42.); // point format 1 requires gps time
//! writer.write(point.clone()).unwrap();
//!
//! point.color = Some(Color::new(1, 2, 3));
//! assert!(writer.write(point).is_err()); // the point's color would be lost
//! ```

use {Header, Point, Result};
use point::Format;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The point format has color, but the point doesn't.
        MissingColor(format: Format, point: Point) {
            description("the point format has color, but the point doesn't")
            display("point format {} has color, but point {:?} doesn't", format, point)
        }
        /// The point format has extra bytes, but the point doesn't.
        MissingExtraBytes(format: Format, point: Point) {
            description("the point format has extra bytes, but the point doesn't")
            display("point format {} has {} extra bytes, but point {:?} has {}", format, format.extra_bytes, point, point.extra_bytes.len())
        }
        /// The point format has gps time, but the point doesn't.
        MissingGpsTime(format: Format, point: Point) {
            description("the point format has gps time, but the point doesn't")
            display("point format {} has gps time, but point {:?} doesn't", format, point)
        }
        /// The point format has nir, but the point doesn't.
        MissingNir(format: Format, point: Point) {
            description("the point format has nir, but the point doesn't")
            display("point format {} has nir, but point {:?} doesn't", format, point)
        }
        /// The point format has waveform, but the point doesn't.
        MissingWaveform(format: Format, point: Point) {
            description("the point format has waveform, but the point doesn't")
            display("point format {} has waveform, but point {:?} doesn't", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// # use las::Writer;
/// {
///     let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        header.bounds = Default::default();
        header.number_of_points = 0;
        header.number_of_points_by_return = HashMap::new();
        if header.version.requires_point_data_start_signature() {
            // TODO we shouldn't overwrite the old vlr padding
            header.vlr_padding = ::raw::POINT_DATA_START_SIGNATURE.to_vec();
        }
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs().iter() {
            (*vlr).clone().into_raw(false).and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding.is_empty() {
            write.write_all(&header.vlr_padding)?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    ///
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        // TODO check if point has color but format doesn't
        if self.closed {
            return Err(Error::Closed.into());
        }
        if self.header.point_format.has_gps_time && point.gps_time.is_none() {
            return Err(
                Error::MissingGpsTime(self.header.point_format, point).into(),
            );
        }
        if self.header.point_format.has_color && point.color.is_none() {
            return Err(Error::MissingColor(self.header.point_format, point).into());
        }
        if self.header.point_format.has_nir && point.nir.is_none() {
            return Err(Error::MissingNir(self.header.point_format, point).into());
        }
        if self.header.point_format.has_waveform && point.waveform.is_none() {
            return Err(
                Error::MissingWaveform(self.header.point_format, point).into(),
            );
        }
        if self.header.point_format.extra_bytes as usize != point.extra_bytes.len() {
            return Err(
                Error::MissingExtraBytes(self.header.point_format, point).into(),
            );
        }
        self.header.number_of_points += 1;
        {
            let entry = self.header
                .number_of_points_by_return
                .entry(point.return_number)
                .or_insert(0);
            *entry += 1;
        }
        self.header.bounds.grow(&point);
        point.into_raw(self.header.transforms).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format)
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// A second call to close is a no-op.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.close().unwrap();
    /// writer.close().unwrap(); // <- no-op
    ///
    pub fn close(&mut self) -> Result<()> {
        if !self.closed {
            for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
                evlr.clone().into_raw(true)
            })
            {
                raw_evlr?.write_to(&mut self.write)?;
            }
            self.write.seek(SeekFrom::Start(0))?;
            self.header.clone().into_raw().and_then(|raw_header| {
                raw_header.write_to(&mut self.write)
            })?;
            self.closed = true;
        }
        Ok(())
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {Header, Version};
    use byteorder::{LittleEndian, ReadBytesExt};
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut header = Header::default();
        header.point_format = format;
        header.version = version;
        Writer::new(Cursor::new(Vec::new()), header).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut header = Header::default();
            header.version = (1, 0).into();
            header.push_vlr(Default::default());
            let mut writer = Writer::new(&mut cursor, header).unwrap();
            writer.write(Default::default()).unwrap();
        }
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
        writer.close().unwrap();
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }
}
<|endoftext|>


<commit_before><commit_msg>mouse selection<commit_after><|endoftext|>


<commit_before><commit_msg>Fix prefix filter<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::DOMStringMapBinding;
use dom::bindings::codegen::Bindings::DOMStringMapBinding::DOMStringMapMethods;
use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::htmlelement::HTMLElement;
use dom::node::window_from_node;
use util::str::DOMString;

#[dom_struct]
pub struct DOMStringMap {
    reflector_: Reflector,
    element: JS<HTMLElement>,
}

impl DOMStringMap {
    fn new_inherited(element: &HTMLElement) -> DOMStringMap {
        DOMStringMap {
            reflector_: Reflector::new(),
            element: JS::from_ref(element),
        }
    }

    pub fn new(element: &HTMLElement) -> Root<DOMStringMap> {
        let window = window_from_node(element);
        reflect_dom_object(box DOMStringMap::new_inherited(element),
                           GlobalRef::Window(window.r()),
                           DOMStringMapBinding::Wrap)
    }
}

// https://html.spec.whatwg.org/multipage/#domstringmap
impl DOMStringMapMethods for DOMStringMap {
    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
    fn NamedDeleter(&self, name: DOMString) {
        self.element.delete_custom_attr(name)
    }

    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem
    fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
        self.element.set_custom_attr(name, value)
    }

    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString {
        match self.element.get_custom_attr(name) {
            Some(value) => {
                *found = true;
                value.clone()
            },
            None => {
                *found = false;
                DOMString::new()
            }
        }
    }

    // https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.element.supported_prop_names_custom_attr().iter().cloned().collect()
    }
}
<commit_msg>Auto merge of #9161 - frewsxcv:cleanup-match, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::DOMStringMapBinding;
use dom::bindings::codegen::Bindings::DOMStringMapBinding::DOMStringMapMethods;
use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::htmlelement::HTMLElement;
use dom::node::window_from_node;
use util::str::DOMString;

#[dom_struct]
pub struct DOMStringMap {
    reflector_: Reflector,
    element: JS<HTMLElement>,
}

impl DOMStringMap {
    fn new_inherited(element: &HTMLElement) -> DOMStringMap {
        DOMStringMap {
            reflector_: Reflector::new(),
            element: JS::from_ref(element),
        }
    }

    pub fn new(element: &HTMLElement) -> Root<DOMStringMap> {
        let window = window_from_node(element);
        reflect_dom_object(box DOMStringMap::new_inherited(element),
                           GlobalRef::Window(window.r()),
                           DOMStringMapBinding::Wrap)
    }
}

// https://html.spec.whatwg.org/multipage/#domstringmap
impl DOMStringMapMethods for DOMStringMap {
    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
    fn NamedDeleter(&self, name: DOMString) {
        self.element.delete_custom_attr(name)
    }

    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem
    fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
        self.element.set_custom_attr(name, value)
    }

    // https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString {
        let attr = self.element.get_custom_attr(name);
        *found = attr.is_some();
        attr.unwrap_or_default()
    }

    // https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.element.supported_prop_names_custom_attr().iter().cloned().collect()
    }
}
<|endoftext|>


<commit_before>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        const float CLOUD_HEIGHT = 1000;

        uniform vec2 window_size;
        uniform vec3 sun_color;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        void main() {{
          vec3 direction = pixel_direction(gl_FragCoord.xy);
          float dist = (CLOUD_HEIGHT - eye_position.y) / direction.y;
          vec4 fog_color = vec4(sun_color, 1);
          if (dist <= 0 || dist > 1000000) {{
            frag_color = fog_color;
          }} else {{
            vec3 seed = (eye_position + dist * direction) / CLOUD_HEIGHT * vec3(1, 4, 1);
            float f = cnoise(seed);
            // squish away from 0
            f = sign(f) * pow(abs(f), 12.0/16);
            // to [0, 1]
            f = f / 2 + 0.5;
            // squish towards 0
            f = pow(f, 4);
            vec4 sky_color = vec4(mix(sun_color, vec3(1, 1, 1), f), 1);
            frag_color = apply_fog(sky_color, fog_color, dist / 8);
          }}
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<commit_msg>two cloud layers<commit_after>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        uniform vec2 window_size;
        uniform vec3 sun_color;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        float cloud_noise(vec3 seed) {{
          float f = cnoise(seed);
          // to [0, 1]
          f = f / 2 + 0.5;
          return f;
        }}

        void main() {{
          vec3 direction = pixel_direction(gl_FragCoord.xy);
          const int HEIGHTS = 2;
          float heights[HEIGHTS] = float[](150, 1000);
          vec3 offsets[HEIGHTS] = vec3[](vec3(12,553,239), vec3(-10, 103, 10004));

          float alpha = 0;
          for (int i = 0; i < HEIGHTS; ++i) {{
            float cloud_height = heights[i];
            float dist = (cloud_height - eye_position.y) / direction.y;
            if (dist <= 0 || dist > 1000000) {{
              continue;
            }} else {{
              vec3 seed = (eye_position + dist * direction + offsets[i]) / 1000 * vec3(1, 4, 1);
              float f = cloud_noise(seed) * cloud_noise(seed + vec3(-10, -103, 1));
              f = f * f;
              alpha += f * (1 - fog_density(dist / 8));
            }}
          }}

          alpha = min(alpha, 1);
          frag_color = vec4(mix(sun_color, vec3(1, 1, 1), alpha), 1);
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};
use std::slice::Iter;
use std::vec::IntoIter;

#[derive(Clone)]
pub struct Namespace {
    segments: Vec<String>,
}

impl Namespace {
    pub fn new(segments: Vec<String>) -> Self {
        Namespace { segments }
    }

    pub fn iter(&self) -> Iter<String> {
        self.segments.iter()
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            f.write_str(segment)?;
            f.write_str("$")?;
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a String;
    type IntoIter = Iter<'a, String>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl IntoIterator for Namespace {
    type Item = String;
    type IntoIter = IntoIter<String>;
    fn into_iter(self) -> Self::IntoIter {
        self.segments.into_iter()
    }
}
<commit_msg>No longer need to iterate Namespace by value<commit_after>use std::fmt::{self, Display};
use std::slice::Iter;

#[derive(Clone)]
pub struct Namespace {
    segments: Vec<String>,
}

impl Namespace {
    pub fn new(segments: Vec<String>) -> Self {
        Namespace { segments }
    }

    pub fn iter(&self) -> Iter<String> {
        self.segments.iter()
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            f.write_str(segment)?;
            f.write_str("$")?;
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a String;
    type IntoIter = Iter<'a, String>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
<|endoftext|>


<commit_before>
  fn take_n(v: &r/[u8], n: uint) -> (&r/[u8], &r/[u8]) {
    (vec::view(v, 0, n), vec::view(v, n, v.len()))
  }

  fn take_atmost_n(v: &r/[u8], n: uint) -> (&r/[u8], &r/[u8]) {
    take_n(v, uint::min(n, v.len()))
  }

  fn take_head(v: &r/[u8]) -> (u8, &r/[u8]) {
    assert v.is_not_empty();
    (v.head(), vec::view(v, 1, v.len()))
  }

  // in_integer
  enum RedisType {
    TyNone,
    TyList,
    TyData,
    TyInt
  }

  enum Inside {
    in_nothing,
    in_number,
    in_number_digits_only,
    in_number_done,
    in_number_need_newline,
    in_data,
    //in_data_need_newline
  }

  struct RedisState {
    mut in: Inside,
    mut typ: RedisType,
    mut data_size: uint,
    mut data_have: uint,
    mut number: uint,
    mut negative_number: bool,
  }

  enum RedisResult {
    Finished,
    NeedMore,
    Error
  }

  // Return
  trait Visitor {
    fn on_list(&mut self, len: uint) -> bool;

    fn on_data_beg(&mut self, len: uint);
    fn on_data(&mut self, data: &[u8]);
    fn on_data_end(&mut self) -> bool;

    fn on_integer(&mut self, num: uint, sign: bool) -> bool;

    fn on_nil(&mut self) -> bool;
  }

// keep recursion in visitor?
  struct MyVisitor {
    mut stack: ~[(uint, uint)] // (len, idx)
  }

  // returns true if we are finished parsing a redis request
  fn element_done(visitor: &mut MyVisitor) -> bool {
    if visitor.stack.is_empty() {
      true
    }
    else {
      let (len, idx) = visitor.stack.last();
      assert idx+1 <= len;
      visitor.stack[visitor.stack.len()-1] = (len, idx+1);
      if idx + 1 == len {
        error!("Finsihed list");
        let _ = vec::pop(&mut visitor.stack);
        element_done(visitor)
      }
      else {
        false
      }
    }
  }

  impl MyVisitor : Visitor {
    fn on_list(&mut self, len: uint) -> bool {
      error!("on_list(len: %u)", len);
      if len == 0 {
        element_done(self)
      }
      else {
        vec::push(&mut self.stack, (len, 0));
        false
      }
    }

    fn on_data_beg(&mut self, len: uint) {
      error!("on_data_beg(len: %u)", len)
    }

    fn on_data(&mut self, data: &[u8]) {
      error!("on_data(%?)", data)
    }

    fn on_data_end(&mut self) -> bool {
      error!("on_data_end()");
      element_done(self)
    }

    fn on_integer(&mut self, num: uint, sign: bool) -> bool {
      error!("on_integer(%?, %?)", num, sign);
      element_done(self)
    }

    fn on_nil(&mut self) -> bool {
      error!("on_nil");
      element_done(self)
    }
  }

  fn parse_redis<V: Visitor>(st: &mut RedisState, buf: &r/[u8], visitor: &mut V) -> (RedisResult, &r/[u8]) {
    let mut buf = buf;

    loop {
      match st.in {
        in_nothing => {
          if (buf.is_empty()) {break}

          let (c, b) = take_head(buf);
          buf = b;

          match c as char {
            '\r' | '\n' | ' ' =>  {
                error!("ignoring carriage return/new/whitespace line")
              }
            '*' => {
                st.typ = TyList;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
              }
            '$' => {
                st.typ = TyData;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
             }
            ':' => {
                st.typ = TyInt;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
             }

             _ => {
                return (Error, buf) // XXX: return a slice including the character that failed
             }
          }

        }

        in_data => {
          if (buf.is_empty()) {break}
          let (data, b) = take_atmost_n(buf, st.data_size - st.data_have);
          buf = b;
          visitor.on_data(data);
          st.data_have += data.len();
          assert st.data_have <= st.data_size;
          if st.data_have == st.data_size {
            //XXX: st.in = in_data_need_newline;
            st.in = in_nothing;
            if visitor.on_data_end() {
              return (Finished, buf)
            }
          }
        }

        // we could treat the newline after data differently.
/*
        in_data_need_newline => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_nothing;
          }
          else if c == ('\r' as u8) || c == (' ' as u8) {
            error("Consume whitespace");
          }
          else {
            return (Error, buf)
          }
        }
*/

        in_number_need_newline => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }
        }

        // XXX: make a function instead of a STATE
        in_number_done => {
          match st.typ {
            TyData => {
              if st.negative_number {
                if st.number == 1 {
                  st.in = in_nothing;
                  if visitor.on_nil() {
                    return (Finished, buf)
                  }
                }
                else {
                  return (Error, buf)
                }
              }
              else {
                st.data_size = st.number;
                st.data_have = 0;
                st.in = in_data;
                visitor.on_data_beg(st.data_size);
              }
            }
            TyList => {
              // XXX:
              // push current recursion level and index on stack
              st.in = in_nothing;
              if st.negative_number {
                if (st.number == 1) {
                  if visitor.on_nil() {
                    return (Finished, buf)
                  }
                }
                else {
                  return (Error, buf)
                }
              }
              else {
                if visitor.on_list(st.number) {
                  return (Finished, buf)
                }
              }
            }

            TyInt => {
              st.in = in_nothing;
              if visitor.on_integer(st.number, st.negative_number) {
                return (Finished, buf)
              }
            }
            _ => {
              fail ~"THIS SHOULD NEVER HAPPEN"
            }
          }
        }

        in_number | in_number_digits_only => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;

          if c >= ('0' as u8) && c <= ('9' as u8) {
            st.number *= 10;
            st.number += (c - ('0' as u8)) as uint;
            st.in = in_number_digits_only;
          }
          else if c as char == '-' {
            match st.in {
              in_number_digits_only => {
                return (Error, buf)
              }
              _ => {
                st.negative_number = true;
                st.in = in_number_digits_only;
              }
            }
          }
          else if c as char == '\r' || c as char == ' ' {
            st.in = in_number_need_newline;
          }
          else if c as char == '\n' {
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }

        }
      }
    }
    (NeedMore, buf)
  }

fn main() {

  let mut st = RedisState {
    in: in_nothing,
    typ: TyNone,
    data_size: 0,
    data_have: 0,
    number: 0,
    negative_number: false,
  };

  error!("%?", st);

  let mut visitor = MyVisitor {stack: ~[]};

  let s = ~"*4\r\n$3\r\nabc\r\n:123\n:1\n$-1\n";
  do str::as_bytes(&s) |v| {
    let x = parse_redis(&mut st, vec::view(*v, 0, (*v).len() - 1), &mut visitor);
    error!("%?", st);
    error!("%?", x);
  }

}
<commit_msg>Update to rust 0.6<commit_after>
  fn take_n<'r>(v: &'r [u8], n: uint) -> (&'r [u8], &'r [u8]) {
    (vec::slice(v, 0, n), vec::slice(v, n, v.len()))
  }

  fn take_atmost_n<'r>(v: &'r [u8], n: uint) -> (&'r [u8], &'r [u8]) {
    take_n(v, uint::min(n, v.len()))
  }

  fn take_head<'r>(v: &'r [u8]) -> (u8, &'r [u8]) {
    assert!(!v.is_empty());
    (*v.head(), vec::slice(v, 1, v.len()))
  }

  // in_integer
  enum RedisType {
    TyNone,
    TyList,
    TyData,
    TyInt
  }

  enum Inside {
    in_nothing,
    in_number,
    in_number_digits_only,
    in_number_done,
    in_number_need_newline,
    in_data,
    //in_data_need_newline
  }

  struct RedisState {
    in: Inside,
    typ: RedisType,
    data_size: uint,
    data_have: uint,
    number: uint,
    negative_number: bool,
  }

  enum RedisResult {
    Finished,
    NeedMore,
    Error
  }

  enum Result {
    Invalid,
    Nil,
    Int(int),
    Data(~[u8]),
    List(~[Result]),
    Err(~str),
    Status(~str)
  }

  // Return
  trait Visitor {
    fn on_list(&mut self, len: uint) -> bool;

    fn on_data_beg(&mut self, len: uint);
    fn on_data(&mut self, data: &[u8]);
    fn on_data_end(&mut self) -> bool;

    fn on_integer(&mut self, num: uint, sign: bool) -> bool;

    fn on_nil(&mut self) -> bool;
  }

// keep recursion in visitor?
  struct MyVisitor {
    stack: ~[~[Result]], // (len, idx)
    result: Result
  }

  // returns true if we are finished parsing a redis request
  fn element_done(visitor: &mut MyVisitor, value: Result) -> bool {
    if visitor.stack.is_empty() {
      visitor.result = value;
      true
    }
    else {

      vec::push(&mut (visitor.stack[0/*visitor.stack.len()-1*/]), value);
      false
/*      let (len, idx) = visitor.stack.last();
      assert!(idx+1 <= len);
      visitor.stack[visitor.stack.len()-1] = (len, idx+1);
      if idx + 1 == len {
        error!("Finsihed list");
        let _ = vec::pop(&mut visitor.stack);
        element_done(visitor)
      }
      else {
        false
      }
*/
    }
  }

  impl Visitor for MyVisitor {
    fn on_list(&mut self, len: uint) -> bool {
      error!("on_list(len: %u)", len);
      if len == 0 {
        element_done(self, List(~[]))
      }
      else {
        //vec::push(&mut self.stack, (len, 0));
        false
      }
    }

    fn on_data_beg(&mut self, len: uint) {
      error!("on_data_beg(len: %u)", len)
    }

    fn on_data(&mut self, data: &[u8]) {
      error!("on_data(%?)", data)
    }

    fn on_data_end(&mut self) -> bool {
      error!("on_data_end()");
      element_done(self, Data(~[1,2,3]))
    }

    fn on_integer(&mut self, num: uint, sign: bool) -> bool {
      error!("on_integer(%?, %?)", num, sign);
      element_done(self, Int(num as int)) // XXX
    }

    fn on_nil(&mut self) -> bool {
      error!("on_nil");
      element_done(self, Nil)
    }
  }

  fn parse_redis<'r, V: Visitor>(st: &mut RedisState, buf: &'r [u8], visitor: &mut V) -> (RedisResult, &'r [u8]) {
    let mut buf = buf;

    loop {
      match st.in {
        in_nothing => {
          if (buf.is_empty()) {break}

          let (c, b) = take_head(buf);
          buf = b;

          match c as char {
            '\r' | '\n' | ' ' =>  {
                error!("ignoring carriage return/new/whitespace line")
              }
            '*' => {
                st.typ = TyList;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
              }
            '$' => {
                st.typ = TyData;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
             }
            ':' => {
                st.typ = TyInt;
                st.in = in_number;
                st.number = 0;
                st.negative_number = false;
             }

             _ => {
                return (Error, buf) // XXX: return a slice including the character that failed
             }
          }

        }

        in_data => {
          if (buf.is_empty()) {break}
          let (data, b) = take_atmost_n(buf, st.data_size - st.data_have);
          buf = b;
          visitor.on_data(data);
          st.data_have += data.len();
          assert!(st.data_have <= st.data_size);
          if st.data_have == st.data_size {
            //XXX: st.in = in_data_need_newline;
            st.in = in_nothing;
            if visitor.on_data_end() {
              return (Finished, buf)
            }
          }
        }

        // we could treat the newline after data differently.
/*
        in_data_need_newline => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_nothing;
          }
          else if c == ('\r' as u8) || c == (' ' as u8) {
            error("Consume whitespace");
          }
          else {
            return (Error, buf)
          }
        }
*/

        in_number_need_newline => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }
        }

        // XXX: make a function instead of a STATE
        in_number_done => {
          match st.typ {
            TyData => {
              if st.negative_number {
                if st.number == 1 {
                  st.in = in_nothing;
                  if visitor.on_nil() {
                    return (Finished, buf)
                  }
                }
                else {
                  return (Error, buf)
                }
              }
              else {
                st.data_size = st.number;
                st.data_have = 0;
                st.in = in_data;
                visitor.on_data_beg(st.data_size);
              }
            }
            TyList => {
              // XXX:
              // push current recursion level and index on stack
              st.in = in_nothing;
              if st.negative_number {
                if (st.number == 1) {
                  if visitor.on_nil() {
                    return (Finished, buf)
                  }
                }
                else {
                  return (Error, buf)
                }
              }
              else {
                if visitor.on_list(st.number) {
                  return (Finished, buf)
                }
              }
            }

            TyInt => {
              st.in = in_nothing;
              if visitor.on_integer(st.number, st.negative_number) {
                return (Finished, buf)
              }
            }
            _ => {
              fail!(~"THIS SHOULD NEVER HAPPEN")
            }
          }
        }

        in_number | in_number_digits_only => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;

          if c >= ('0' as u8) && c <= ('9' as u8) {
            st.number *= 10;
            st.number += (c - ('0' as u8)) as uint;
            st.in = in_number_digits_only;
          }
          else if c as char == '-' {
            match st.in {
              in_number_digits_only => {
                return (Error, buf)
              }
              _ => {
                st.negative_number = true;
                st.in = in_number_digits_only;
              }
            }
          }
          else if c as char == '\r' || c as char == ' ' {
            st.in = in_number_need_newline;
          }
          else if c as char == '\n' {
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }

        }
      }
    }
    (NeedMore, buf)
  }

fn main() {
  let mut st = RedisState {
    in: in_nothing,
    typ: TyNone,
    data_size: 0,
    data_have: 0,
    number: 0,
    negative_number: false,
  };

  error!("%?", st);

  let mut visitor = MyVisitor {stack: ~[], result: Invalid};

  let s = ~"*4\r\n$3\r\nabc\r\n:123\n:1\n$-1\n";
  let slice = str::as_bytes_slice(s);
  let x = parse_redis(&mut st, slice, &mut visitor);
  error!("%?", st);
  error!("%?", x);
  error!("%?", visitor.result);
}
<|endoftext|>


<commit_before>//! Translations.

use crate::{P2, V2};

/// A trait for spatially translatable types.
pub trait Translate {
    /// Translate `self` by the given translation vector.
    fn translate(self, translation: V2) -> Self;
}

impl Translate for P2 {
    fn translate(self, translation: V2) -> Self {
        self + translation
    }
}
<commit_msg>Add `translate_along` to `Translate`<commit_after>//! Translations.

use crate::{Angle, Ellipse, P2, V2};

/// A trait for spatially translatable types.
pub trait Translate: Sized {
    /// Translate `self` by the given translation vector.
    fn translate(self, translation: V2) -> Self;

    /// Translate `self` along the given direction.
    fn translate_along(self, direction: Angle, distance: f32) -> Self {
        let offset = Ellipse::circle(P2::new(0., 0.), distance)
            .circumpoint(direction)
            .to_vector();
        self.translate(offset)
    }
}

impl Translate for P2 {
    fn translate(self, translation: V2) -> Self {
        self + translation
    }
}
<|endoftext|>


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

extern crate rand;

use smallvec::SmallVec;
use std::cell::RefCell;
use std::fmt;

use crate::numeric::{gcd, Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>);

// The number of factors to inline directly into a `Decomposition` object.
// As a consequence of the Erdős–Kac theorem, the average number of prime factors
// of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value.
const NUM_FACTORS_INLINE: usize = 5;

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(SmallVec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);
        // Assert the factor doesn't already exist in the Decomposition object
        debug_assert_eq!(self.0.iter_mut().find(|(f, _)| *f == factor), None);

        self.0.push((factor, exp))
    }

    fn is_one(&self) -> bool {
        self.0.is_empty()
    }

    fn pop(&mut self) -> Option<(u64, Exponent)> {
        self.0.pop()
    }

    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    #[cfg(test)]
    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _find_factor<A: Arithmetic + miller_rabin::Basis>(num: u64) -> Option<u64> {
    use miller_rabin::Result::*;

    let n = A::new(num);
    match miller_rabin::test::<A>(n) {
        Prime => None,
        Composite(d) => Some(d),
        Pseudoprime => Some(rho::find_divisor::<A>(n)),
    }
}

fn find_factor(num: u64) -> Option<u64> {
    if num < (1 << 32) {
        _find_factor::<Montgomery<u32>>(num)
    } else {
        _find_factor::<Montgomery<u64>>(num)
    }
}

pub fn factor(num: u64) -> Factors {
    let mut factors = Factors::one();

    if num < 2 {
        return factors;
    }

    let mut n = num;
    let n_zeros = num.trailing_zeros();
    if n_zeros > 0 {
        factors.add(2, n_zeros as Exponent);
        n >>= n_zeros;
    }
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    table::factor(&mut n, &mut factors);
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    let mut dec = Decomposition::one();
    dec.add(n, 1);

    while !dec.is_one() {
        // Check correctness invariant
        debug_assert_eq!(num, factors.product() * dec.product());

        let (factor, exp) = dec.pop().unwrap();

        if let Some(divisor) = find_factor(factor) {
            let mut gcd_queue = Decomposition::one();

            let quotient = factor / divisor;
            let mut trivial_gcd = quotient == divisor;
            if trivial_gcd {
                gcd_queue.add(divisor, exp + 1);
            } else {
                gcd_queue.add(divisor, exp);
                gcd_queue.add(quotient, exp);
            }

            while !trivial_gcd {
                debug_assert_eq!(factor, gcd_queue.product());

                let mut tmp = Decomposition::one();
                trivial_gcd = true;
                for i in 0..gcd_queue.0.len() - 1 {
                    let (mut a, exp_a) = gcd_queue.0[i];
                    let (mut b, exp_b) = gcd_queue.0[i + 1];

                    if a == 1 {
                        continue;
                    }

                    let g = gcd(a, b);
                    if g != 1 {
                        trivial_gcd = false;
                        a /= g;
                        b /= g;
                    }
                    if a != 1 {
                        tmp.add(a, exp_a);
                    }
                    if g != 1 {
                        tmp.add(g, exp_a + exp_b);
                    }

                    if i + 1 != gcd_queue.0.len() - 1 {
                        gcd_queue.0[i + 1].0 = b;
                    } else if b != 1 {
                        tmp.add(b, exp_b);
                    }
                }
                gcd_queue = tmp;
            }

            debug_assert_eq!(factor, gcd_queue.product());
            dec.0.extend(gcd_queue.0);
        } else {
            // factor is prime
            factors.add(factor, exp);
        }
    }

    factors
}

#[cfg(test)]
mod tests {
    use super::{factor, Factors};
    use quickcheck::quickcheck;

    #[test]
    fn factor_correctly_recombines_prior_test_failures() {
        let prior_failures = [
            // * integers with duplicate factors (ie, N.pow(M))
            4566769_u64, // == 2137.pow(2)
            2044854919485649_u64,
            18446739546814299361_u64,
            18446738440860217487_u64,
            18446736729316206481_u64,
        ];
        assert!(prior_failures.iter().all(|i| factor(*i).product() == *i));
    }

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_small_squares() {
        // factor(18446736729316206481) == 4294966441 ** 2 ; causes debug_assert fault for repeated decomposition factor in add()
        // ToDO: explain/combine with factor_18446736729316206481 and factor_18446739546814299361 tests
        assert!((1..10_000)
            .map(|i| (2 * i + 1) * (2 * i + 1))
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's codepath handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> bool {
            assert_eq!(factor(f.product()), f);
            true
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary<G: quickcheck::Gen>(gen: &mut G) -> Self {
        use rand::Rng;
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorisation.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = gen.gen_range(1, n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}
<commit_msg>polish/factor ~ correct spelling<commit_after>// * This file is part of the uutils coreutils package.
// *
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

extern crate rand;

use smallvec::SmallVec;
use std::cell::RefCell;
use std::fmt;

use crate::numeric::{gcd, Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>);

// The number of factors to inline directly into a `Decomposition` object.
// As a consequence of the Erdős–Kac theorem, the average number of prime factors
// of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value.
const NUM_FACTORS_INLINE: usize = 5;

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(SmallVec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);
        // Assert the factor doesn't already exist in the Decomposition object
        debug_assert_eq!(self.0.iter_mut().find(|(f, _)| *f == factor), None);

        self.0.push((factor, exp))
    }

    fn is_one(&self) -> bool {
        self.0.is_empty()
    }

    fn pop(&mut self) -> Option<(u64, Exponent)> {
        self.0.pop()
    }

    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    #[cfg(test)]
    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _find_factor<A: Arithmetic + miller_rabin::Basis>(num: u64) -> Option<u64> {
    use miller_rabin::Result::*;

    let n = A::new(num);
    match miller_rabin::test::<A>(n) {
        Prime => None,
        Composite(d) => Some(d),
        Pseudoprime => Some(rho::find_divisor::<A>(n)),
    }
}

fn find_factor(num: u64) -> Option<u64> {
    if num < (1 << 32) {
        _find_factor::<Montgomery<u32>>(num)
    } else {
        _find_factor::<Montgomery<u64>>(num)
    }
}

pub fn factor(num: u64) -> Factors {
    let mut factors = Factors::one();

    if num < 2 {
        return factors;
    }

    let mut n = num;
    let n_zeros = num.trailing_zeros();
    if n_zeros > 0 {
        factors.add(2, n_zeros as Exponent);
        n >>= n_zeros;
    }
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    table::factor(&mut n, &mut factors);
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    let mut dec = Decomposition::one();
    dec.add(n, 1);

    while !dec.is_one() {
        // Check correctness invariant
        debug_assert_eq!(num, factors.product() * dec.product());

        let (factor, exp) = dec.pop().unwrap();

        if let Some(divisor) = find_factor(factor) {
            let mut gcd_queue = Decomposition::one();

            let quotient = factor / divisor;
            let mut trivial_gcd = quotient == divisor;
            if trivial_gcd {
                gcd_queue.add(divisor, exp + 1);
            } else {
                gcd_queue.add(divisor, exp);
                gcd_queue.add(quotient, exp);
            }

            while !trivial_gcd {
                debug_assert_eq!(factor, gcd_queue.product());

                let mut tmp = Decomposition::one();
                trivial_gcd = true;
                for i in 0..gcd_queue.0.len() - 1 {
                    let (mut a, exp_a) = gcd_queue.0[i];
                    let (mut b, exp_b) = gcd_queue.0[i + 1];

                    if a == 1 {
                        continue;
                    }

                    let g = gcd(a, b);
                    if g != 1 {
                        trivial_gcd = false;
                        a /= g;
                        b /= g;
                    }
                    if a != 1 {
                        tmp.add(a, exp_a);
                    }
                    if g != 1 {
                        tmp.add(g, exp_a + exp_b);
                    }

                    if i + 1 != gcd_queue.0.len() - 1 {
                        gcd_queue.0[i + 1].0 = b;
                    } else if b != 1 {
                        tmp.add(b, exp_b);
                    }
                }
                gcd_queue = tmp;
            }

            debug_assert_eq!(factor, gcd_queue.product());
            dec.0.extend(gcd_queue.0);
        } else {
            // factor is prime
            factors.add(factor, exp);
        }
    }

    factors
}

#[cfg(test)]
mod tests {
    use super::{factor, Factors};
    use quickcheck::quickcheck;

    #[test]
    fn factor_correctly_recombines_prior_test_failures() {
        let prior_failures = [
            // * integers with duplicate factors (ie, N.pow(M))
            4566769_u64, // == 2137.pow(2)
            2044854919485649_u64,
            18446739546814299361_u64,
            18446738440860217487_u64,
            18446736729316206481_u64,
        ];
        assert!(prior_failures.iter().all(|i| factor(*i).product() == *i));
    }

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_small_squares() {
        // factor(18446736729316206481) == 4294966441 ** 2 ; causes debug_assert fault for repeated decomposition factor in add()
        // ToDO: explain/combine with factor_18446736729316206481 and factor_18446739546814299361 tests
        assert!((1..10_000)
            .map(|i| (2 * i + 1) * (2 * i + 1))
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's code path handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> bool {
            assert_eq!(factor(f.product()), f);
            true
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary<G: quickcheck::Gen>(gen: &mut G) -> Self {
        use rand::Rng;
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorization.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = gen.gen_range(1, n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::hash::Hash;
use std::ops::Index;

pub use self::unordered::UnorderedMap;
pub use std::collections::hash_map::Entry;

mod unordered {
    use crate::syntax::set::UnorderedSet;
    use std::borrow::Borrow;
    use std::collections::hash_map::{Entry, HashMap};
    use std::hash::Hash;

    // Wrapper prohibits accidentally introducing iteration over the map, which
    // could lead to nondeterministic generated code.
    pub struct UnorderedMap<K, V>(HashMap<K, V>);

    impl<K, V> UnorderedMap<K, V> {
        pub fn new() -> Self {
            UnorderedMap(HashMap::new())
        }
    }

    impl<K, V> UnorderedMap<K, V>
    where
        K: Hash + Eq,
    {
        pub fn insert(&mut self, key: K, value: V) -> Option<V> {
            self.0.insert(key, value)
        }

        pub fn contains_key<Q>(&self, key: &Q) -> bool
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.contains_key(key)
        }

        pub fn get<Q>(&self, key: &Q) -> Option<&V>
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.get(key)
        }

        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.0.entry(key)
        }

        pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.remove(key)
        }

        pub fn keys(&self) -> UnorderedSet<K>
        where
            K: Copy,
        {
            let mut set = UnorderedSet::new();
            for key in self.0.keys() {
                set.insert(*key);
            }
            set
        }
    }
}

impl<K, V> Default for UnorderedMap<K, V> {
    fn default() -> Self {
        UnorderedMap::new()
    }
}

impl<Q, K, V> Index<&Q> for UnorderedMap<K, V>
where
    K: Borrow<Q> + Hash + Eq,
    Q: ?Sized + Hash + Eq,
{
    type Output = V;

    fn index(&self, key: &Q) -> &V {
        self.get(key).unwrap()
    }
}
<commit_msg>Add OrderedMap type<commit_after>use std::borrow::Borrow;
use std::hash::Hash;
use std::ops::Index;
use std::slice;

pub use self::ordered::OrderedMap;
pub use self::unordered::UnorderedMap;
pub use std::collections::hash_map::Entry;

mod ordered {
    use super::{Entry, Iter, UnorderedMap};
    use std::borrow::Borrow;
    use std::hash::Hash;
    use std::mem;

    pub struct OrderedMap<K, V> {
        map: UnorderedMap<K, usize>,
        vec: Vec<(K, V)>,
    }

    impl<K, V> OrderedMap<K, V> {
        pub fn new() -> Self {
            OrderedMap {
                map: UnorderedMap::new(),
                vec: Vec::new(),
            }
        }

        pub fn iter(&self) -> Iter<K, V> {
            Iter(self.vec.iter())
        }
    }

    impl<K, V> OrderedMap<K, V>
    where
        K: Copy + Hash + Eq,
    {
        pub fn insert(&mut self, key: K, value: V) -> Option<V> {
            match self.map.entry(key) {
                Entry::Occupied(entry) => {
                    let i = &mut self.vec[*entry.get()];
                    Some(mem::replace(&mut i.1, value))
                }
                Entry::Vacant(entry) => {
                    entry.insert(self.vec.len());
                    self.vec.push((key, value));
                    None
                }
            }
        }

        pub fn contains_key<Q>(&self, key: &Q) -> bool
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.map.contains_key(key)
        }

        pub fn get<Q>(&self, key: &Q) -> Option<&V>
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            let i = *self.map.get(key)?;
            Some(&self.vec[i].1)
        }
    }

    impl<'a, K, V> IntoIterator for &'a OrderedMap<K, V> {
        type Item = (&'a K, &'a V);
        type IntoIter = Iter<'a, K, V>;
        fn into_iter(self) -> Self::IntoIter {
            self.iter()
        }
    }
}

mod unordered {
    use crate::syntax::set::UnorderedSet;
    use std::borrow::Borrow;
    use std::collections::hash_map::{Entry, HashMap};
    use std::hash::Hash;

    // Wrapper prohibits accidentally introducing iteration over the map, which
    // could lead to nondeterministic generated code.
    pub struct UnorderedMap<K, V>(HashMap<K, V>);

    impl<K, V> UnorderedMap<K, V> {
        pub fn new() -> Self {
            UnorderedMap(HashMap::new())
        }
    }

    impl<K, V> UnorderedMap<K, V>
    where
        K: Hash + Eq,
    {
        pub fn insert(&mut self, key: K, value: V) -> Option<V> {
            self.0.insert(key, value)
        }

        pub fn contains_key<Q>(&self, key: &Q) -> bool
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.contains_key(key)
        }

        pub fn get<Q>(&self, key: &Q) -> Option<&V>
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.get(key)
        }

        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.0.entry(key)
        }

        pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
        where
            K: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.0.remove(key)
        }

        pub fn keys(&self) -> UnorderedSet<K>
        where
            K: Copy,
        {
            let mut set = UnorderedSet::new();
            for key in self.0.keys() {
                set.insert(*key);
            }
            set
        }
    }
}

pub struct Iter<'a, K, V>(slice::Iter<'a, (K, V)>);

impl<'a, K, V> Iterator for Iter<'a, K, V> {
    type Item = (&'a K, &'a V);

    fn next(&mut self) -> Option<Self::Item> {
        let (k, v) = self.0.next()?;
        Some((k, v))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<K, V> Default for UnorderedMap<K, V> {
    fn default() -> Self {
        UnorderedMap::new()
    }
}

impl<Q, K, V> Index<&Q> for UnorderedMap<K, V>
where
    K: Borrow<Q> + Hash + Eq,
    Q: ?Sized + Hash + Eq,
{
    type Output = V;

    fn index(&self, key: &Q) -> &V {
        self.get(key).unwrap()
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;

use quire::validate::{Structure, Scalar, Enum, Numeric, Nothing};
use quire::validate::{Sequence};
use quire::De;

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum LoadBalancing {
    queue,
}

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
pub struct Destination {
    pub load_balancing: LoadBalancing,
    pub queue_size_for_503: usize,
    pub backend_connections_per_ip_port: usize,
    pub in_flight_requests_per_backend_connection: usize,
    pub addresses: Vec<String>,
    pub keep_alive_timeout: De<Duration>,
    pub max_request_timeout: De<Duration>,
    pub safe_pipelining_timeout: De<Duration>,
}

pub fn validator<'x>() -> Structure<'x> {
    Structure::new()
    .member("load_balancing", Enum::new()
        .option("queue", Nothing)
        .allow_plain()
        .plain_default("queue"))
    .member("queue_size_for_503",
        Numeric::new().min(0).max(1 << 32).default(100_000))
    .member("backend_connections_per_ip_port",
        Numeric::new().min(1).max(100_000).default(100))
    .member("in_flight_requests_per_backend_connection",
        Numeric::new().min(1).max(1000).default(2))
    .member("addresses", Sequence::new(Scalar::new()).min_length(1))
    .member("keep_alive_timeout", Scalar::new().default("4 sec"))
    .member("max_request_timeout", Scalar::new().default("30 secs"))
    .member("safe_pipeline_timeout", Scalar::new().default("300 ms"))
}
<commit_msg>Fixes typo in config<commit_after>use std::time::Duration;

use quire::validate::{Structure, Scalar, Enum, Numeric, Nothing};
use quire::validate::{Sequence};
use quire::De;

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum LoadBalancing {
    queue,
}

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
pub struct Destination {
    pub load_balancing: LoadBalancing,
    pub queue_size_for_503: usize,
    pub backend_connections_per_ip_port: usize,
    pub in_flight_requests_per_backend_connection: usize,
    pub addresses: Vec<String>,
    pub keep_alive_timeout: De<Duration>,
    pub max_request_timeout: De<Duration>,
    pub safe_pipeline_timeout: De<Duration>,
}

pub fn validator<'x>() -> Structure<'x> {
    Structure::new()
    .member("load_balancing", Enum::new()
        .option("queue", Nothing)
        .allow_plain()
        .plain_default("queue"))
    .member("queue_size_for_503",
        Numeric::new().min(0).max(1 << 32).default(100_000))
    .member("backend_connections_per_ip_port",
        Numeric::new().min(1).max(100_000).default(100))
    .member("in_flight_requests_per_backend_connection",
        Numeric::new().min(1).max(1000).default(2))
    .member("addresses", Sequence::new(Scalar::new()).min_length(1))
    .member("keep_alive_timeout", Scalar::new().default("4 sec"))
    .member("max_request_timeout", Scalar::new().default("30 secs"))
    .member("safe_pipeline_timeout", Scalar::new().default("300 ms"))
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagmail;
extern crate libimagerror;
extern crate libimagutil;
extern crate libimagentryref;

use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
use libimagmail::mail::Mail;
use libimagentryref::reference::Ref;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagutil::info_result::*;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-mail",
                                    &version!()[..],
                                    "Mail collection tool",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "import-mail" => import_mail(&rt),
                "list"        => list(&rt),
                "mail-store"  => mail_store(&rt),
                _             => debug!("Unknown command") // More error handling
            }
        });
}

fn import_mail(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("import-mail").unwrap();
    let path = scmd.value_of("path").unwrap(); // enforced by clap

    let _ = Mail::import_from_path(rt.store(), path)
        .map_err_trace()
        .map_info_str("Ok");
}

fn list(rt: &Runtime) {
    use libimagmail::error::MailErrorKind as MEK;
    use libimagmail::error::MapErrInto;

    let store = rt.store();

    let iter = match store.retrieve_for_module("ref") {
        Ok(iter) => iter.filter_map(|id| {
            Ref::get(store, id)
                .map_err_into(MEK::RefHandlingError)
                .and_then(|rf| Mail::from_ref(rf))
                .map_err_trace()
                .ok()
        }),
        Err(e)   => trace_error_exit(&e, 1),
    };

    fn list_mail(m: Mail) {
        let id = match m.get_message_id() {
            Ok(Some(f)) => f,
            Ok(None) => "<no id>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let from = match m.get_from() {
            Ok(Some(f)) => f,
            Ok(None) => "<no from>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let to = match m.get_to() {
            Ok(Some(f)) => f,
            Ok(None) => "<no to>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let subject = match m.get_subject() {
            Ok(Some(f)) => f,
            Ok(None) => "<no subject>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        println!("Mail: {id}\n\tFrom: {from}\n\tTo: {to}\n\t{subj}\n",
                 from = from,
                 id   = id,
                 subj = subject,
                 to   = to
        );
    }

    // TODO: Implement lister type in libimagmail for this
    for mail in iter {
        list_mail(mail)
    }
}

fn mail_store(rt: &Runtime) {
    let _ = rt.cli().subcommand_matches("mail-store").unwrap();
    error!("This feature is currently not implemented.");
    unimplemented!()
}

<commit_msg>imag-mail: Rewrite error handling<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagmail;
extern crate libimagerror;
extern crate libimagutil;
extern crate libimagentryref;

use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
use libimagmail::mail::Mail;
use libimagentryref::reference::Ref;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagutil::info_result::*;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-mail",
                                    &version!()[..],
                                    "Mail collection tool",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "import-mail" => import_mail(&rt),
                "list"        => list(&rt),
                "mail-store"  => mail_store(&rt),
                _             => debug!("Unknown command") // More error handling
            }
        });
}

fn import_mail(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("import-mail").unwrap();
    let path = scmd.value_of("path").unwrap(); // enforced by clap

    let _ = Mail::import_from_path(rt.store(), path)
        .map_err_trace()
        .map_info_str("Ok");
}

fn list(rt: &Runtime) {
    use libimagmail::error::MailErrorKind as MEK;
    use libimagmail::error::ResultExt;

    let store = rt.store();

    let iter = match store.retrieve_for_module("ref") {
        Ok(iter) => iter.filter_map(|id| {
            Ref::get(store, id)
                .chain_err(|| MEK::RefHandlingError)
                .and_then(|rf| Mail::from_ref(rf))
                .map_err_trace()
                .ok()
        }),
        Err(e)   => trace_error_exit(&e, 1),
    };

    fn list_mail(m: Mail) {
        let id = match m.get_message_id() {
            Ok(Some(f)) => f,
            Ok(None) => "<no id>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let from = match m.get_from() {
            Ok(Some(f)) => f,
            Ok(None) => "<no from>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let to = match m.get_to() {
            Ok(Some(f)) => f,
            Ok(None) => "<no to>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        let subject = match m.get_subject() {
            Ok(Some(f)) => f,
            Ok(None) => "<no subject>".to_owned(),
            Err(e) => {
                trace_error(&e);
                "<error>".to_owned()
            },
        };

        println!("Mail: {id}\n\tFrom: {from}\n\tTo: {to}\n\t{subj}\n",
                 from = from,
                 id   = id,
                 subj = subject,
                 to   = to
        );
    }

    // TODO: Implement lister type in libimagmail for this
    for mail in iter {
        list_mail(mail)
    }
}

fn mail_store(rt: &Runtime) {
    let _ = rt.cli().subcommand_matches("mail-store").unwrap();
    error!("This feature is currently not implemented.");
    unimplemented!()
}

<|endoftext|>