<commit_before>extern crate pine;

use time;
use std::fmt;
use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::process::{Command, Stdio};
use std::sync::mpsc::Receiver;
use super::Event;
use super::rep::Payload;

/// Represents a description of a github hook
/// A hook should describe a cmd to run and for which
/// events. It should be assumed that the github event name
/// and event payload will be available in env vars
/// `GH_EVENT_NAME` and `GH_EVENT_PAYLOAD` respectively
#[derive(Clone, Default, Debug, RustcDecodable, RustcEncodable)]
pub struct Hook {
  /// Command to run when an event is recieved
  pub cmd: String,
  /// List of github events that should trigger this hook
  pub events: Vec<String>,
  /// Optional name of hook. Defaults to cmd
  pub name: Option<String>,
  /// Github organization filter
  pub organization: Option<String>,
  /// Github repository filter
  pub repository: Option<String>,
  /// Github event sender filter
  pub sender: Option<String>
}

struct Log {
  timestamp: String,
  src: String,
  delivery: String,
  message: String
}

impl Log {
  fn new<S: Into<String>>(src: &String, delivery: &String, message: S) -> Log {
    Log {
      timestamp: time::now().to_utc().rfc3339().to_string(),
      src: src.clone(),
      delivery: delivery.clone(),
      message: message.into()
    }
  }
}

impl fmt::Display for Log {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{} {} {} {}", self.timestamp, self.src, self.delivery, self.message)
  }
}

impl Hook {

  /// return a debug hook that targets all events
  /// and does nothing but echo the event name and payload
  pub fn echo() -> Hook {
     Hook {
       cmd: "echo \"$GH_EVENT_NAME\": \"$GH_EVENT_PAYLOAD\"".to_owned(),
       events: vec!["*".to_owned()],
       ..Default::default()
     }
  }

  /// return true if this hook targets the provided
  /// event name, false otherwise
  pub fn targets(&self, event: &String, payload: &Payload) -> bool {
    // todo: filter on payload.{ repo, org, sender }
    let targets_event = self.events.contains(event)
      || self.events.contains(&"*".to_owned());
    if let Some(ref porg) = payload.organization {
      if let Some(ref org) = self.organization {
        if porg.login != *org {
          return false
        }
      }
    }
    if let Some(ref prepo) = payload.repository {
      if let Some(ref repo) = self.repository {
        if prepo.name != *repo {
          return false
        }
      }
    }
    targets_event
  }

  /// return name if defined, otherwise cmd
  pub fn name(&self) -> String {
    self.name.clone().unwrap_or(self.cmd.clone())
  }

  /// start recv'ing events
  pub fn recv(&self, rx: Receiver<Event>) {
    loop {
      match rx.recv() {
        Ok(event) => {
          self.run(&event);
          ()
        },
        Err(e) => {
          error!("{}", Log::new(&"-".to_owned(), &"-".to_owned(), format!("Recv err: {}\n", e.to_string())));
          break
        }
      }
    }
  }

  fn log<S: Into<String>>(&self, event: &Event, msg: S) -> Log {
    Log::new(&self.name(), &event.delivery, msg)
  }

  /// run hook cmd, returning true if cmd succeeded, otherwise false
  pub fn run(&self, event: &Event) -> bool {

     match Command::new("/bin/sh")
       .arg("-c")
       .arg(&self.cmd)
       .env("GH_DELIVERY", &event.delivery)
       .env("GH_EVENT_NAME", &event.name)
       .env("GH_EVENT_PAYLOAD", &event.payload)
       .stdin(Stdio::null())
       .stdout(Stdio::piped())
       .stderr(Stdio::piped())
       .spawn() {
         Err(e) => {
           error!(
             "{}", &self.log(
               &event, format!("error executing {}: {}\n", self.cmd, e)
              )
           );
           false
         },
         Ok(mut child)  => {

           let lines = pine::lines(&mut child);
           let status = child.wait();
           for l in lines.iter() {
             info!("{}", self.log(&event, format!("{:?}", l)));
           }

           match status {
             Ok(s) => {
               if s.success() {
                 info!("{}", self.log(&event, "that worked"));
                 true
               } else {
                 match s.code() {
                   Some(c) => info!("{}", self.log(&event, format!("hook exited with status {}\n", c))),
                   _ => if let Some(s) = s.signal() {
                     error!("{}", self.log(&event, format!("process killed by signal {}\n", s)))
                   }
                 };
                 false
               }
             },
             Err(e) => {
               error!("{}", self.log(&event, format!("error getting exit status {}\n", e.to_string())));
               false
             }
           }
         }
       }
  }
}

#[cfg(test)]
mod tests {
  use super::Hook;
  use super::super::Event;

  #[test]
  fn test_hook_run_pass() {
    let hook = Hook {
      cmd: "true".to_owned(),
      ..Default::default()
    };
    assert!(hook.run(&Event {
      ..Default::default()
    }))
  }

  #[test]
  fn test_hook_run_fail() {
    let hook = Hook {
      cmd: "false".to_owned(),
      ..Default::default()
    };
    assert!(!hook.run(&Event {
      ..Default::default()
    }))
  }

  #[test]
  fn test_hook_run_panic() {
    let hook = Hook {
      cmd: "oiusdfasdf".to_owned(),
      ..Default::default()
    };
    assert!(!hook.run(&Event {
      ..Default::default()
    }))
  }
}
<commit_msg>log output first<commit_after>extern crate pine;

use time;
use std::fmt;
use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::process::{Command, Stdio};
use std::sync::mpsc::Receiver;
use super::Event;
use super::rep::Payload;

/// Represents a description of a github hook
/// A hook should describe a cmd to run and for which
/// events. It should be assumed that the github event name
/// and event payload will be available in env vars
/// `GH_EVENT_NAME` and `GH_EVENT_PAYLOAD` respectively
#[derive(Clone, Default, Debug, RustcDecodable, RustcEncodable)]
pub struct Hook {
  /// Command to run when an event is recieved
  pub cmd: String,
  /// List of github events that should trigger this hook
  pub events: Vec<String>,
  /// Optional name of hook. Defaults to cmd
  pub name: Option<String>,
  /// Github organization filter
  pub organization: Option<String>,
  /// Github repository filter
  pub repository: Option<String>,
  /// Github event sender filter
  pub sender: Option<String>
}

struct Log {
  timestamp: String,
  src: String,
  delivery: String,
  message: String
}

impl Log {
  fn new<S: Into<String>>(src: &String, delivery: &String, message: S) -> Log {
    Log {
      timestamp: time::now().to_utc().rfc3339().to_string(),
      src: src.clone(),
      delivery: delivery.clone(),
      message: message.into()
    }
  }
}

impl fmt::Display for Log {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{} {} {} {}", self.timestamp, self.src, self.delivery, self.message)
  }
}

impl Hook {

  /// return a debug hook that targets all events
  /// and does nothing but echo the event name and payload
  pub fn echo() -> Hook {
     Hook {
       cmd: "echo \"$GH_EVENT_NAME\": \"$GH_EVENT_PAYLOAD\"".to_owned(),
       events: vec!["*".to_owned()],
       ..Default::default()
     }
  }

  /// return true if this hook targets the provided
  /// event name, false otherwise
  pub fn targets(&self, event: &String, payload: &Payload) -> bool {
    // todo: filter on payload.{ repo, org, sender }
    let targets_event = self.events.contains(event)
      || self.events.contains(&"*".to_owned());
    if let Some(ref porg) = payload.organization {
      if let Some(ref org) = self.organization {
        if porg.login != *org {
          return false
        }
      }
    }
    if let Some(ref prepo) = payload.repository {
      if let Some(ref repo) = self.repository {
        if prepo.name != *repo {
          return false
        }
      }
    }
    targets_event
  }

  /// return name if defined, otherwise cmd
  pub fn name(&self) -> String {
    self.name.clone().unwrap_or(self.cmd.clone())
  }

  /// start recv'ing events
  pub fn recv(&self, rx: Receiver<Event>) {
    loop {
      match rx.recv() {
        Ok(event) => {
          self.run(&event);
          ()
        },
        Err(e) => {
          error!("{}", Log::new(&"-".to_owned(), &"-".to_owned(), format!("Recv err: {}\n", e.to_string())));
          break
        }
      }
    }
  }

  fn log<S: Into<String>>(&self, event: &Event, msg: S) -> Log {
    Log::new(&self.name(), &event.delivery, msg)
  }

  /// run hook cmd, returning true if cmd succeeded, otherwise false
  pub fn run(&self, event: &Event) -> bool {

     match Command::new("/bin/sh")
       .arg("-c")
       .arg(&self.cmd)
       .env("GH_DELIVERY", &event.delivery)
       .env("GH_EVENT_NAME", &event.name)
       .env("GH_EVENT_PAYLOAD", &event.payload)
       .stdin(Stdio::null())
       .stdout(Stdio::piped())
       .stderr(Stdio::piped())
       .spawn() {
         Err(e) => {
           error!(
             "{}", &self.log(
               &event, format!("error executing {}: {}\n", self.cmd, e)
              )
           );
           false
         },
         Ok(mut child)  => {

           let lines = pine::lines(&mut child);
           for l in lines.iter() {
             info!("{}", self.log(&event, format!("{:?}", l)));
           }

           match child.wait() {
             Ok(s) => {
               if s.success() {
                 info!("{}", self.log(&event, "that worked"));
                 true
               } else {
                 match s.code() {
                   Some(c) => info!("{}", self.log(&event, format!("hook exited with status {}\n", c))),
                   _ => if let Some(s) = s.signal() {
                     error!("{}", self.log(&event, format!("process killed by signal {}\n", s)))
                   }
                 };
                 false
               }
             },
             Err(e) => {
               error!("{}", self.log(&event, format!("error getting exit status {}\n", e.to_string())));
               false
             }
           }
         }
       }
  }
}

#[cfg(test)]
mod tests {
  use super::Hook;
  use super::super::Event;

  #[test]
  fn test_hook_run_pass() {
    let hook = Hook {
      cmd: "true".to_owned(),
      ..Default::default()
    };
    assert!(hook.run(&Event {
      ..Default::default()
    }))
  }

  #[test]
  fn test_hook_run_fail() {
    let hook = Hook {
      cmd: "false".to_owned(),
      ..Default::default()
    };
    assert!(!hook.run(&Event {
      ..Default::default()
    }))
  }

  #[test]
  fn test_hook_run_panic() {
    let hook = Hook {
      cmd: "oiusdfasdf".to_owned(),
      ..Default::default()
    };
    assert!(!hook.run(&Event {
      ..Default::default()
    }))
  }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io::{Read, Seek, SeekFrom};
use std::fs::File;
use std::str;

extern crate byteorder;
use self::byteorder::LittleEndian;

use super::{ReadAt, WriteAt, Size, Cursor, SizeCursor, ByteIo, Slice, ReadIntAt};

#[test]
fn test_read_at() {
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    file.read_exact_at(10, buf.as_mut()).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!(s, "name");
}

#[test]
fn test_size() {
    let file = File::open("Cargo.toml").unwrap();
    let size = file.size().unwrap().unwrap();
    assert!(size > 0);
}

#[test]
fn test_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = Cursor::new_pos(file, 10);
    let mut buf = [0; 4];
    {
        curs.read_exact(&mut buf).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!("name", s);
    }
    curs.seek(SeekFrom::Current(4)).unwrap();
    curs.read_exact(&mut buf).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!("posi", s);
}

#[test]
fn test_size_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = SizeCursor::new_pos(file, 10);
    let mut buf = [0; 4];
    curs.seek(SeekFrom::End(-2)).unwrap();
    assert_eq!(2, curs.read(&mut buf).unwrap());
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert!(s.contains("\n"));
}

#[test]
fn test_byteio() {
    let file = File::open("Cargo.toml").unwrap();
    let io: ByteIo<_, LittleEndian> = ByteIo::new(file);
    let r = io.read_i32_at(3).unwrap();
    assert_eq!(0x67616b63, r);
}

#[test]
fn test_vector() {
    // Write past the end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [4, 5, 6, 7];
    (&mut v).write_all_at(2, &buf).unwrap();
    assert_eq!(vec![0, 1, 4, 5, 6, 7], v);
}

#[test]
fn test_slice() {
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        // Read too much, limited by size.
        let mut buf = [9; 4];
        let slice = Slice::new(&mut v, 2, Some(3));
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 1);
        assert_eq!(buf, [4, 9, 9, 9]);

        // Read too much, limited by buf
        let mut buf = [9; 2];
        let bytes = slice.read_at(1, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [3, 4]);
    }

    {
        // Read too much, limited by original vec.
        let slice = Slice::new(&mut v, 2, Some(5));
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    {
        // Read too much of unsized slice.
        let slice = Slice::new(&mut v, 2, None);
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    // Interleaved read/write to same slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice = Slice::new(&mut v, 2, Some(3));
        let mut buf = [9; 3];
        {
            let bytes = slice.write_at(2, &buf).unwrap();
            assert_eq!(bytes, 1);
        }
        {
            let bytes = slice.read_at(1, &mut buf).unwrap();
            assert_eq!(bytes, 2);
        }
        assert_eq!(buf, [3, 9, 9]);
        {
            let bytes = slice.write_at(0, &buf[..1]).unwrap();
            assert_eq!(bytes, 1);
        }
    }
    assert_eq!(v, vec![0, 1, 3, 3, 9, 5]);

    // Write past end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [9; 6];
    // Limited by size.
    {
        let mut slice = Slice::new(&mut v, 2, Some(5));
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 4);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9]);
    // No size.
    {
        let mut slice = Slice::new(&mut v, 2, None);
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 6);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9, 9, 9]);

    // Automatic-size constructor.
    let mut v = vec![0, 1, 2, 3];
    {
        let mut slice = Slice::new_to_end(&mut v, 1).unwrap();
        assert_eq!(slice.size().unwrap().unwrap(), 3);
        let bytes = slice.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 3);
    }
    assert_eq!(v, vec![0, 9, 9, 9]);

    // Slice of slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice1 = Slice::new(&mut v, 1, Some(4));
        let mut slice2 = Slice::new(&mut slice1, 1, Some(2));
        let bytes = slice2.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 2);
    }
    assert_eq!(v, vec![0, 1, 9, 9, 4, 5]);
}

#[test]
fn test_refcell() {
    let mut buf = [0; 3];

    // Make sure we can instantiate a bunch of combinations.
    let mut a = [0, 1, 2, 3];
    a.as_ref().read_at(0, &mut buf).unwrap();
    a.as_mut().write_at(0, &buf).unwrap();

    let mut v = vec![0, 1, 2, 3];
    v.read_at(0, &mut buf).unwrap();
    v.write_at(0, &buf).unwrap();

    let mut ra = &RefCell::new(a.as_mut());
    ra.read_at(0, &mut buf).unwrap();
    ra.write_at(0, &buf).unwrap();

    let mut rv = &RefCell::new(&mut v);
    rv.read_at(0, &mut buf).unwrap();
    rv.write_at(0, &buf).unwrap();

    // Test writing but still being able to use, thanks to RefCell.
    let mut v = vec![0, 1, 2, 3];
    let mut rv = &RefCell::new(&mut v);
    let buf = [9; 4];
    rv.write_at(0, &buf).unwrap();
    assert_eq!(*rv.borrow(), &vec![9; 4]);
}
<commit_msg>test interrupts<commit_after>use std::cell::{Cell, RefCell};
use std::io::{Read, Seek, SeekFrom, ErrorKind, Result, Error};
use std::fs::File;
use std::str;

extern crate byteorder;
use self::byteorder::LittleEndian;

use super::{ReadAt, WriteAt, Size, Cursor, SizeCursor, ByteIo, Slice, ReadIntAt};

#[test]
fn test_read_at() {
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    file.read_exact_at(10, buf.as_mut()).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!(s, "name");
}

// A ReadAt that has weird behavior.
struct ReadCustom<I: ReadAt, F: Fn() -> Result<usize>> {
    i: I,
    fail: Cell<bool>,
    onfail: F,
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadCustom<I, F> {
    fn new(i: I, f: F) -> Self {
        ReadCustom {
            i: i,
            fail: Cell::new(true),
            onfail: f,
        }
    }
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadAt for ReadCustom<I, F> {
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
        let fail = self.fail.get();
        self.fail.set(!fail);
        if fail {
            (self.onfail)()
        } else {
            self.i.read_at(pos, buf)
        }
    }
}

#[test]
fn test_read_fails() {
    let file = File::open("Cargo.toml").unwrap();
    let interrupt = ReadCustom::new(file,
                                    || Err(Error::new(ErrorKind::Interrupted, "interrupt!")));
    let mut buf = [0; 4];
    interrupt.read_exact_at(10, buf.as_mut()).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!(s, "name");
}

#[test]
fn test_size() {
    let file = File::open("Cargo.toml").unwrap();
    let size = file.size().unwrap().unwrap();
    assert!(size > 0);
}

#[test]
fn test_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = Cursor::new_pos(file, 10);
    let mut buf = [0; 4];
    {
        curs.read_exact(&mut buf).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!("name", s);
    }
    curs.seek(SeekFrom::Current(4)).unwrap();
    curs.read_exact(&mut buf).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!("posi", s);
}

#[test]
fn test_size_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = SizeCursor::new_pos(file, 10);
    let mut buf = [0; 4];
    curs.seek(SeekFrom::End(-2)).unwrap();
    assert_eq!(2, curs.read(&mut buf).unwrap());
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert!(s.contains("\n"));
}

#[test]
fn test_byteio() {
    let file = File::open("Cargo.toml").unwrap();
    let io: ByteIo<_, LittleEndian> = ByteIo::new(file);
    let r = io.read_i32_at(3).unwrap();
    assert_eq!(0x67616b63, r);
}

#[test]
fn test_vector() {
    // Write past the end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [4, 5, 6, 7];
    (&mut v).write_all_at(2, &buf).unwrap();
    assert_eq!(vec![0, 1, 4, 5, 6, 7], v);
}

#[test]
fn test_slice() {
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        // Read too much, limited by size.
        let mut buf = [9; 4];
        let slice = Slice::new(&mut v, 2, Some(3));
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 1);
        assert_eq!(buf, [4, 9, 9, 9]);

        // Read too much, limited by buf
        let mut buf = [9; 2];
        let bytes = slice.read_at(1, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [3, 4]);
    }

    {
        // Read too much, limited by original vec.
        let slice = Slice::new(&mut v, 2, Some(5));
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    {
        // Read too much of unsized slice.
        let slice = Slice::new(&mut v, 2, None);
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    // Interleaved read/write to same slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice = Slice::new(&mut v, 2, Some(3));
        let mut buf = [9; 3];
        {
            let bytes = slice.write_at(2, &buf).unwrap();
            assert_eq!(bytes, 1);
        }
        {
            let bytes = slice.read_at(1, &mut buf).unwrap();
            assert_eq!(bytes, 2);
        }
        assert_eq!(buf, [3, 9, 9]);
        {
            let bytes = slice.write_at(0, &buf[..1]).unwrap();
            assert_eq!(bytes, 1);
        }
    }
    assert_eq!(v, vec![0, 1, 3, 3, 9, 5]);

    // Write past end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [9; 6];
    // Limited by size.
    {
        let mut slice = Slice::new(&mut v, 2, Some(5));
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 4);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9]);
    // No size.
    {
        let mut slice = Slice::new(&mut v, 2, None);
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 6);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9, 9, 9]);

    // Automatic-size constructor.
    let mut v = vec![0, 1, 2, 3];
    {
        let mut slice = Slice::new_to_end(&mut v, 1).unwrap();
        assert_eq!(slice.size().unwrap().unwrap(), 3);
        let bytes = slice.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 3);
    }
    assert_eq!(v, vec![0, 9, 9, 9]);

    // Slice of slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice1 = Slice::new(&mut v, 1, Some(4));
        let mut slice2 = Slice::new(&mut slice1, 1, Some(2));
        let bytes = slice2.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 2);
    }
    assert_eq!(v, vec![0, 1, 9, 9, 4, 5]);
}

#[test]
fn test_refcell() {
    let mut buf = [0; 3];

    // Make sure we can instantiate a bunch of combinations.
    let mut a = [0, 1, 2, 3];
    a.as_ref().read_at(0, &mut buf).unwrap();
    a.as_mut().write_at(0, &buf).unwrap();

    let mut v = vec![0, 1, 2, 3];
    v.read_at(0, &mut buf).unwrap();
    v.write_at(0, &buf).unwrap();

    let mut ra = &RefCell::new(a.as_mut());
    ra.read_at(0, &mut buf).unwrap();
    ra.write_at(0, &buf).unwrap();

    let mut rv = &RefCell::new(&mut v);
    rv.read_at(0, &mut buf).unwrap();
    rv.write_at(0, &buf).unwrap();

    // Test writing but still being able to use, thanks to RefCell.
    let mut v = vec![0, 1, 2, 3];
    let mut rv = &RefCell::new(&mut v);
    let buf = [9; 4];
    rv.write_at(0, &buf).unwrap();
    assert_eq!(*rv.borrow(), &vec![9; 4]);
}
<|endoftext|>


<commit_before>use conduit::{Request, Response};
use conduit_middleware::Middleware;

use curl;
use curl::easy::{Easy, List};

use oauth2::*;

use serde_json;
use serde::Deserialize;

use std::str;
use std::error::Error;
use std::collections::HashMap;

use app::App;
use util::{CargoResult, internal, ChainError, human};
use Uploader;

/// Does all the nonsense for sending a GET to Github. Doesn't handle parsing
/// because custom error-code handling may be desirable. Use
/// `parse_github_response` to handle the "common" processing of responses.
pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec<u8>), curl::Error> {
    let url = format!("{}://api.github.com{}", app.config.api_protocol, url);
    info!("GITHUB HTTP: {}", url);

    let mut headers = List::new();
    headers
        .append("Accept: application/vnd.github.v3+json")
        .unwrap();
    headers.append("User-Agent: hello!").unwrap();
    headers
        .append(&format!("Authorization: token {}", auth.access_token))
        .unwrap();

    let mut handle = app.handle();
    handle.url(&url).unwrap();
    handle.get(true).unwrap();
    handle.http_headers(headers).unwrap();

    let mut data = Vec::new();
    {
        let mut transfer = handle.transfer();
        transfer
            .write_function(|buf| {
                data.extend_from_slice(buf);
                Ok(buf.len())
            })
            .unwrap();
        transfer.perform()?;
    }
    Ok((handle, data))
}

/// Checks for normal responses
pub fn parse_github_response<'de, 'a: 'de, T: Deserialize<'de>>(
    mut resp: Easy,
    data: &'a [u8],
) -> CargoResult<T> {
    match resp.response_code().unwrap() {
        200 => {} // Ok!
        403 => {
            return Err(human(
                "It looks like you don't have permission \
                 to query a necessary property from Github \
                 to complete this request. \
                 You may need to re-authenticate on \
                 crates.io to grant permission to read \
                 github org memberships. Just go to \
                 https://crates.io/login",
            ));
        }
        n => {
            let resp = String::from_utf8_lossy(data);
            return Err(internal(&format_args!(
                "didn't get a 200 result from \
                 github, got {} with: {}",
                n,
                resp
            )));
        }
    }

    let json = str::from_utf8(data).ok().chain_error(|| {
        internal("github didn't send a utf8-response")
    })?;

    serde_json::from_str(json).chain_error(|| internal("github didn't send a valid json response"))
}

/// Gets a token with the given string as the access token, but all
/// other info null'd out. Generally, just to be fed to the `github` fn.
pub fn token(token: String) -> Token {
    Token {
        access_token: token,
        scopes: Vec::new(),
        token_type: String::new(),
    }
}

#[derive(Clone, Debug)]
pub struct SecurityHeadersMiddleware {
    headers: HashMap<String, Vec<String>>,
}

impl SecurityHeadersMiddleware {
    pub fn new(uploader: &Uploader) -> Self {
        let mut headers = HashMap::new();

        headers.insert(
            "X-Content-Type-Options".into(),
            vec!["nosniff".into()],
        );

        headers.insert(
            "X-Frame-Options".into(),
            vec!["SAMEORIGIN".into()],
        );

        headers.insert(
            "X-XSS-Protection".into(),
            vec!["1; mode=block".into()],
        );

        let s3_host = match *uploader {
            Uploader::S3 { ref bucket, .. } => bucket.host(),
            _ => unreachable!("This middleware should only be used in the production environment, \
                               which should also require an S3 uploader, QED"),
        };

        // It would be better if we didn't have to have 'unsafe-eval' in the `script-src`
        // policy, but google charts (used for the download graph on crate pages) uses `eval`
        // to load scripts. Remove 'unsafe-eval' if google fixes the issue:
        // https://github.com/google/google-visualization-issues/issues/1356
        // or if we switch to a different graph generation library.
        headers.insert(
            "Content-Security-Policy".into(),
            vec![
                format!("default-src 'self'; \
                  connect-src 'self' https://docs.rs https://{}; \
                  script-src 'self' 'unsafe-eval' \
                             https://www.google-analytics.com https://www.google.com; \
                  style-src 'self' https://www.google.com https://ajax.googleapis.com; \
                  img-src *; \
                  object-src 'none'",
                  s3_host
                ),
            ],
        );

        SecurityHeadersMiddleware { headers }
    }
}

impl Middleware for SecurityHeadersMiddleware {
    fn after(
        &self,
        _: &mut Request,
        mut res: Result<Response, Box<Error + Send>>,
    ) -> Result<Response, Box<Error + Send>> {
        if let Ok(ref mut response) = res {
            response.headers.extend(self.headers.clone());
        }
        res
    }
}
<commit_msg>cargo fmt<commit_after>use conduit::{Request, Response};
use conduit_middleware::Middleware;

use curl;
use curl::easy::{Easy, List};

use oauth2::*;

use serde_json;
use serde::Deserialize;

use std::str;
use std::error::Error;
use std::collections::HashMap;

use app::App;
use util::{CargoResult, internal, ChainError, human};
use Uploader;

/// Does all the nonsense for sending a GET to Github. Doesn't handle parsing
/// because custom error-code handling may be desirable. Use
/// `parse_github_response` to handle the "common" processing of responses.
pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec<u8>), curl::Error> {
    let url = format!("{}://api.github.com{}", app.config.api_protocol, url);
    info!("GITHUB HTTP: {}", url);

    let mut headers = List::new();
    headers
        .append("Accept: application/vnd.github.v3+json")
        .unwrap();
    headers.append("User-Agent: hello!").unwrap();
    headers
        .append(&format!("Authorization: token {}", auth.access_token))
        .unwrap();

    let mut handle = app.handle();
    handle.url(&url).unwrap();
    handle.get(true).unwrap();
    handle.http_headers(headers).unwrap();

    let mut data = Vec::new();
    {
        let mut transfer = handle.transfer();
        transfer
            .write_function(|buf| {
                data.extend_from_slice(buf);
                Ok(buf.len())
            })
            .unwrap();
        transfer.perform()?;
    }
    Ok((handle, data))
}

/// Checks for normal responses
pub fn parse_github_response<'de, 'a: 'de, T: Deserialize<'de>>(
    mut resp: Easy,
    data: &'a [u8],
) -> CargoResult<T> {
    match resp.response_code().unwrap() {
        200 => {} // Ok!
        403 => {
            return Err(human(
                "It looks like you don't have permission \
                 to query a necessary property from Github \
                 to complete this request. \
                 You may need to re-authenticate on \
                 crates.io to grant permission to read \
                 github org memberships. Just go to \
                 https://crates.io/login",
            ));
        }
        n => {
            let resp = String::from_utf8_lossy(data);
            return Err(internal(&format_args!(
                "didn't get a 200 result from \
                 github, got {} with: {}",
                n,
                resp
            )));
        }
    }

    let json = str::from_utf8(data).ok().chain_error(|| {
        internal("github didn't send a utf8-response")
    })?;

    serde_json::from_str(json).chain_error(|| internal("github didn't send a valid json response"))
}

/// Gets a token with the given string as the access token, but all
/// other info null'd out. Generally, just to be fed to the `github` fn.
pub fn token(token: String) -> Token {
    Token {
        access_token: token,
        scopes: Vec::new(),
        token_type: String::new(),
    }
}

#[derive(Clone, Debug)]
pub struct SecurityHeadersMiddleware {
    headers: HashMap<String, Vec<String>>,
}

impl SecurityHeadersMiddleware {
    pub fn new(uploader: &Uploader) -> Self {
        let mut headers = HashMap::new();

        headers.insert("X-Content-Type-Options".into(), vec!["nosniff".into()]);

        headers.insert("X-Frame-Options".into(), vec!["SAMEORIGIN".into()]);

        headers.insert("X-XSS-Protection".into(), vec!["1; mode=block".into()]);

        let s3_host = match *uploader {
            Uploader::S3 { ref bucket, .. } => bucket.host(),
            _ => {
                unreachable!(
                    "This middleware should only be used in the production environment, \
                               which should also require an S3 uploader, QED"
                )
            }
        };

        // It would be better if we didn't have to have 'unsafe-eval' in the `script-src`
        // policy, but google charts (used for the download graph on crate pages) uses `eval`
        // to load scripts. Remove 'unsafe-eval' if google fixes the issue:
        // https://github.com/google/google-visualization-issues/issues/1356
        // or if we switch to a different graph generation library.
        headers.insert(
            "Content-Security-Policy".into(),
            vec![
                format!(
                    "default-src 'self'; \
                  connect-src 'self' https://docs.rs https://{}; \
                  script-src 'self' 'unsafe-eval' \
                             https://www.google-analytics.com https://www.google.com; \
                  style-src 'self' https://www.google.com https://ajax.googleapis.com; \
                  img-src *; \
                  object-src 'none'",
                    s3_host
                ),
            ],
        );

        SecurityHeadersMiddleware { headers }
    }
}

impl Middleware for SecurityHeadersMiddleware {
    fn after(
        &self,
        _: &mut Request,
        mut res: Result<Response, Box<Error + Send>>,
    ) -> Result<Response, Box<Error + Send>> {
        if let Ok(ref mut response) = res {
            response.headers.extend(self.headers.clone());
        }
        res
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
use reqwest::{Client, RedirectPolicy};
use std::time::Duration;
use url::{ParseError, Url};
use utils::data_to_dataurl;

lazy_static! {
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

pub fn is_data_url(url: &str) -> Result<bool, String> {
    match Url::parse(url) {
        Ok(parsed_url) => Ok(parsed_url.scheme() == "data"),
        Err(err) => Err(format!("{}", err)),
    }
}

pub fn is_valid_url(path: &str) -> bool {
    REGEX_URL.is_match(path)
}

pub fn resolve_url(from: &str, to: &str) -> Result<String, ParseError> {
    let result = if is_valid_url(to) {
        // (anything, http://site.com/css/main.css)
        to.to_string()
    } else {
        Url::parse(from)?.join(to)?.to_string()
    };

    Ok(result)
}

pub fn retrieve_asset(
    url: &str,
    as_dataurl: bool,
    as_mime: &str,
    opt_user_agent: &str,
) -> Result<String, reqwest::Error> {
    if is_data_url(&url).unwrap() {
        Ok(url.to_string())
    } else {
        let client = Client::builder()
            .redirect(RedirectPolicy::limited(3))
            .timeout(Duration::from_secs(10))
            .build()
            .unwrap();
        let mut response = client
            .get(url)
            .header(USER_AGENT, opt_user_agent)
            .send()
            .unwrap();

        if as_dataurl {
            // Convert response into a byte array
            let mut data: Vec<u8> = vec![];
            response.copy_to(&mut data)?;

            // Attempt to obtain MIME type by reading the Content-Type header
            let mimetype = if as_mime == "" {
                response
                    .headers()
                    .get(CONTENT_TYPE)
                    .and_then(|header| header.to_str().ok())
                    .unwrap_or(&as_mime)
            } else {
                as_mime
            };

            Ok(data_to_dataurl(&mimetype, &data))
        } else {
            Ok(response.text().unwrap())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_is_url() {
        assert!(is_valid_url("https://www.rust-lang.org/"));
        assert!(is_valid_url("http://kernel.org"));
        assert!(!is_valid_url("./index.html"));
        assert!(!is_valid_url("some-local-page.htm"));
        assert!(!is_valid_url("ftp://1.2.3.4/www/index.html"));
        assert!(!is_valid_url(
            "data:text/html;base64,V2VsY29tZSBUbyBUaGUgUGFydHksIDxiPlBhbDwvYj4h"
        ));
    }

    #[test]
    fn test_resolve_url() -> Result<(), ParseError> {
        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "../category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "saved_page.htm",
            "https://www.kernel.org/category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "//www.kernel.org/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "//another-host.org/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://another-host.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org/category/signatures.html",
            "/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.w3schools.com/html/html_iframe.asp",
            "default.asp",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.w3schools.com/html/default.asp"
        );

        Ok(())
    }

    #[test]
    fn test_is_data_url() {
        assert!(
            is_data_url("data:text/html;base64,V2VsY29tZSBUbyBUaGUgUGFydHksIDxiPlBhbDwvYj4h")
                .unwrap_or(false)
        );
        assert!(!is_data_url("https://kernel.org").unwrap_or(false));
        assert!(!is_data_url("//kernel.org").unwrap_or(false));
    }
}
<commit_msg>Fix name of a test function<commit_after>use regex::Regex;
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
use reqwest::{Client, RedirectPolicy};
use std::time::Duration;
use url::{ParseError, Url};
use utils::data_to_dataurl;

lazy_static! {
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

pub fn is_data_url(url: &str) -> Result<bool, String> {
    match Url::parse(url) {
        Ok(parsed_url) => Ok(parsed_url.scheme() == "data"),
        Err(err) => Err(format!("{}", err)),
    }
}

pub fn is_valid_url(path: &str) -> bool {
    REGEX_URL.is_match(path)
}

pub fn resolve_url(from: &str, to: &str) -> Result<String, ParseError> {
    let result = if is_valid_url(to) {
        // (anything, http://site.com/css/main.css)
        to.to_string()
    } else {
        Url::parse(from)?.join(to)?.to_string()
    };

    Ok(result)
}

pub fn retrieve_asset(
    url: &str,
    as_dataurl: bool,
    as_mime: &str,
    opt_user_agent: &str,
) -> Result<String, reqwest::Error> {
    if is_data_url(&url).unwrap() {
        Ok(url.to_string())
    } else {
        let client = Client::builder()
            .redirect(RedirectPolicy::limited(3))
            .timeout(Duration::from_secs(10))
            .build()
            .unwrap();
        let mut response = client
            .get(url)
            .header(USER_AGENT, opt_user_agent)
            .send()
            .unwrap();

        if as_dataurl {
            // Convert response into a byte array
            let mut data: Vec<u8> = vec![];
            response.copy_to(&mut data)?;

            // Attempt to obtain MIME type by reading the Content-Type header
            let mimetype = if as_mime == "" {
                response
                    .headers()
                    .get(CONTENT_TYPE)
                    .and_then(|header| header.to_str().ok())
                    .unwrap_or(&as_mime)
            } else {
                as_mime
            };

            Ok(data_to_dataurl(&mimetype, &data))
        } else {
            Ok(response.text().unwrap())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_is_valid_url() {
        assert!(is_valid_url("https://www.rust-lang.org/"));
        assert!(is_valid_url("http://kernel.org"));
        assert!(!is_valid_url("./index.html"));
        assert!(!is_valid_url("some-local-page.htm"));
        assert!(!is_valid_url("ftp://1.2.3.4/www/index.html"));
        assert!(!is_valid_url(
            "data:text/html;base64,V2VsY29tZSBUbyBUaGUgUGFydHksIDxiPlBhbDwvYj4h"
        ));
    }

    #[test]
    fn test_resolve_url() -> Result<(), ParseError> {
        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "../category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "saved_page.htm",
            "https://www.kernel.org/category/signatures.html",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/category/signatures.html"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "//www.kernel.org/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org",
            "//another-host.org/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://another-host.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.kernel.org/category/signatures.html",
            "/theme/images/logos/tux.png",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.kernel.org/theme/images/logos/tux.png"
        );

        let resolved_url = resolve_url(
            "https://www.w3schools.com/html/html_iframe.asp",
            "default.asp",
        )?;
        assert_eq!(
            resolved_url.as_str(),
            "https://www.w3schools.com/html/default.asp"
        );

        Ok(())
    }

    #[test]
    fn test_is_data_url() {
        assert!(
            is_data_url("data:text/html;base64,V2VsY29tZSBUbyBUaGUgUGFydHksIDxiPlBhbDwvYj4h")
                .unwrap_or(false)
        );
        assert!(!is_data_url("https://kernel.org").unwrap_or(false));
        assert!(!is_data_url("//kernel.org").unwrap_or(false));
    }
}
<|endoftext|>


<commit_before>use num::Float;

use std::f64::consts::PI;
use std::cmp::PartialEq;
use std::ops::{Add, Sub};

use flt;

macro_rules! make_hues {
    ($($(#[$doc:meta])+ struct $name:ident;)+) => ($(
        $(#[$doc])+
        ///
        ///The hue is a circular type, where `0` and `360` is the same, and
        ///it's normalized to `(-180, 180]` when it's converted to a linear
        ///number (like `f32`). This makes many calculations easier, but may
        ///also have some surprising effects if it's expected to act as a
        ///linear number.
        #[derive(Clone, Copy, Debug, Default)]
        pub struct $name<T:Float = f32>(T);

        impl<T:Float> $name<T> {
            ///Create a new hue from radians, instead of degrees.
            pub fn from_radians(radians: T) -> $name<T> {
                $name(radians * flt(180.0) / flt(PI))
            }

            ///Get the hue as degrees, in the range `(-180, 180]`.
            pub fn to_degrees(self) -> T {
                normalize_angle(self.0)
            }

            ///Convert the hue to radians, in the range `(-π, π]`.
            pub fn to_radians(self) -> T {
                normalize_angle(self.0) * flt(PI) / flt(180.0)
            }

            ///Convert the hue to positive degrees, in the range `[0, 360)`.
            pub fn to_positive_degrees(self) -> T {
                normalize_angle_positive(self.0)
            }

            ///Convert the hue to positive radians, in the range `[0, 2π)`.
            pub fn to_positive_radians(self) -> T {
                normalize_angle_positive(self.0) * flt(PI) / flt(180.0)
            }
        }

        impl<T:Float> From<T> for $name<T> {
            fn from(degrees: T) -> $name<T> {
                $name(degrees)
            }
        }

        impl Into<f64> for $name<f64> {
            fn into(self) -> f64 {
                normalize_angle(self.0)
            }
        }

        impl Into<f32> for $name<f32> {
            fn into(self) -> f32 {
                normalize_angle(self.0)
            }
        }
        impl Into<f32> for $name<f64> {
            fn into(self) -> f32 {
                normalize_angle(self.0) as f32
            }
        }

        impl<T:Float> PartialEq for $name<T> {
            fn eq(&self, other: &$name<T>) -> bool {
                let hue_s: T = (*self).to_degrees();
                let hue_o: T = (*other).to_degrees();
                hue_s.eq(&hue_o)
            }
        }

        impl<T:Float> PartialEq<T> for $name<T> {
            fn eq(&self, other: &T) -> bool {
                let hue: T = (*self).to_degrees();
                hue.eq(&normalize_angle(*other))
            }
        }

        impl<T:Float> Add<$name<T>> for $name<T> {
            type Output = $name<T>;

            fn add(self, other: $name<T>) -> $name<T> {
                $name(self.0 + other.0)
            }
        }

        impl<T:Float> Add<T> for $name<T> {
            type Output = $name<T>;

            fn add(self, other: T) -> $name<T> {
                $name(self.0 + other)
            }
        }

        impl<T:Float> Sub<$name<T>> for $name<T> {
            type Output = $name<T>;

            fn sub(self, other: $name<T>) -> $name<T> {
                $name(self.0 - other.0)
            }
        }

        impl<T:Float> Sub<T> for $name<T> {
            type Output = $name<T>;

            fn sub(self, other: T) -> $name<T> {
                $name(self.0 - other)
            }
        }
    )+)
}

make_hues! {
    ///A hue type for the CIE L*a*b* family of color spaces.
    ///
    ///It's measured in degrees and it's based on the four physiological
    ///elementary colors _red_, _yellow_, _green_ and _blue_. This makes it
    ///different from the hue of RGB based color spaces.
    struct LabHue;

    ///A hue type for the RGB family of color spaces.
    ///
    ///It's measured in degrees and uses the three additive primaries _red_,
    ///_green_ and _blue_.
    struct RgbHue;
}

fn normalize_angle<T: Float>(mut deg: T) -> T {
    let c180 = flt(180.0);
    let c360 = flt(360.0);
    while deg > c180 {
        deg = deg - c360;
    }

    while deg <= -c180 {
        deg = deg + c360;
    }

    deg
}

fn normalize_angle_positive<T: Float>(mut deg: T) -> T {
    let c360 = flt(360.0);
    while deg >= c360 {
        deg = deg - c360;
    }

    while deg < T::zero() {
        deg = deg + c360;
    }

    deg
}

#[cfg(test)]
mod test {
    use RgbHue;

    #[test]
    fn float_conversion() {
        for i in -180..180 {
            let hue = RgbHue::from(4.0 * i as f32);

            let degs = hue.to_degrees();
            assert!(degs > -180.0 && degs <= 180.0);

            let pos_degs = hue.to_positive_degrees();
            assert!(pos_degs >= 0.0 && pos_degs < 360.0);

            assert_eq!(RgbHue::from(degs), RgbHue::from(pos_degs));
        }
    }
}
<commit_msg>change normalize to use floor and ceil formula instead of while loop<commit_after>use num::Float;

use std::f64::consts::PI;
use std::cmp::PartialEq;
use std::ops::{Add, Sub};

use flt;

macro_rules! make_hues {
    ($($(#[$doc:meta])+ struct $name:ident;)+) => ($(
        $(#[$doc])+
        ///
        ///The hue is a circular type, where `0` and `360` is the same, and
        ///it's normalized to `(-180, 180]` when it's converted to a linear
        ///number (like `f32`). This makes many calculations easier, but may
        ///also have some surprising effects if it's expected to act as a
        ///linear number.
        #[derive(Clone, Copy, Debug, Default)]
        pub struct $name<T:Float = f32>(T);

        impl<T:Float> $name<T> {
            ///Create a new hue from radians, instead of degrees.
            pub fn from_radians(radians: T) -> $name<T> {
                $name(radians * flt(180.0) / flt(PI))
            }

            ///Get the hue as degrees, in the range `(-180, 180]`.
            pub fn to_degrees(self) -> T {
                normalize_angle(self.0)
            }

            ///Convert the hue to radians, in the range `(-π, π]`.
            pub fn to_radians(self) -> T {
                normalize_angle(self.0) * flt(PI) / flt(180.0)
            }

            ///Convert the hue to positive degrees, in the range `[0, 360)`.
            pub fn to_positive_degrees(self) -> T {
                normalize_angle_positive(self.0)
            }

            ///Convert the hue to positive radians, in the range `[0, 2π)`.
            pub fn to_positive_radians(self) -> T {
                normalize_angle_positive(self.0) * flt(PI) / flt(180.0)
            }
        }

        impl<T:Float> From<T> for $name<T> {
            fn from(degrees: T) -> $name<T> {
                $name(degrees)
            }
        }

        impl Into<f64> for $name<f64> {
            fn into(self) -> f64 {
                normalize_angle(self.0)
            }
        }

        impl Into<f32> for $name<f32> {
            fn into(self) -> f32 {
                normalize_angle(self.0)
            }
        }
        impl Into<f32> for $name<f64> {
            fn into(self) -> f32 {
                normalize_angle(self.0) as f32
            }
        }

        impl<T:Float> PartialEq for $name<T> {
            fn eq(&self, other: &$name<T>) -> bool {
                let hue_s: T = (*self).to_degrees();
                let hue_o: T = (*other).to_degrees();
                hue_s.eq(&hue_o)
            }
        }

        impl<T:Float> PartialEq<T> for $name<T> {
            fn eq(&self, other: &T) -> bool {
                let hue: T = (*self).to_degrees();
                hue.eq(&normalize_angle(*other))
            }
        }

        impl<T:Float> Add<$name<T>> for $name<T> {
            type Output = $name<T>;

            fn add(self, other: $name<T>) -> $name<T> {
                $name(self.0 + other.0)
            }
        }

        impl<T:Float> Add<T> for $name<T> {
            type Output = $name<T>;

            fn add(self, other: T) -> $name<T> {
                $name(self.0 + other)
            }
        }

        impl<T:Float> Sub<$name<T>> for $name<T> {
            type Output = $name<T>;

            fn sub(self, other: $name<T>) -> $name<T> {
                $name(self.0 - other.0)
            }
        }

        impl<T:Float> Sub<T> for $name<T> {
            type Output = $name<T>;

            fn sub(self, other: T) -> $name<T> {
                $name(self.0 - other)
            }
        }
    )+)
}

make_hues! {
    ///A hue type for the CIE L*a*b* family of color spaces.
    ///
    ///It's measured in degrees and it's based on the four physiological
    ///elementary colors _red_, _yellow_, _green_ and _blue_. This makes it
    ///different from the hue of RGB based color spaces.
    struct LabHue;

    ///A hue type for the RGB family of color spaces.
    ///
    ///It's measured in degrees and uses the three additive primaries _red_,
    ///_green_ and _blue_.
    struct RgbHue;
}

fn normalize_angle<T: Float>(deg: T) -> T {
    let c360 = flt(360.0);
    let c180 = flt(180.0);
    deg - ( ((deg + c180) / c360) - T::one() ).ceil() * c360
}

fn normalize_angle_positive<T: Float>(deg: T) -> T {
    let c360 = flt(360.0);
    deg - ((deg / c360).floor() * c360)
}

#[cfg(test)]
mod test {
    use RgbHue;
    use super::{normalize_angle, normalize_angle_positive};

    #[test]
    fn normalize_angle_0_360() {
        let inp = [-1000.0_f32, -900.0 , -360.5, -360.0, -359.5, -240.0 , -180.5, -180.0, -179.5,
            -90.0, -0.5, 0.0, 0.5, 90.0, 179.5, 180.0, 180.5, 240.0, 359.5, 360.0, 360.5,
             900.0, 1000.0 ];

        let expected = [80.0_f32, 180.0, 359.5, 0.0, 0.5, 120.0, 179.5, 180.0, 180.5, 270.0,
            359.5, 0.0, 0.5, 90.0, 179.5, 180.0, 180.5, 240.0, 359.5, 0.0, 0.5, 180.0, 280.0];

        let result: Vec<f32> = inp.iter().map(|x| normalize_angle_positive(*x) ).collect();
        for (res, exp) in result.iter().zip(expected.iter()) {
            assert_eq!(res, exp);
        }
    }

    #[test]
    fn normalize_angle_180_180() {
        let inp = [-1000.0_f32, -900.0 , -360.5, -360.0, -359.5, -240.0 , -180.5, -180.0, -179.5,
            -90.0, -0.5, 0.0, 0.5, 90.0, 179.5, 180.0, 180.5, 240.0, 359.5, 360.0, 360.5,
             900.0, 1000.0 ];

        let expected = [80.0, 180.0, -0.5, 0.0, 0.5, 120.0, 179.5, 180.0, -179.5, -90.0, -0.5,
            0.0, 0.5, 90.0, 179.5, 180.0, -179.5, -120.0, -0.5, 0.0, 0.5, 180.0, -80.0];

        let result: Vec<f32> = inp.iter().map(|x| normalize_angle(*x) ).collect();
        for (res, exp) in result.iter().zip(expected.iter()) {
            assert_eq!(res, exp);
        }
    }

    #[test]
    fn float_conversion() {
        for i in -180..180 {
            let hue = RgbHue::from(4.0 * i as f32);

            let degs = hue.to_degrees();
            assert!(degs > -180.0 && degs <= 180.0);

            let pos_degs = hue.to_positive_degrees();
            assert!(pos_degs >= 0.0 && pos_degs < 360.0);

            assert_eq!(RgbHue::from(degs), RgbHue::from(pos_degs));
        }
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
 * __ears__ initialization (optional).
 *
 * This module provide a unique function to initialize __ears__.
 * Use this function in the case of you don't use __ears__ for the first time
 * in you program in the main task. This prevent that the context was created
 * and destroyed in a another task.
 */

use record_context::RecordContext;
use internal::OpenAlData;

/**
 * Initialize the internal context
 *
 * # Return
 * true if initialization is made with success, false otherwise
 *
 * # Example
 * ```no_run
 * match ears::init() {
 *     true  => {
 *         // do stuff
 *     },
 *     false => panic!("ears init error")
 * }
 * ```
 */
pub fn init() -> bool {
    match OpenAlData::check_al_context() {
        Ok(_)    => true,
        Err(err) => { println!("{}", err); false }
    }
}

/**
 * Initialize the input device context
 *
 * # Return
 * true if initialization is made with success, false otherwise
 *
 * # Example
 * ```no_run
 * match ears::init_in() {
 *     Some(rc) => {
 *         // do stuff
 *     },
 *     None     => panic!("ears init input error")
 * }
 * ```
 */
pub fn init_in() -> Option<RecordContext> {
    match OpenAlData::check_al_input_context() {
        Ok(ctxt) => Some(ctxt),
        Err(err) => { println!("{}", err); None }
    }
}

#[cfg(test)]
mod test {
    #![allow(non_snake_case)]

    use init;
    use init_in;
	use std::thread;

    #[test]
    #[ignore]
    fn test_init_ears_OK() -> () {
        assert_eq!(init(), true)
    }

    #[test]
    #[ignore]
    fn test_init_in_with_normal_init_OK() -> () {
        init();
        assert!(init_in().is_some())
    }

    #[test]
    #[ignore]
    fn test_init_in_alone_OK() -> () {
        assert!(init_in().is_some())
    }

    #[test]
    #[ignore]
    fn test_init_in_in_another_task_OK() -> () {
        init();
        thread::spawn(move || {
            assert_eq!(init_in(), None)
        });
    }
}
<commit_msg>Change functions in init.rs to return a `Result`<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
 * __ears__ initialization (optional).
 *
 * This module provide a unique function to initialize __ears__.
 * Use this function in the case of you don't use __ears__ for the first time
 * in you program in the main task. This prevent that the context was created
 * and destroyed in a another task.
 */

use record_context::RecordContext;
use internal::OpenAlData;

/**
 * Initialize the internal context
 *
 * # Return
 * `Ok(())` if initialization is successful, `Err(String)` otherwise
 *
 * # Example
 * ```no_run
 * ears::init().unwrap()
 * ```
 */
pub fn init() -> Result<(), String> {
    return OpenAlData::check_al_context()
}

/**
 * Initialize the input device context
 *
 * # Return
 * `Ok(RecordContext)` if initialization is successful, `Err(String)` otherwise
 *
 * # Example
 * ```no_run
 * ears::init_in().unwrap();
 * ```
 */
pub fn init_in() -> Result<RecordContext, String> {
    return OpenAlData::check_al_input_context()
}

#[cfg(test)]
mod test {
    #![allow(non_snake_case)]

    use init;
    use init_in;
	use std::thread;

    #[test]
    #[ignore]
    fn test_init_ears_OK() -> () {
        assert!(init().is_ok())
    }

    #[test]
    #[ignore]
    fn test_init_in_with_normal_init_OK() -> () {
        init();
        assert!(init_in().is_ok())
    }

    #[test]
    #[ignore]
    fn test_init_in_alone_OK() -> () {
        assert!(init_in().is_ok())
    }

    #[test]
    #[ignore]
    fn test_init_in_in_another_task_OK() -> () {
        init();
        thread::spawn(move || {
            assert!(init_in().is_err())
        });
    }
}
<|endoftext|>


<commit_before>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
#[cfg(feature = "ssl")]
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    #[cfg(feature = "ssl")]
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            #[cfg(feature = "ssl")]
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    #[cfg(feature = "ssl")]
    pub fn https<A: ToSocketAddrs>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                   -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs>(mut self, addr: A, threads: usize,
                                         protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");

        self.addr = Some(sock_addr);

        self.protocol = Some(protocol.clone());

        match protocol {
            Protocol::Http => try!(Server::http(sock_addr)).handle_threads(self, threads),

            #[cfg(feature = "ssl")]
            Protocol::Https { ref certificate, ref key } => {
                use hyper::net::Openssl;

                try!(Server::https(sock_addr,
                                   try!(Openssl::with_cert_and_key(certificate, key))))
                    .handle_threads(self, threads)
            }
        }
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        // Consume and flush the response.
        // We would like this to work, but can't do anything if it doesn't.
        if let Ok(res) = http_res.start()
        {
            let _ = res.end();
        }
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, http_res: HttpResponse<Fresh>) {
        // Create `Request` wrapper.
        match Request::from_http(http_req, self.addr.clone().unwrap(),
                                 self.protocol.as_ref().unwrap()) {
            Ok(mut req) => {
                // Dispatch the request, write the response back to http_res
                self.handler.handle(&mut req).unwrap_or_else(|e| {
                    error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                    e.response
                }).write_back(http_res)
            },
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                self.bad_request(http_res)
            }
        }
    }
}
<commit_msg>(fix) Return 500 server error in case of panic<commit_after>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
#[cfg(feature = "ssl")]
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    #[cfg(feature = "ssl")]
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            #[cfg(feature = "ssl")]
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    #[cfg(feature = "ssl")]
    pub fn https<A: ToSocketAddrs>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                   -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs>(mut self, addr: A, threads: usize,
                                         protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");

        self.addr = Some(sock_addr);

        self.protocol = Some(protocol.clone());

        match protocol {
            Protocol::Http => try!(Server::http(sock_addr)).handle_threads(self, threads),

            #[cfg(feature = "ssl")]
            Protocol::Https { ref certificate, ref key } => {
                use hyper::net::Openssl;

                try!(Server::https(sock_addr,
                                   try!(Openssl::with_cert_and_key(certificate, key))))
                    .handle_threads(self, threads)
            }
        }
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        // Consume and flush the response.
        // We would like this to work, but can't do anything if it doesn't.
        if let Ok(res) = http_res.start()
        {
            let _ = res.end();
        }
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, mut http_res: HttpResponse<Fresh>) {
        // Set some defaults in case request handler panics.
        // This should not be necessary anymore once stdlib's catch_panic becomes stable.
        *http_res.status_mut() = status::InternalServerError;

        // Create `Request` wrapper.
        match Request::from_http(http_req, self.addr.clone().unwrap(),
                                 self.protocol.as_ref().unwrap()) {
            Ok(mut req) => {
                // Dispatch the request, write the response back to http_res
                self.handler.handle(&mut req).unwrap_or_else(|e| {
                    error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                    e.response
                }).write_back(http_res)
            },
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                self.bad_request(http_res)
            }
        }
    }
}
<|endoftext|>


<commit_before>
extern crate serde;
extern crate serde_json;

use flowgger::Encoder;
use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use self::serde_json::builder::ObjectBuilder;
use self::serde_json::value::Value;

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

impl Encoder for GelfEncoder {
    fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => extra.as_table().expect("output.gelf_extra must be a list of key/value pairs").
                into_iter().map(|(k, v)| (k.to_owned(), v.as_str().
                expect("output.gelf_extra values must be strings").to_owned())).collect()
        };
        GelfEncoder { extra: extra }
    }

    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new().
            insert("version".to_owned(), Value::String("1.1".to_owned())).
            insert("host".to_owned(), Value::String(record.hostname)).
            insert("short_message".to_owned(), Value::String(record.msg.unwrap_or("-".to_owned()))).
            insert("timestamp".to_owned(), Value::I64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(severity as u64));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null
                };
                map = map.insert(name, value);
            }
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        let json = serde_json::to_vec(&map.unwrap());
        Ok(json)
    }
}
<commit_msg>gelf encoder: insert extra properties first<commit_after>
extern crate serde;
extern crate serde_json;

use flowgger::Encoder;
use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use self::serde_json::builder::ObjectBuilder;
use self::serde_json::value::Value;

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

impl Encoder for GelfEncoder {
    fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => extra.as_table().expect("output.gelf_extra must be a list of key/value pairs").
                into_iter().map(|(k, v)| (k.to_owned(), v.as_str().
                expect("output.gelf_extra values must be strings").to_owned())).collect()
        };
        GelfEncoder { extra: extra }
    }

    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new().
            insert("version".to_owned(), Value::String("1.1".to_owned())).
            insert("host".to_owned(), Value::String(record.hostname)).
            insert("short_message".to_owned(), Value::String(record.msg.unwrap_or("-".to_owned()))).
            insert("timestamp".to_owned(), Value::I64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(severity as u64));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null
                };
                map = map.insert(name, value);
            }
        }
        let json = serde_json::to_vec(&map.unwrap());
        Ok(json)
    }
}
<|endoftext|>


<commit_before>//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```
//! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !
//! # { loop {} }
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
//! The reason for this is that libcore is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. The actual symbol is declared through the `#[panic_handler]` attribute.

#![allow(dead_code, missing_docs)]
#![unstable(
    feature = "core_panic",
    reason = "internal details of the implementation of the `panic!` and related macros",
    issue = "none"
)]

use crate::fmt;
use crate::panic::{Location, PanicInfo};

/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
#[cold]
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
pub fn panic(expr: &'static str) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}

#[inline]
#[track_caller]
#[lang = "panic_str"] // needed for const-evaluated panics
pub fn panic_str(expr: &str) -> ! {
    panic_fmt(format_args!("{}", expr));
}

#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
fn panic_bounds_check(index: usize, len: usize) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    panic!("index out of bounds: the len is {} but the index is {}", len, index)
}

/// The underlying implementation of libcore's `panic!` macro when formatting is used.
#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
    // that gets resolved to the `#[panic_handler]` function.
    extern "Rust" {
        #[lang = "panic_impl"]
        fn panic_impl(pi: &PanicInfo<'_>) -> !;
    }

    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());

    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
    unsafe { panic_impl(&pi) }
}

#[derive(Debug)]
pub enum AssertKind {
    Eq,
    Ne,
}

/// Internal function for `assert_eq!` and `assert_ne!` macros
#[cold]
#[track_caller]
pub fn assert_failed<T, U>(
    kind: AssertKind,
    left: &T,
    right: &U,
    args: Option<fmt::Arguments<'_>>,
) -> !
where
    T: fmt::Debug + ?Sized,
    U: fmt::Debug + ?Sized,
{
    #[track_caller]
    fn inner(
        kind: AssertKind,
        left: &dyn fmt::Debug,
        right: &dyn fmt::Debug,
        args: Option<fmt::Arguments<'_>>,
    ) -> ! {
        let op = match kind {
            AssertKind::Eq => "==",
            AssertKind::Ne => "!=",
        };

        match args {
            Some(args) => panic!(
                r#"assertion failed: `(left {} right)`
  left: `{:?}`,
 right: `{:?}: {}`"#,
                op, left, right, args
            ),
            None => panic!(
                r#"assertion failed: `(left {} right)`
  left: `{:?}`,
 right: `{:?}`"#,
                op, left, right,
            ),
        }
    }
    inner(kind, &left, &right, args)
}
<commit_msg>Hide internals items in documentation<commit_after>//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```
//! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !
//! # { loop {} }
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
//! The reason for this is that libcore is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. The actual symbol is declared through the `#[panic_handler]` attribute.

#![allow(dead_code, missing_docs)]
#![unstable(
    feature = "core_panic",
    reason = "internal details of the implementation of the `panic!` and related macros",
    issue = "none"
)]

use crate::fmt;
use crate::panic::{Location, PanicInfo};

/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
#[cold]
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
pub fn panic(expr: &'static str) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}

#[inline]
#[track_caller]
#[lang = "panic_str"] // needed for const-evaluated panics
pub fn panic_str(expr: &str) -> ! {
    panic_fmt(format_args!("{}", expr));
}

#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
fn panic_bounds_check(index: usize, len: usize) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    panic!("index out of bounds: the len is {} but the index is {}", len, index)
}

/// The underlying implementation of libcore's `panic!` macro when formatting is used.
#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
    if cfg!(feature = "panic_immediate_abort") {
        super::intrinsics::abort()
    }

    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
    // that gets resolved to the `#[panic_handler]` function.
    extern "Rust" {
        #[lang = "panic_impl"]
        fn panic_impl(pi: &PanicInfo<'_>) -> !;
    }

    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());

    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
    unsafe { panic_impl(&pi) }
}

#[derive(Debug)]
#[doc(hidden)]
pub enum AssertKind {
    Eq,
    Ne,
}

/// Internal function for `assert_eq!` and `assert_ne!` macros
#[cold]
#[track_caller]
#[doc(hidden)]
pub fn assert_failed<T, U>(
    kind: AssertKind,
    left: &T,
    right: &U,
    args: Option<fmt::Arguments<'_>>,
) -> !
where
    T: fmt::Debug + ?Sized,
    U: fmt::Debug + ?Sized,
{
    #[track_caller]
    fn inner(
        kind: AssertKind,
        left: &dyn fmt::Debug,
        right: &dyn fmt::Debug,
        args: Option<fmt::Arguments<'_>>,
    ) -> ! {
        let op = match kind {
            AssertKind::Eq => "==",
            AssertKind::Ne => "!=",
        };

        match args {
            Some(args) => panic!(
                r#"assertion failed: `(left {} right)`
  left: `{:?}`,
 right: `{:?}: {}`"#,
                op, left, right, args
            ),
            None => panic!(
                r#"assertion failed: `(left {} right)`
  left: `{:?}`,
 right: `{:?}`"#,
                op, left, right,
            ),
        }
    }
    inner(kind, &left, &right, args)
}
<|endoftext|>


<commit_before>//! Defines utf8 error type.

use crate::fmt;

/// Errors which can occur when attempting to interpret a sequence of [`u8`]
/// as a string.
///
/// As such, the `from_utf8` family of functions and methods for both [`String`]s
/// and [`&str`]s make use of this error, for example.
///
/// [`String`]: ../../std/string/struct.String.html#method.from_utf8
/// [`&str`]: super::from_utf8
///
/// # Examples
///
/// This error type’s methods can be used to create functionality
/// similar to `String::from_utf8_lossy` without allocating heap memory:
///
/// ```
/// fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) {
///     loop {
///         match std::str::from_utf8(input) {
///             Ok(valid) => {
///                 push(valid);
///                 break
///             }
///             Err(error) => {
///                 let (valid, after_valid) = input.split_at(error.valid_up_to());
///                 unsafe {
///                     push(std::str::from_utf8_unchecked(valid))
///                 }
///                 push("\u{FFFD}");
///
///                 if let Some(invalid_sequence_length) = error.error_len() {
///                     input = &after_valid[invalid_sequence_length..]
///                 } else {
///                     break
///                 }
///             }
///         }
///     }
/// }
/// ```
#[derive(Copy, Eq, PartialEq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Utf8Error {
    pub(super) valid_up_to: usize,
    pub(super) error_len: Option<u8>,
}

impl Utf8Error {
    /// Returns the index in the given string up to which valid UTF-8 was
    /// verified.
    ///
    /// It is the maximum index such that `from_utf8(&input[..index])`
    /// would return `Ok(_)`.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use std::str;
    ///
    /// // some invalid bytes, in a vector
    /// let sparkle_heart = vec![0, 159, 146, 150];
    ///
    /// // std::str::from_utf8 returns a Utf8Error
    /// let error = str::from_utf8(&sparkle_heart).unwrap_err();
    ///
    /// // the second byte is invalid here
    /// assert_eq!(1, error.valid_up_to());
    /// ```
    #[stable(feature = "utf8_error", since = "1.5.0")]
    pub fn valid_up_to(&self) -> usize {
        self.valid_up_to
    }

    /// Provides more information about the failure:
    ///
    /// * `None`: the end of the input was reached unexpectedly.
    ///   `self.valid_up_to()` is 1 to 3 bytes from the end of the input.
    ///   If a byte stream (such as a file or a network socket) is being decoded incrementally,
    ///   this could be a valid `char` whose UTF-8 byte sequence is spanning multiple chunks.
    ///
    /// * `Some(len)`: an unexpected byte was encountered.
    ///   The length provided is that of the invalid byte sequence
    ///   that starts at the index given by `valid_up_to()`.
    ///   Decoding should resume after that sequence
    ///   (after inserting a [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]) in case of
    ///   lossy decoding.
    ///
    /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
    #[stable(feature = "utf8_error_error_len", since = "1.20.0")]
    pub fn error_len(&self) -> Option<usize> {
        self.error_len.map(|len| len as usize)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(error_len) = self.error_len {
            write!(
                f,
                "invalid utf-8 sequence of {} bytes from index {}",
                error_len, self.valid_up_to
            )
        } else {
            write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
        }
    }
}

/// An error returned when parsing a `bool` using [`from_str`] fails
///
/// [`from_str`]: super::FromStr::from_str
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseBoolError {
    pub(super) _priv: (),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseBoolError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "provided string was not `true` or `false`".fmt(f)
    }
}
<commit_msg>Add #[inline] to the Utf8Error accessors.<commit_after>//! Defines utf8 error type.

use crate::fmt;

/// Errors which can occur when attempting to interpret a sequence of [`u8`]
/// as a string.
///
/// As such, the `from_utf8` family of functions and methods for both [`String`]s
/// and [`&str`]s make use of this error, for example.
///
/// [`String`]: ../../std/string/struct.String.html#method.from_utf8
/// [`&str`]: super::from_utf8
///
/// # Examples
///
/// This error type’s methods can be used to create functionality
/// similar to `String::from_utf8_lossy` without allocating heap memory:
///
/// ```
/// fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) {
///     loop {
///         match std::str::from_utf8(input) {
///             Ok(valid) => {
///                 push(valid);
///                 break
///             }
///             Err(error) => {
///                 let (valid, after_valid) = input.split_at(error.valid_up_to());
///                 unsafe {
///                     push(std::str::from_utf8_unchecked(valid))
///                 }
///                 push("\u{FFFD}");
///
///                 if let Some(invalid_sequence_length) = error.error_len() {
///                     input = &after_valid[invalid_sequence_length..]
///                 } else {
///                     break
///                 }
///             }
///         }
///     }
/// }
/// ```
#[derive(Copy, Eq, PartialEq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Utf8Error {
    pub(super) valid_up_to: usize,
    pub(super) error_len: Option<u8>,
}

impl Utf8Error {
    /// Returns the index in the given string up to which valid UTF-8 was
    /// verified.
    ///
    /// It is the maximum index such that `from_utf8(&input[..index])`
    /// would return `Ok(_)`.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use std::str;
    ///
    /// // some invalid bytes, in a vector
    /// let sparkle_heart = vec![0, 159, 146, 150];
    ///
    /// // std::str::from_utf8 returns a Utf8Error
    /// let error = str::from_utf8(&sparkle_heart).unwrap_err();
    ///
    /// // the second byte is invalid here
    /// assert_eq!(1, error.valid_up_to());
    /// ```
    #[stable(feature = "utf8_error", since = "1.5.0")]
    #[inline]
    pub fn valid_up_to(&self) -> usize {
        self.valid_up_to
    }

    /// Provides more information about the failure:
    ///
    /// * `None`: the end of the input was reached unexpectedly.
    ///   `self.valid_up_to()` is 1 to 3 bytes from the end of the input.
    ///   If a byte stream (such as a file or a network socket) is being decoded incrementally,
    ///   this could be a valid `char` whose UTF-8 byte sequence is spanning multiple chunks.
    ///
    /// * `Some(len)`: an unexpected byte was encountered.
    ///   The length provided is that of the invalid byte sequence
    ///   that starts at the index given by `valid_up_to()`.
    ///   Decoding should resume after that sequence
    ///   (after inserting a [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]) in case of
    ///   lossy decoding.
    ///
    /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
    #[stable(feature = "utf8_error_error_len", since = "1.20.0")]
    #[inline]
    pub fn error_len(&self) -> Option<usize> {
        self.error_len.map(|len| len as usize)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(error_len) = self.error_len {
            write!(
                f,
                "invalid utf-8 sequence of {} bytes from index {}",
                error_len, self.valid_up_to
            )
        } else {
            write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
        }
    }
}

/// An error returned when parsing a `bool` using [`from_str`] fails
///
/// [`from_str`]: super::FromStr::from_str
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseBoolError {
    pub(super) _priv: (),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseBoolError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "provided string was not `true` or `false`".fmt(f)
    }
}
<|endoftext|>


<commit_before>use super::BaseNum;

/// A two-dimensional dimension.
pub struct Dimension2<T> {
    pub width: T,
    pub height: T,
}

pub type Dimension2f = Dimension2<super::DefaultFloat>;
pub type Dimension2i = Dimension2<super::DefaultInt>;
pub type Dimension2u = Dimension2<super::DefaultUnsigned>;

impl<T: BaseNum> Dimension2<T> {
    pub fn new(width: T, height: T) -> Self {
        Dimension2 {
            width: width,
            height: height,
        }
    }

    // TODO: area()
    // TODO: scale(scalar)
    // TODO: aspect_ratio()
    // TODO: fitting(other: Dimension2)
    // TODO: filling(other: Dimension2)
}
<commit_msg>start working on dimension.rs<commit_after>use super::{BaseNum, PartialOrd};
use std::ops::{Div, Mul};

/// A two-dimensional dimension.
pub struct Dimension2<T> {
    pub width: T,
    pub height: T,
}

pub type Dimension2f = Dimension2<super::DefaultFloat>;
pub type Dimension2i = Dimension2<super::DefaultInt>;
pub type Dimension2u = Dimension2<super::DefaultUnsigned>;

impl<T: BaseNum> Dimension2<T> {
    pub fn new(width: T, height: T) -> Self {
        Dimension2 {
            width: width,
            height: height,
        }
    }

    pub fn area(&self) -> <T as Mul>::Output {
        self.width * self.height
    }
    pub fn scale(&self, scale: T) -> Dimension2<T> {
        Dimension2 {
            width: self.width * scale,
            height: self.height * scale,
        }
    }
    pub fn aspect_ratio(&self) -> <T as Div>::Output {
        //     assert!(self.height != 0);
        self.width / self.height
    }
    pub fn fitting(&self, other: Dimension2<T>) -> Dimension2<T> {
        let scale = PartialOrd::partial_min(other.width / self.width, other.height / self.height);
        self.scale(scale)

    }
    pub fn filling(&self, other: Dimension2<T>) -> Dimension<T>
}
<|endoftext|>