<commit_before>//! Word splitting functionality.
//!
//! To wrap text into lines, long words sometimes need to be split
//! across lines. The [`WordSplitter`] trait defines this
//! functionality. [`HyphenSplitter`] is the default implementation of
//! this treat: it will simply split words on existing hyphens.

/// An interface for splitting words.
///
/// When the [`wrap_iter`] method will try to fit text into a line, it
/// will eventually find a word that it too large the current text
/// width. It will then call the currently configured `WordSplitter` to
/// have it attempt to split the word into smaller parts. This trait
/// describes that functionality via the [`split`] method.
///
/// If the `textwrap` crate has been compiled with the `hyphenation`
/// feature enabled, you will find an implementation of `WordSplitter`
/// by the `hyphenation::Standard` struct. Use this struct for
/// language-aware hyphenation. See the [`hyphenation` documentation]
/// for details.
///
/// [`wrap_iter`]: ../struct.Wrapper.html#method.wrap_iter
/// [`split`]: #tymethod.split
/// [`hyphenation` documentation]: https://docs.rs/hyphenation/
pub trait WordSplitter {
    /// Return all possible splits of word. Each split is a triple
    /// with a head, a hyphen, and a tail where `head + &hyphen +
    /// &tail == word`. The hyphen can be empty if there is already a
    /// hyphen in the head.
    ///
    /// The splits should go from smallest to longest and should
    /// include no split at all. So the word "technology" could be
    /// split into
    ///
    /// ```no_run
    /// vec![("tech", "-", "nology"),
    ///      ("technol", "-", "ogy"),
    ///      ("technolo", "-", "gy"),
    ///      ("technology", "", "")];
    /// ```
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)>;
}

/// Use this as a [`Wrapper.splitter`] to avoid any kind of
/// hyphenation:
///
/// ```
/// use textwrap::{Wrapper, NoHyphenation};
///
/// let wrapper = Wrapper::with_splitter(8, NoHyphenation);
/// assert_eq!(wrapper.wrap("foo bar-baz"), vec!["foo", "bar-baz"]);
/// ```
///
/// [`Wrapper.splitter`]: ../struct.Wrapper.html#structfield.splitter
#[derive(Clone, Debug)]
pub struct NoHyphenation;

/// `NoHyphenation` implements `WordSplitter` by not splitting the
/// word at all.
impl WordSplitter for NoHyphenation {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        vec![(word, "", "")]
    }
}

/// Simple and default way to split words: splitting on existing
/// hyphens only.
///
/// You probably don't need to use this type since it's already used
/// by default by `Wrapper::new`.
#[derive(Clone, Debug)]
pub struct HyphenSplitter;

/// `HyphenSplitter` is the default `WordSplitter` used by
/// `Wrapper::new`. It will split words on any existing hyphens in the
/// word.
///
/// It will only use hyphens that are surrounded by alphanumeric
/// characters, which prevents a word like "--foo-bar" from being
/// split on the first or second hyphen.
impl WordSplitter for HyphenSplitter {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        let mut triples = Vec::new();
        // Split on hyphens, smallest split first. We only use hyphens
        // that are surrounded by alphanumeric characters. This is to
        // avoid splitting on repeated hyphens, such as those found in
        // --foo-bar.
        let mut char_indices = word.char_indices();
        // Early return if the word is empty.
        let mut prev = match char_indices.next() {
            None => return vec![(word, "", "")],
            Some((_, ch)) => ch,
        };

        // Find current word, or return early if the word only has a
        // single character.
        let (mut idx, mut cur) = match char_indices.next() {
            None => return vec![(word, "", "")],
            Some((idx, cur)) => (idx, cur),
        };

        for (i, next) in char_indices {
            if prev.is_alphanumeric() && cur == '-' && next.is_alphanumeric() {
                let (head, tail) = word.split_at(idx + 1);
                triples.push((head, "", tail));
            }
            prev = cur;
            idx = i;
            cur = next;
        }

        // Finally option is no split at all.
        triples.push((word, "", ""));

        triples
    }
}

/// A hyphenation dictionary can be used to do language-specific
/// hyphenation using patterns from the hyphenation crate.
///
/// **Note:** Only available when the `hyphenation` feature is
/// enabled.
#[cfg(feature = "hyphenation")]
impl WordSplitter for hyphenation::Standard {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        use hyphenation::Hyphenator;
        // Find splits based on language dictionary.
        let mut triples = Vec::new();
        for n in self.hyphenate(word).breaks {
            let (head, tail) = word.split_at(n);
            let hyphen = if head.ends_with('-') { "" } else { "-" };
            triples.push((head, hyphen, tail));
        }
        // Finally option is no split at all.
        triples.push((word, "", ""));

        triples
    }
}
<commit_msg>Fix docs: splitting can introduce a hyphen<commit_after>//! Word splitting functionality.
//!
//! To wrap text into lines, long words sometimes need to be split
//! across lines. The [`WordSplitter`] trait defines this
//! functionality. [`HyphenSplitter`] is the default implementation of
//! this treat: it will simply split words on existing hyphens.

/// An interface for splitting words.
///
/// When the [`wrap_iter`] method will try to fit text into a line, it
/// will eventually find a word that it too large the current text
/// width. It will then call the currently configured `WordSplitter` to
/// have it attempt to split the word into smaller parts. This trait
/// describes that functionality via the [`split`] method.
///
/// If the `textwrap` crate has been compiled with the `hyphenation`
/// feature enabled, you will find an implementation of `WordSplitter`
/// by the `hyphenation::Standard` struct. Use this struct for
/// language-aware hyphenation. See the [`hyphenation` documentation]
/// for details.
///
/// [`wrap_iter`]: ../struct.Wrapper.html#method.wrap_iter
/// [`split`]: #tymethod.split
/// [`hyphenation` documentation]: https://docs.rs/hyphenation/
pub trait WordSplitter {
    /// Return all possible splits of word. Each split is a triple
    /// with a head, a hyphen, and a tail where `head + &tail == word`.
    /// The hyphen can be empty if there is already a hyphen in the
    /// head.
    ///
    /// The splits should go from smallest to longest and should
    /// include no split at all. So the word "technology" could be
    /// split into
    ///
    /// ```no_run
    /// vec![("tech", "-", "nology"),
    ///      ("technol", "-", "ogy"),
    ///      ("technolo", "-", "gy"),
    ///      ("technology", "", "")];
    /// ```
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)>;
}

/// Use this as a [`Wrapper.splitter`] to avoid any kind of
/// hyphenation:
///
/// ```
/// use textwrap::{Wrapper, NoHyphenation};
///
/// let wrapper = Wrapper::with_splitter(8, NoHyphenation);
/// assert_eq!(wrapper.wrap("foo bar-baz"), vec!["foo", "bar-baz"]);
/// ```
///
/// [`Wrapper.splitter`]: ../struct.Wrapper.html#structfield.splitter
#[derive(Clone, Debug)]
pub struct NoHyphenation;

/// `NoHyphenation` implements `WordSplitter` by not splitting the
/// word at all.
impl WordSplitter for NoHyphenation {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        vec![(word, "", "")]
    }
}

/// Simple and default way to split words: splitting on existing
/// hyphens only.
///
/// You probably don't need to use this type since it's already used
/// by default by `Wrapper::new`.
#[derive(Clone, Debug)]
pub struct HyphenSplitter;

/// `HyphenSplitter` is the default `WordSplitter` used by
/// `Wrapper::new`. It will split words on any existing hyphens in the
/// word.
///
/// It will only use hyphens that are surrounded by alphanumeric
/// characters, which prevents a word like "--foo-bar" from being
/// split on the first or second hyphen.
impl WordSplitter for HyphenSplitter {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        let mut triples = Vec::new();
        // Split on hyphens, smallest split first. We only use hyphens
        // that are surrounded by alphanumeric characters. This is to
        // avoid splitting on repeated hyphens, such as those found in
        // --foo-bar.
        let mut char_indices = word.char_indices();
        // Early return if the word is empty.
        let mut prev = match char_indices.next() {
            None => return vec![(word, "", "")],
            Some((_, ch)) => ch,
        };

        // Find current word, or return early if the word only has a
        // single character.
        let (mut idx, mut cur) = match char_indices.next() {
            None => return vec![(word, "", "")],
            Some((idx, cur)) => (idx, cur),
        };

        for (i, next) in char_indices {
            if prev.is_alphanumeric() && cur == '-' && next.is_alphanumeric() {
                let (head, tail) = word.split_at(idx + 1);
                triples.push((head, "", tail));
            }
            prev = cur;
            idx = i;
            cur = next;
        }

        // Finally option is no split at all.
        triples.push((word, "", ""));

        triples
    }
}

/// A hyphenation dictionary can be used to do language-specific
/// hyphenation using patterns from the hyphenation crate.
///
/// **Note:** Only available when the `hyphenation` feature is
/// enabled.
#[cfg(feature = "hyphenation")]
impl WordSplitter for hyphenation::Standard {
    fn split<'w>(&self, word: &'w str) -> Vec<(&'w str, &'w str, &'w str)> {
        use hyphenation::Hyphenator;
        // Find splits based on language dictionary.
        let mut triples = Vec::new();
        for n in self.hyphenate(word).breaks {
            let (head, tail) = word.split_at(n);
            let hyphen = if head.ends_with('-') { "" } else { "-" };
            triples.push((head, hyphen, tail));
        }
        // Finally option is no split at all.
        triples.push((word, "", ""));

        triples
    }
}
<|endoftext|>


<commit_before>extern crate time;

use std::cell::{RefCell, Ref};
use std::rc::Rc;
use std::collections::HashMap;

/// A simple stopwatch taht can time events and print stats about them.
#[deriving(Send)]
pub struct Stopwatch {
  pub total_time: u64,
  // number of time windows we've clocked
  pub number_of_windows: u64,
}

impl Stopwatch {
  #[inline]
  /// Creates a new stopwatch.
  pub fn new() -> Stopwatch {
    Stopwatch {
      total_time: 0,
      number_of_windows: 0,
    }
  }

  #[inline]
  /// Times a function, updating stats as necessary.
  pub fn timed<T>(&mut self, event: | | -> T) -> T {
    let then = time::precise_time_ns();
    let ret = event();
    self.total_time += time::precise_time_ns() - then;
    self.number_of_windows += 1;
    ret
  }

  /// Prints out timing statistics of this stopwatch.
  fn print(&self, name: &str) {
    if self.number_of_windows == 0 {
      println!("{} never ran", name);
    } else {
      println!(
        "{}: {}ms over {} samples (avg {}ms)",
        name,
        self.total_time / 1000000,
        self.number_of_windows,
        (self.total_time / self.number_of_windows / 1000000),
      );
    }
  }

}

/// A set of stopwatches for multiple, named events.
pub struct TimerSet {
  timers: RefCell<HashMap<String, Rc<RefCell<Stopwatch>>>>,
}

impl TimerSet {
  /// Creates a new set of timers.
  pub fn new() -> TimerSet {
    TimerSet { timers: RefCell::new(HashMap::new()) }
  }

  /// Times the execution of a function, and logs it under a timer with
  /// the given name.
  ///
  /// You probably want to use the `time!` macro instead of using this
  /// directly.
  ///
  /// This function is not marked `mut` because borrow checking is done
  /// dynamically.
  pub fn time<T>(&self, name: &str, f: || -> T) -> T {
    // TODO(cgaebel): is the explicit scope needed here?
    let has_key = { self.timers.borrow().contains_key_equiv(&name) };

    let timer : Rc<RefCell<Stopwatch>> =
      if has_key {
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      } else {
        {
          self.timers
              .borrow_mut()
              .insert(String::from_str(name), Rc::new(RefCell::new(Stopwatch::new())));
        }
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      };

    timer.borrow_mut().timed(f)
  }

  /// Prints all the timer statistics to stdout, each tagged with their name.
  pub fn print(&self) {
    let timers = self.timers.borrow();

    let mut timer_vec : Vec<(&str, Ref<Stopwatch>)> =
      timers
        .iter()
        .map(|(name, sw)| (name.as_slice(), sw.borrow()))
        .collect();

    timer_vec.sort_by(|&(k1, _), &(k2, _)| k1.cmp(&k2));

    for &(name, ref timer) in timer_vec.iter() {
      timer.print(name);
    }
  }
}

#[test]
fn test_simple() {
  let ts = TimerSet::new();
  ts.time("hello", || {});
}

#[test]
fn test_nested() {
  let ts = TimerSet::new();
  ts.time("hello", || {
    ts.time("world", || {});
  });
}
<commit_msg>change stopwatch to print averages in microseconds<commit_after>extern crate time;

use std::cell::{RefCell, Ref};
use std::rc::Rc;
use std::collections::HashMap;

/// A simple stopwatch taht can time events and print stats about them.
#[deriving(Send)]
pub struct Stopwatch {
  pub total_time: u64,
  // number of time windows we've clocked
  pub number_of_windows: u64,
}

impl Stopwatch {
  #[inline]
  /// Creates a new stopwatch.
  pub fn new() -> Stopwatch {
    Stopwatch {
      total_time: 0,
      number_of_windows: 0,
    }
  }

  #[inline]
  /// Times a function, updating stats as necessary.
  pub fn timed<T>(&mut self, event: | | -> T) -> T {
    let then = time::precise_time_ns();
    let ret = event();
    self.total_time += time::precise_time_ns() - then;
    self.number_of_windows += 1;
    ret
  }

  /// Prints out timing statistics of this stopwatch.
  fn print(&self, name: &str) {
    if self.number_of_windows == 0 {
      println!("{} never ran", name);
    } else {
      println!(
        "{}: {}ms over {} samples (avg {}us)",
        name,
        self.total_time / 1000000,
        self.number_of_windows,
        (self.total_time / self.number_of_windows / 1000),
      );
    }
  }

}

/// A set of stopwatches for multiple, named events.
pub struct TimerSet {
  timers: RefCell<HashMap<String, Rc<RefCell<Stopwatch>>>>,
}

impl TimerSet {
  /// Creates a new set of timers.
  pub fn new() -> TimerSet {
    TimerSet { timers: RefCell::new(HashMap::new()) }
  }

  /// Times the execution of a function, and logs it under a timer with
  /// the given name.
  ///
  /// You probably want to use the `time!` macro instead of using this
  /// directly.
  ///
  /// This function is not marked `mut` because borrow checking is done
  /// dynamically.
  pub fn time<T>(&self, name: &str, f: || -> T) -> T {
    // TODO(cgaebel): is the explicit scope needed here?
    let has_key = { self.timers.borrow().contains_key_equiv(&name) };

    let timer : Rc<RefCell<Stopwatch>> =
      if has_key {
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      } else {
        {
          self.timers
              .borrow_mut()
              .insert(String::from_str(name), Rc::new(RefCell::new(Stopwatch::new())));
        }
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      };

    timer.borrow_mut().timed(f)
  }

  /// Prints all the timer statistics to stdout, each tagged with their name.
  pub fn print(&self) {
    let timers = self.timers.borrow();

    let mut timer_vec : Vec<(&str, Ref<Stopwatch>)> =
      timers
        .iter()
        .map(|(name, sw)| (name.as_slice(), sw.borrow()))
        .collect();

    timer_vec.sort_by(|&(k1, _), &(k2, _)| k1.cmp(&k2));

    for &(name, ref timer) in timer_vec.iter() {
      timer.print(name);
    }
  }
}

#[test]
fn test_simple() {
  let ts = TimerSet::new();
  ts.time("hello", || {});
}

#[test]
fn test_nested() {
  let ts = TimerSet::new();
  ts.time("hello", || {
    ts.time("world", || {});
  });
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let opt_size = self.width.checked_mul(self.height)
            .map_or(None, |v| v.checked_mul(3))
            .map_or(None, |v| v.checked_mul(self.bytewidth()));

        let size = match opt_size {
            Some(v) => v,
            None => return Err(ImageError::DimensionError),
        };

        let mut data = vec![0 as u8; size as usize];

        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}

/// Tests parsing binary buffers were written based on and validated against `identify` from
/// ImageMagick (https://www.imagemagick.org/script/identify.php).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = super::PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }
}
<commit_msg>Improve diagnostice messages<commit_after>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;
use std::ascii::AsciiExt;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        if !bytes.as_slice().is_ascii() {
            return Err(ImageError::FormatError("Non ascii character in preamble"))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Invalid number in preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let opt_size = self.width.checked_mul(self.height)
            .map_or(None, |v| v.checked_mul(3))
            .map_or(None, |v| v.checked_mul(self.bytewidth()));

        let size = match opt_size {
            Some(v) => v,
            None => return Err(ImageError::DimensionError),
        };

        let mut data = vec![0 as u8; size as usize];

        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}

/// Tests parsing binary buffers were written based on and validated against `identify` from
/// ImageMagick (https://www.imagemagick.org/script/identify.php).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = super::PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }
}
<|endoftext|>


<commit_before>
use serialize::json;
use serialize::json::{Json, ToJson};
use std::collections::TreeMap;

use mutable_json::MutableJson;
use builder::Builder;
use helpers::{single_coerce_error};
use ValicoResult;

pub trait Coercer: Send + Sync {
	fn coerce(&self, &mut Json, Option<&Builder>) -> ValicoResult<Option<Json>>;
}

pub struct StringCoercer;

impl Coercer for StringCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_string() {
			Ok(None)
		} else if val.is_number() {
			Ok(Some(val.to_string().to_json()))
		} else {
			Err(
				single_coerce_error(format!("Can't coerce object {} to string", val))
			)
		}
	}
}

pub struct I64Coercer;

impl Coercer for I64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_i64() {
			return Ok(None)
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<i64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to i64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to i64", val)))
		}
	}
}

pub struct U64Coercer;

impl Coercer for U64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_u64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<u64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to u64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to u64", val)))
		}
	}
}

pub struct F64Coercer;

impl Coercer for F64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_f64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<f64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to f64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to f64", val)))
		}
	}
}

pub struct BooleanCoercer;

impl Coercer for BooleanCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_boolean() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "true" {
				Ok(Some(true.to_json()))
			} else if val == "false" {
				Ok(Some(false.to_json()))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to boolean. Correct values is 'true' and 'false'", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to boolean", val)))
		}
	}
}

pub struct NullCoercer;

impl Coercer for NullCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_null() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "" {
				Ok(Some(json::Null))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to null. Correct value is only empty string", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

pub struct ListCoercer {
	sub_coercer: Option<Box<Coercer + Send + Sync>>
}

impl ListCoercer {
	pub fn new() -> ListCoercer {
		ListCoercer {
			sub_coercer: None
		}
	}

	pub fn of_type(sub_coercer: Box<Coercer + Send + Sync>) -> ListCoercer {
		ListCoercer {
			sub_coercer: Some(sub_coercer)
		}
	}
}

impl Coercer for ListCoercer {
	fn coerce(&self, val: &mut Json, nest: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_list() {
			let list = val.as_list_mut().unwrap();
			let mut errors = TreeMap::new();
			if nest.is_some() {
				for (idx, item) in list.iter_mut().enumerate() {
					if item.is_object() {
						match nest.unwrap().process(item.as_object_mut().unwrap()) {
							Ok(()) => (),
							Err(err) => { errors.insert(idx.to_string(), err.to_json()); }
						}
					} else {
						errors.insert(idx.to_string(), format!("List item {} is not and object", item).to_json());
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else if self.sub_coercer.is_some() {
				let sub_coercer = self.sub_coercer.as_ref().unwrap();
				let mut errors = TreeMap::new();
				for i in range(0, list.len()) {
					match sub_coercer.coerce(list.get_mut(i), None) {
						Ok(Some(value)) => {
							list.remove(i);
							list.insert(i, value);
						},
						Ok(None) => (),
						Err(err) => {
							errors.insert(i.to_string(), err.to_json());
						}
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else {
				Ok(None)
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to list", val)))
		}
	}
}

pub struct ObjectCoercer;

impl Coercer for ObjectCoercer {
	fn coerce(&self, val: &mut Json, nest: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_object() {
			if nest.is_some() {
				nest.unwrap().process(val.as_object_mut().unwrap()).map(|()| None)
			} else {
				Ok(None)
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce non-object value {} to object", val)))
		}
	}
}
<commit_msg>fix: error in coercer<commit_after>
use serialize::json;
use serialize::json::{Json, ToJson};
use std::collections::TreeMap;

use mutable_json::MutableJson;
use builder::Builder;
use helpers::{single_coerce_error};
use ValicoResult;

pub trait Coercer: Send + Sync {
	fn coerce(&self, &mut Json, Option<&Builder>) -> ValicoResult<Option<Json>>;
}

pub struct StringCoercer;

impl Coercer for StringCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_string() {
			Ok(None)
		} else if val.is_number() {
			Ok(Some(val.to_string().to_json()))
		} else {
			Err(
				single_coerce_error(format!("Can't coerce object {} to string", val))
			)
		}
	}
}

pub struct I64Coercer;

impl Coercer for I64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_i64() {
			return Ok(None)
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<i64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to i64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to i64", val)))
		}
	}
}

pub struct U64Coercer;

impl Coercer for U64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_u64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<u64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to u64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to u64", val)))
		}
	}
}

pub struct F64Coercer;

impl Coercer for F64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_f64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<f64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to f64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to f64", val)))
		}
	}
}

pub struct BooleanCoercer;

impl Coercer for BooleanCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_boolean() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "true" {
				Ok(Some(true.to_json()))
			} else if val == "false" {
				Ok(Some(false.to_json()))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to boolean. Correct values is 'true' and 'false'", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to boolean", val)))
		}
	}
}

pub struct NullCoercer;

impl Coercer for NullCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_null() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "" {
				Ok(Some(json::Null))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to null. Correct value is only empty string", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

pub struct ListCoercer {
	sub_coercer: Option<Box<Coercer + Send + Sync>>
}

impl ListCoercer {
	pub fn new() -> ListCoercer {
		ListCoercer {
			sub_coercer: None
		}
	}

	pub fn of_type(sub_coercer: Box<Coercer + Send + Sync>) -> ListCoercer {
		ListCoercer {
			sub_coercer: Some(sub_coercer)
		}
	}
}

impl Coercer for ListCoercer {
	fn coerce(&self, val: &mut Json, nest: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_list() {
			let list = val.as_list_mut().unwrap();
			let mut errors = TreeMap::new();
			if nest.is_some() {
				for (idx, item) in list.iter_mut().enumerate() {
					if item.is_object() {
						match nest.unwrap().process(item.as_object_mut().unwrap()) {
							Ok(()) => (),
							Err(err) => { errors.insert(idx.to_string(), err.to_json()); }
						}
					} else {
						errors.insert(idx.to_string(),
							single_coerce_error(format!("List item {} is not and object", item)).to_json()
						);
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else if self.sub_coercer.is_some() {
				let sub_coercer = self.sub_coercer.as_ref().unwrap();
				let mut errors = TreeMap::new();
				for i in range(0, list.len()) {
					match sub_coercer.coerce(list.get_mut(i), None) {
						Ok(Some(value)) => {
							list.remove(i);
							list.insert(i, value);
						},
						Ok(None) => (),
						Err(err) => {
							errors.insert(i.to_string(), err.to_json());
						}
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else {
				Ok(None)
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to list", val)))
		}
	}
}

pub struct ObjectCoercer;

impl Coercer for ObjectCoercer {
	fn coerce(&self, val: &mut Json, nest: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_object() {
			if nest.is_some() {
				nest.unwrap().process(val.as_object_mut().unwrap()).map(|()| None)
			} else {
				Ok(None)
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce non-object value {} to object", val)))
		}
	}
}
<|endoftext|>


<commit_before>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver: mpsc::Receiver<T>,
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl<T> EventedImpl for Receiver<T>
    where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&mut self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify", token.as_usize());
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn reregister(&mut self,
                  _event_loop: &mut EventLoop<Handler>,
                  token: Token,
                  interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn deregister(&mut self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, receiver: mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => return Ok(t),
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let _prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            // since send() first sends, then increases the counter, it is
            // possible for _prev_counter to be zero
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

struct SenderShared {
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl Drop for SenderShared {
    fn drop(&mut self) {

        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);
        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared);
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::Sender<T>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }
}

fn maybe_notify_receiver(shared: &ArcChannelShared) {
    let mut lock = shared.lock();
    let ChannelShared { ref mut sender, ref mut token } = *lock;

    if let Some(token) = *token {
        trace!("Sender: notifying {:?}", token);
        let sender = sender.as_ref().unwrap();
        sender_retry(&sender, Message::ChannelMsg(token))
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (Sender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

unsafe impl<T> Send for Receiver<T> {}
<commit_msg>Limit `Send` in `mpsc`<commit_after>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver: mpsc::Receiver<T>,
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl<T> EventedImpl for Receiver<T>
    where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&mut self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify", token.as_usize());
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn reregister(&mut self,
                  _event_loop: &mut EventLoop<Handler>,
                  token: Token,
                  interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn deregister(&mut self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, receiver: mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => return Ok(t),
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let _prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            // since send() first sends, then increases the counter, it is
            // possible for _prev_counter to be zero
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

struct SenderShared {
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl Drop for SenderShared {
    fn drop(&mut self) {

        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);
        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared);
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::Sender<T>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }
}

fn maybe_notify_receiver(shared: &ArcChannelShared) {
    let mut lock = shared.lock();
    let ChannelShared { ref mut sender, ref mut token } = *lock;

    if let Some(token) = *token {
        trace!("Sender: notifying {:?}", token);
        let sender = sender.as_ref().unwrap();
        sender_retry(&sender, Message::ChannelMsg(token))
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (Sender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

unsafe impl<T : Send> Send for Receiver<T> {}
unsafe impl<T : Send> Send for Sender<T> {}
<|endoftext|>


<commit_before>#![crate_name = "sync"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alexander Fomin <xander.fomin@ya.ru>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

 /* Last synced with: sync (GNU coreutils) 8.13 */

extern crate getopts;
extern crate libc;

#[path = "../common/util.rs"] #[macro_use] mod util;

static NAME: &'static str = "sync";
static VERSION: &'static str = "1.0.0";

#[cfg(unix)]
mod platform {
    use super::libc;

    extern {
        fn sync() -> libc::c_void;
    }

    pub unsafe fn do_sync() -> isize {
        sync();
        0
    }
}

#[cfg(windows)]
mod platform {
    extern crate winapi;
    extern crate kernel32;
    #[path = "../../common/wide.rs"] mod wide;
    use std::{mem};
    use std::fs::OpenOptions;
    use std::io::{Write};
    use std::os::windows::prelude::*;
    use self::wide::{FromWide, ToWide};

    unsafe fn flush_volume(name: &str) {
        let name_wide = name.to_wide_null();
        if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winapi::DRIVE_FIXED {
            let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
            match OpenOptions::new().write(true).open(sliced_name) {
                Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 {
                    crash!(kernel32::GetLastError() as i32, "failed to flush file buffer");
                },
                Err(e) => crash!(e.raw_os_error().unwrap_or(1), "failed to create volume handle")
            }
        }
    }

    unsafe fn find_first_volume() -> (String, winapi::HANDLE) {
        let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
        let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as winapi::DWORD);
        if handle == winapi::INVALID_HANDLE_VALUE {
            crash!(kernel32::GetLastError() as i32, "failed to find first volume");
        }
        (String::from_wide_null(&name), handle)
    }

    unsafe fn find_all_volumes() -> Vec<String> {
        let (first_volume, next_volume_handle) = find_first_volume();
        let mut volumes = vec![first_volume];
        loop {
            let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
            if kernel32::FindNextVolumeW(
                next_volume_handle, name.as_mut_ptr(), name.len() as winapi::DWORD
            ) == 0 {
                match kernel32::GetLastError() {
                    winapi::ERROR_NO_MORE_FILES => {
                        kernel32::FindVolumeClose(next_volume_handle);
                        return volumes
                    },
                    err => crash!(err as i32, "failed to find next volume"),
                }
            } else {
                volumes.push(String::from_wide_null(&name));
            }
        }
    }

    pub unsafe fn do_sync() -> isize {
        let volumes = find_all_volumes();
        for vol in &volumes {
            flush_volume(vol);
        }
        0
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        _ => { help(&opts); return 1 }
    };

    if matches.opt_present("h") {
        help(&opts);
        return 0
    }

    if matches.opt_present("V") {
        version();
        return 0
    }

    sync();
    0
}

fn version() {
    println!("{} (uutils) {}", NAME, VERSION);
    println!("The MIT License");
    println!("");
    println!("Author -- Alexander Fomin.");
}

fn help(opts: &getopts::Options) {
    let msg = format!("{0} {1}

Usage:
  {0} [OPTION]

Force changed blocks to disk, update the super block.", NAME, VERSION);

    print!("{}", opts.usage(&msg));
}

fn sync() -> isize {
    unsafe {
        platform::do_sync()
    }
}
<commit_msg>Fix build on non-windows<commit_after>#![crate_name = "sync"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alexander Fomin <xander.fomin@ya.ru>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

 /* Last synced with: sync (GNU coreutils) 8.13 */

extern crate getopts;
extern crate libc;

#[path = "../common/util.rs"] #[macro_use] mod util;
#[cfg(windows)] #[path = "../common/wide.rs"] mod wide;

static NAME: &'static str = "sync";
static VERSION: &'static str = "1.0.0";

#[cfg(unix)]
mod platform {
    use super::libc;

    extern {
        fn sync() -> libc::c_void;
    }

    pub unsafe fn do_sync() -> isize {
        sync();
        0
    }
}

#[cfg(windows)]
mod platform {
    extern crate winapi;
    extern crate kernel32;
    use std::{mem};
    use std::fs::OpenOptions;
    use std::io::{Write};
    use std::os::windows::prelude::*;
    use wide::{FromWide, ToWide};

    unsafe fn flush_volume(name: &str) {
        let name_wide = name.to_wide_null();
        if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winapi::DRIVE_FIXED {
            let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
            match OpenOptions::new().write(true).open(sliced_name) {
                Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 {
                    crash!(kernel32::GetLastError() as i32, "failed to flush file buffer");
                },
                Err(e) => crash!(e.raw_os_error().unwrap_or(1), "failed to create volume handle")
            }
        }
    }

    unsafe fn find_first_volume() -> (String, winapi::HANDLE) {
        let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
        let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as winapi::DWORD);
        if handle == winapi::INVALID_HANDLE_VALUE {
            crash!(kernel32::GetLastError() as i32, "failed to find first volume");
        }
        (String::from_wide_null(&name), handle)
    }

    unsafe fn find_all_volumes() -> Vec<String> {
        let (first_volume, next_volume_handle) = find_first_volume();
        let mut volumes = vec![first_volume];
        loop {
            let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
            if kernel32::FindNextVolumeW(
                next_volume_handle, name.as_mut_ptr(), name.len() as winapi::DWORD
            ) == 0 {
                match kernel32::GetLastError() {
                    winapi::ERROR_NO_MORE_FILES => {
                        kernel32::FindVolumeClose(next_volume_handle);
                        return volumes
                    },
                    err => crash!(err as i32, "failed to find next volume"),
                }
            } else {
                volumes.push(String::from_wide_null(&name));
            }
        }
    }

    pub unsafe fn do_sync() -> isize {
        let volumes = find_all_volumes();
        for vol in &volumes {
            flush_volume(vol);
        }
        0
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        _ => { help(&opts); return 1 }
    };

    if matches.opt_present("h") {
        help(&opts);
        return 0
    }

    if matches.opt_present("V") {
        version();
        return 0
    }

    sync();
    0
}

fn version() {
    println!("{} (uutils) {}", NAME, VERSION);
    println!("The MIT License");
    println!("");
    println!("Author -- Alexander Fomin.");
}

fn help(opts: &getopts::Options) {
    let msg = format!("{0} {1}

Usage:
  {0} [OPTION]

Force changed blocks to disk, update the super block.", NAME, VERSION);

    print!("{}", opts.usage(&msg));
}

fn sync() -> isize {
    unsafe {
        platform::do_sync()
    }
}
<|endoftext|>


<commit_before>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

bitflags!(
    #[repr(C)]
    pub flags EpollFlags: libc::c_int {
        const EPOLLIN = libc::EPOLLIN,
        const EPOLLPRI = libc::EPOLLPRI,
        const EPOLLOUT = libc::EPOLLOUT,
        const EPOLLRDNORM = libc::EPOLLRDNORM,
        const EPOLLRDBAND = libc::EPOLLRDBAND,
        const EPOLLWRNORM = libc::EPOLLWRNORM,
        const EPOLLWRBAND = libc::EPOLLWRBAND,
        const EPOLLMSG = libc::EPOLLMSG,
        const EPOLLERR = libc::EPOLLERR,
        const EPOLLHUP = libc::EPOLLHUP,
        const EPOLLRDHUP = libc::EPOLLRDHUP,
        const EPOLLEXCLUSIVE = 1 << 28,
        const EPOLLWAKEUP = libc::EPOLLWAKEUP,
        const EPOLLONESHOT = libc::EPOLLONESHOT,
        const EPOLLET = libc::EPOLLET,
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

libc_bitflags!{
    pub flags EpollCreateFlags: c_int {
        EPOLL_CLOEXEC,
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<commit_msg>epoll: Use libc_bitflags for EpollFlags<commit_after>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

libc_bitflags!(
    pub flags EpollFlags: libc::c_int {
        EPOLLIN,
        EPOLLPRI,
        EPOLLOUT,
        EPOLLRDNORM,
        EPOLLRDBAND,
        EPOLLWRNORM,
        EPOLLWRBAND,
        EPOLLMSG,
        EPOLLERR,
        EPOLLHUP,
        EPOLLRDHUP,
        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
        EPOLLEXCLUSIVE,
        EPOLLWAKEUP,
        EPOLLONESHOT,
        EPOLLET,
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

libc_bitflags!{
    pub flags EpollCreateFlags: c_int {
        EPOLL_CLOEXEC,
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<|endoftext|>


<commit_before>///! Provide helpers for making ioctl system calls
///!
///! # Overview of IOCTLs
///!
///! The `ioctl` system call is a widely support system
///! call on *nix systems providing access to functions
///! and data that do not fit nicely into the standard
///! read and write operations on a file itself.  It is
///! common to see ioctls used for the following purposes:
///!
///! * Provide read/write access to out-of-band data related
///!   to a device such as configuration (for instance, setting
///!   serial port options)
///! * Provide a mechanism for performing full-duplex data
///!   transfers (for instance, xfer on SPI devices).
///! * Provide access to control functions on a device (for example,
///!   on Linux you can send commands like pause, resume, and eject
///!   to the CDROM device.
///! * Do whatever else the device driver creator thought made most sense.
///!
///! Ioctls are synchronous system calls and are similar to read and
///! write calls in that regard.
///!
///! The prototype for the ioctl system call in libc is as follows:
///!
///! ```c
///! int ioctl(int fd, unsigned long request, ...);
///! ```
///!
///! Typically, an ioctl takes 3 parameters as arguments:
///! 1. An open file descriptor, `fd`.
///! 2. An device-dependennt request code or operation.  This request
///!    code is referred to as `op` in this module.
///! 3. Either a pointer to a location in memory or an integer.  This
///!    number of pointer may either be used by the kernel or written
///!    to by the kernel depending on how the operation is documented
///!    to work.
///!
///! The `op` request code is essentially an arbitrary integer having
///! a device-driver specific meaning.  Over time, it proved difficult
///! for various driver implementors to use this field sanely, so a
///! convention with macros was introduced to the Linux Kernel that
///! is used by most newer drivers.  See
///! https://github.com/torvalds/linux/blob/master/Documentation/ioctl/ioctl-number.txt
///! for additional details.  The macros exposed by the kernel for
///! consumers are implemented in this module and may be used to
///! instead of calls like `_IOC`, `_IO`, `_IOR`, and `_IOW`.
///!
///! # Interface Overview
///!
///! This ioctl module seeks to tame the ioctl beast by providing
///! a set of safer (although not safe) functions
///! implementing the most common ioctl access patterns.
///!
///! The most common access patterns for ioctls are as follows:
///! 1. `read`: A pointer is provided to the kernel which is populated
///!    with a value containing the "result" of the operation.  The
///!    result may be an integer or structure.  The kernel may also
///!    read values from the provided pointer (usually a structure).
///! 2. `write`: A pointer is provided to the kernel containing values
///!    that the kernel will read in order to perform the operation.
///! 3. `execute`: The operation is passed to the kernel but no
///!    additional pointer is passed.  The operation is enough
///!    and it either succeeds or results in an error.
///!
///! Where appropriate, versions of these interface function are provided
///! taking either refernces or pointers.  The pointer versions are
///! necessary for cases (notably slices) where a reference cannot
///! be generically cast to a pointer.

use libc::{c_int, c_ulong};
use libc::funcs::bsd44::ioctl as libc_ioctl;
use std::mem;
use fcntl::Fd;
use {Error, Result, errno};

pub type ioctl_op_t = c_ulong;

// the libc definiton of the 'op' type is platform dependent
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
type os_ioctl_op_t = c_ulong;

#[cfg(any(target_os = "linux", target_os = "android"))]
type os_ioctl_op_t = c_int;

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
// const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

/// Flags indicating the direction of the ioctl operation
/// for ioctls using modern operation conventions
bitflags! {
    flags IoctlDirFlags: u8 {
        /// Indicates that the ioctl data pointer is not used
        const IOC_NONE  = 0x00,
        /// Indicates that the ioctl data pointer contains data that
        /// will be consumed by the operating system
        const IOC_WRITE = 0x01,
        /// Indicates tha the ioctl data pointer contains data that
        /// will be populated by the operating system to be consumed
        /// by userspace
        const IOC_READ  = 0x02,
    }
}

/// Build an ioctl op with the provide parameters.  This is a helper
/// function for IOCTLs in the Linux kernel using the newer conventions
/// for IOCTLs operations.  Many ioctls do not use this newer convention
/// and the constants for those should just be used as-is.
///
/// This provides the same functionality as the Linux `_IOC` macro.
pub fn op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    // actual number will always fit in 32 bits, but ioctl() expects
    // an unsigned long for the op
    let size_to_use: u32 = if size < (1 << IOC_SIZEBITS) { size as u32 } else { 0 };
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size_to_use) << IOC_SIZESHIFT)) as ioctl_op_t
}

/// Build an op indicating that the data pointer is not used.
/// That is, the command itself is sufficient.
///
/// This provides the same functionality the Linux `_IO` macro.
pub fn op_none(ioctl_type: u8, nr: u8) -> ioctl_op_t {
    op(IOC_NONE, ioctl_type, nr, 0)
}

/// Build an op indicating that the data pointer will be populated
/// with data from the kernel
///
/// This provides the same functionality as the Linux `_IOR` macro.
pub fn op_read(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_READ, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer contains data
/// to be consumed by the kernel (and not written to).
///
/// This provides the same functionality as the Linux `_IOW` macro.
pub fn op_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer both contains
/// data to be consumed by the kernel and contains fields that
/// will be populated by the kernel.
///
/// This provides the same functionality as the Linux `_IOWR` macro.
pub fn op_read_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

fn convert_ioctl_res(res: c_int) -> Result<c_int> {
    if res < 0 {
        return Err(Error::Sys(errno::Errno::last()))
    }
    Ok(res) // res may length or similar useful to caller
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
///
/// This function will allocate allocate space for and returned an owned
/// reference to the result.
pub unsafe fn read<T>(fd: Fd, op: ioctl_op_t) -> Result<T> {
    // allocate memory for the result (should get a value from kernel)
    let mut dst: T = mem::zeroed();
    let dst_ptr: *mut T = &mut dst;
    try!(read_into_ptr(fd, op, dst_ptr));
    Ok(dst)
}

/// Ioctl where the result from the kernel will be written to the
/// provided reference
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into<T>(fd: Fd, op: ioctl_op_t, data: &mut T) -> Result<c_int> {
    read_into_ptr(fd, op, data as *mut T)
}

/// Ioctl where the result from the kernel will be written to the
/// provided pointer
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into_ptr<T>(fd: Fd, op: ioctl_op_t, data_ptr: *mut T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data_ptr))
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write<T>(fd: Fd, op: ioctl_op_t, data: &T) -> Result<c_int> {
    write_ptr(fd, op, data as *const T)
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write_ptr<T>(fd: Fd, op: ioctl_op_t, data: *const T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data as *const T))
}

/// Ioctl call for which no data pointer is provided to the kernel.
/// That is, the kernel has sufficient information about what to
/// do based on the op alone.
pub fn execute(fd: Fd, op: ioctl_op_t) -> Result<c_int> {
    convert_ioctl_res(unsafe { libc_ioctl(fd, op as os_ioctl_op_t) })
}
<commit_msg>docs: fix module documentation for ioctl<commit_after>//! Provide helpers for making ioctl system calls
//!
//! # Overview of IOCTLs
//!
//! The `ioctl` system call is a widely support system
//! call on *nix systems providing access to functions
//! and data that do not fit nicely into the standard
//! read and write operations on a file itself.  It is
//! common to see ioctls used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! Ioctls are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! The prototype for the ioctl system call in libc is as follows:
//!
//! ```c
//! int ioctl(int fd, unsigned long request, ...);
//! ```
//!
//! Typically, an ioctl takes 3 parameters as arguments:
//!
//! 1. An open file descriptor, `fd`.
//! 2. An device-dependennt request code or operation.  This request
//!    code is referred to as `op` in this module.
//! 3. Either a pointer to a location in memory or an integer.  This
//!    number of pointer may either be used by the kernel or written
//!    to by the kernel depending on how the operation is documented
//!    to work.
//!
//! The `op` request code is essentially an arbitrary integer having
//! a device-driver specific meaning.  Over time, it proved difficult
//! for various driver implementors to use this field sanely, so a
//! convention with macros was introduced to the Linux Kernel that
//! is used by most newer drivers.  See
//! https://github.com/torvalds/linux/blob/master/Documentation/ioctl/ioctl-number.txt
//! for additional details.  The macros exposed by the kernel for
//! consumers are implemented in this module and may be used to
//! instead of calls like `_IOC`, `_IO`, `_IOR`, and `_IOW`.
//!
//! # Interface Overview
//!
//! This ioctl module seeks to tame the ioctl beast by providing
//! a set of safer (although not safe) functions
//! implementing the most common ioctl access patterns.
//!
//! The most common access patterns for ioctls are as follows:
//!
//! 1. `read`: A pointer is provided to the kernel which is populated
//!    with a value containing the "result" of the operation.  The
//!    result may be an integer or structure.  The kernel may also
//!    read values from the provided pointer (usually a structure).
//! 2. `write`: A pointer is provided to the kernel containing values
//!    that the kernel will read in order to perform the operation.
//! 3. `execute`: The operation is passed to the kernel but no
//!    additional pointer is passed.  The operation is enough
//!    and it either succeeds or results in an error.
//!
//! Where appropriate, versions of these interface function are provided
//! taking either refernces or pointers.  The pointer versions are
//! necessary for cases (notably slices) where a reference cannot
//! be generically cast to a pointer.

use libc::{c_int, c_ulong};
use libc::funcs::bsd44::ioctl as libc_ioctl;
use std::mem;
use fcntl::Fd;
use {Error, Result, errno};

pub type ioctl_op_t = c_ulong;

// the libc definiton of the 'op' type is platform dependent
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
type os_ioctl_op_t = c_ulong;

#[cfg(any(target_os = "linux", target_os = "android"))]
type os_ioctl_op_t = c_int;

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
// const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

/// Flags indicating the direction of the ioctl operation
/// for ioctls using modern operation conventions
bitflags! {
    flags IoctlDirFlags: u8 {
        /// Indicates that the ioctl data pointer is not used
        const IOC_NONE  = 0x00,
        /// Indicates that the ioctl data pointer contains data that
        /// will be consumed by the operating system
        const IOC_WRITE = 0x01,
        /// Indicates tha the ioctl data pointer contains data that
        /// will be populated by the operating system to be consumed
        /// by userspace
        const IOC_READ  = 0x02,
    }
}

/// Build an ioctl op with the provide parameters.  This is a helper
/// function for IOCTLs in the Linux kernel using the newer conventions
/// for IOCTLs operations.  Many ioctls do not use this newer convention
/// and the constants for those should just be used as-is.
///
/// This provides the same functionality as the Linux `_IOC` macro.
pub fn op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    // actual number will always fit in 32 bits, but ioctl() expects
    // an unsigned long for the op
    let size_to_use: u32 = if size < (1 << IOC_SIZEBITS) { size as u32 } else { 0 };
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size_to_use) << IOC_SIZESHIFT)) as ioctl_op_t
}

/// Build an op indicating that the data pointer is not used.
/// That is, the command itself is sufficient.
///
/// This provides the same functionality the Linux `_IO` macro.
pub fn op_none(ioctl_type: u8, nr: u8) -> ioctl_op_t {
    op(IOC_NONE, ioctl_type, nr, 0)
}

/// Build an op indicating that the data pointer will be populated
/// with data from the kernel
///
/// This provides the same functionality as the Linux `_IOR` macro.
pub fn op_read(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_READ, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer contains data
/// to be consumed by the kernel (and not written to).
///
/// This provides the same functionality as the Linux `_IOW` macro.
pub fn op_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer both contains
/// data to be consumed by the kernel and contains fields that
/// will be populated by the kernel.
///
/// This provides the same functionality as the Linux `_IOWR` macro.
pub fn op_read_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

fn convert_ioctl_res(res: c_int) -> Result<c_int> {
    if res < 0 {
        return Err(Error::Sys(errno::Errno::last()))
    }
    Ok(res) // res may length or similar useful to caller
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
///
/// This function will allocate allocate space for and returned an owned
/// reference to the result.
pub unsafe fn read<T>(fd: Fd, op: ioctl_op_t) -> Result<T> {
    // allocate memory for the result (should get a value from kernel)
    let mut dst: T = mem::zeroed();
    let dst_ptr: *mut T = &mut dst;
    try!(read_into_ptr(fd, op, dst_ptr));
    Ok(dst)
}

/// Ioctl where the result from the kernel will be written to the
/// provided reference
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into<T>(fd: Fd, op: ioctl_op_t, data: &mut T) -> Result<c_int> {
    read_into_ptr(fd, op, data as *mut T)
}

/// Ioctl where the result from the kernel will be written to the
/// provided pointer
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into_ptr<T>(fd: Fd, op: ioctl_op_t, data_ptr: *mut T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data_ptr))
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write<T>(fd: Fd, op: ioctl_op_t, data: &T) -> Result<c_int> {
    write_ptr(fd, op, data as *const T)
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write_ptr<T>(fd: Fd, op: ioctl_op_t, data: *const T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data as *const T))
}

/// Ioctl call for which no data pointer is provided to the kernel.
/// That is, the kernel has sufficient information about what to
/// do based on the op alone.
pub fn execute(fd: Fd, op: ioctl_op_t) -> Result<c_int> {
    convert_ioctl_res(unsafe { libc_ioctl(fd, op as os_ioctl_op_t) })
}
<|endoftext|>