<commit_before>pub use self::os::{mqd_t};
pub use self::os::{mq_attr};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn mq_close(mqdes: mqd_t) -> ::int_t {
    extern { fn mq_close(mqdes: mqd_t) -> ::int_t; }
    unsafe { mq_close(mqdes) }
}

pub fn mq_getattr(mqdes: mqd_t, mqstat: &mut mq_attr) -> ::int_t {
    extern { fn mq_getattr(mqdes: mqd_t, mqstat: *mut mq_attr) -> ::int_t; }
    unsafe { mq_getattr(mqdes, mqstat as *mut _) }
}

pub fn mq_notify(mqdes: mqd_t, notification: &::signal::sigevent) -> ::int_t {
    extern { fn mq_notify(mqdes: mqd_t,
                          notification: *const ::signal::sigevent) -> ::int_t; }
    unsafe { mq_notify(mqdes, notification as *const _) }
}

pub fn mq_receive(mqdes: mqd_t, buf: &mut [u8],
                  msg_prio: Option<&mut ::uint_t>) -> ::ssize_t {
    extern { fn mq_receive(mqdes: mqd_t, msg_ptr: *mut ::char_t, msg_len: ::size_t,
                           msg_prio: *mut ::uint_t) -> ::ssize_t; }
    let ptr = msg_prio.map(|v| v as *mut _).unwrap_or(0 as *mut ::uint_t);
    unsafe { mq_receive(mqdes, buf.as_mut_ptr() as *mut _, buf.len() as ::size_t, ptr) }
}

pub fn mq_send(mqdes: mqd_t, buf: &[u8], prio: ::uint_t) -> ::int_t {
    extern { fn mq_send(mqdes: mqd_t, msg_ptr: *const ::char_t, msg_len: ::size_t,
                        msg_prio: ::uint_t) -> ::int_t; }
    unsafe { mq_send(mqdes, buf.as_ptr() as *const _, buf.len() as ::size_t, prio) }
}

pub fn mq_setattr(mqdes: mqd_t, newattr: &mq_attr,
                  oldattr: Option<&mut mq_attr>) -> ::int_t {
    extern { fn mq_setattr(mqdes: mqd_t, mqstat: *const mq_attr,
                           omqstat: *mut mq_attr) -> ::int_t; }
    let ptr = oldattr.map(|v| v as *mut _).unwrap_or(0 as *mut _);
    unsafe { mq_setattr(mqdes, newattr as *const _, ptr) }
}

pub fn mq_timedreceive(mqdes: mqd_t, buf: &mut [u8], prio: Option<&mut ::uint_t>,
                       timeout: &::time::timespec) -> ::ssize_t {
    extern {
        fn mq_timedreceive(mqdes: mqd_t, msg_ptr: *mut ::char_t,
                           msg_len: ::size_t, msg_prio: *mut ::uint_t,
                           abs_timeout: *const ::time::timespec) -> ::ssize_t;
    }
    let ptr = prio.map(|v| v as *mut _).unwrap_or(0 as *mut ::uint_t);
    unsafe { mq_timedreceive(mqdes, buf.as_mut_ptr() as *mut _, buf.len() as ::size_t,
                             ptr, timeout as *const _) }
}

pub fn mq_timedsend(mqdes: mqd_t, buf: &[u8], prio: ::uint_t,
                    timeout: &::time::timespec) -> ::int_t {
    extern { fn mq_timedsend(mqdes: mqd_t, msg_ptr: *const ::char_t,
                             msg_len: ::size_t, msg_prio: ::uint_t,
                             abs_timeout: *const ::time::timespec) -> ::int_t; }
    unsafe { mq_timedsend(mqdes, buf.as_ptr() as *const _, buf.len() as ::size_t,
                          prio, timeout as *const _) }
}

pub fn mq_unlink<T: ::NTStr>(name: &T) -> ::int_t {
    extern { fn mq_unlink(name: *const ::char_t) -> ::int_t; }
    unsafe { mq_unlink(name.as_ptr()) }
}

pub fn mq_open<T: ::NTStr>(name: &T, oflag: ::int_t, mode: Option<::sys::types::mode_t>,
                           attr: Option<&mut mq_attr>) -> mqd_t {
    extern { fn mq_open(name: *const ::char_t, oflag: ::int_t, ...) -> mqd_t; }
    match mode {
        Some(m) => {
            let ptr = attr.map(|v| v as *mut mq_attr).unwrap_or(0 as *mut _);
            unsafe { mq_open(name.as_ptr(), oflag, m, ptr) }
        },
        _ => unsafe { mq_open(name.as_ptr(), oflag) },
    }
}
<commit_msg>mqueue.h<commit_after>pub use self::os::{mqd_t};
pub use self::os::{mq_attr};

use {NTStr, int_t, uint_t, char_t, size_t, ssize_t};
use signal::{sigevent};
use time::{timespec};
use sys::types::{mode_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn mq_close(mqdes: mqd_t) -> int_t {
    extern { fn mq_close(mqdes: mqd_t) -> int_t; }
    unsafe { mq_close(mqdes) }
}

pub fn mq_getattr(mqdes: mqd_t, mqstat: &mut mq_attr) -> int_t {
    extern { fn mq_getattr(mqdes: mqd_t, mqstat: *mut mq_attr) -> int_t; }
    unsafe { mq_getattr(mqdes, mqstat as *mut _) }
}

pub fn mq_notify(mqdes: mqd_t, notification: &sigevent) -> int_t {
    extern { fn mq_notify(mqdes: mqd_t,
                          notification: *const sigevent) -> int_t; }
    unsafe { mq_notify(mqdes, notification as *const _) }
}

pub fn mq_receive(mqdes: mqd_t, buf: &mut [u8],
                  msg_prio: Option<&mut uint_t>) -> ssize_t {
    extern { fn mq_receive(mqdes: mqd_t, msg_ptr: *mut char_t, msg_len: size_t,
                           msg_prio: *mut uint_t) -> ssize_t; }
    let ptr = msg_prio.map(|v| v as *mut _).unwrap_or(0 as *mut uint_t);
    unsafe { mq_receive(mqdes, buf.as_mut_ptr() as *mut _, buf.len() as size_t, ptr) }
}

pub fn mq_send(mqdes: mqd_t, buf: &[u8], prio: uint_t) -> int_t {
    extern { fn mq_send(mqdes: mqd_t, msg_ptr: *const char_t, msg_len: size_t,
                        msg_prio: uint_t) -> int_t; }
    unsafe { mq_send(mqdes, buf.as_ptr() as *const _, buf.len() as size_t, prio) }
}

pub fn mq_setattr(mqdes: mqd_t, newattr: &mq_attr,
                  oldattr: Option<&mut mq_attr>) -> int_t {
    extern { fn mq_setattr(mqdes: mqd_t, mqstat: *const mq_attr,
                           omqstat: *mut mq_attr) -> int_t; }
    let ptr = oldattr.map(|v| v as *mut _).unwrap_or(0 as *mut _);
    unsafe { mq_setattr(mqdes, newattr as *const _, ptr) }
}

pub fn mq_timedreceive(mqdes: mqd_t, buf: &mut [u8], prio: Option<&mut uint_t>,
                       timeout: &timespec) -> ssize_t {
    extern {
        fn mq_timedreceive(mqdes: mqd_t, msg_ptr: *mut char_t,
                           msg_len: size_t, msg_prio: *mut uint_t,
                           abs_timeout: *const timespec) -> ssize_t;
    }
    let ptr = prio.map(|v| v as *mut _).unwrap_or(0 as *mut uint_t);
    unsafe { mq_timedreceive(mqdes, buf.as_mut_ptr() as *mut _, buf.len() as size_t,
                             ptr, timeout as *const _) }
}

pub fn mq_timedsend(mqdes: mqd_t, buf: &[u8], prio: uint_t,
                    timeout: &timespec) -> int_t {
    extern { fn mq_timedsend(mqdes: mqd_t, msg_ptr: *const char_t,
                             msg_len: size_t, msg_prio: uint_t,
                             abs_timeout: *const timespec) -> int_t; }
    unsafe { mq_timedsend(mqdes, buf.as_ptr() as *const _, buf.len() as size_t,
                          prio, timeout as *const _) }
}

pub fn mq_unlink<T: NTStr>(name: &T) -> int_t {
    extern { fn mq_unlink(name: *const char_t) -> int_t; }
    unsafe { mq_unlink(name.as_ptr()) }
}

pub fn mq_open<T: NTStr>(name: &T, oflag: int_t, mode: Option<mode_t>,
                         attr: Option<&mut mq_attr>) -> mqd_t {
    extern { fn mq_open(name: *const char_t, oflag: int_t, ...) -> mqd_t; }
    match mode {
        Some(m) => {
            let ptr = attr.map(|v| v as *mut mq_attr).unwrap_or(0 as *mut _);
            unsafe { mq_open(name.as_ptr(), oflag, m, ptr) }
        },
        _ => unsafe { mq_open(name.as_ptr(), oflag) },
    }
}
<|endoftext|>


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

use rustc_serialize::json::Json;

use super::Sprite;
use super::error::{LoadModelError, ModelError};

/// This struct simplifies the implementation of `parse`
#[derive(Clone, Debug)]
struct SpriteDataDefaults {
  pub sprite: String,
  pub frame: u64,
  pub cut_from: (u16, u16),
  pub cut_offset: (i8, i8),
  pub size: (u16, u16),
  pub pin_to: (i32, i32),
  pub pin_offset: (i8, i8),
}

impl SpriteDataDefaults {
  pub fn new() -> SpriteDataDefaults {
    SpriteDataDefaults {
      sprite: "default".to_string(),
      frame: 0,
      cut_from: (0, 0),
      cut_offset: (0, 0),
      size: (1, 1),
      pin_to: (0, 0),
      pin_offset: (0, 0),
    }
  }
}

/// Process sprite data.
pub fn parse(data: &Vec<Json>)
                          -> Result<BTreeMap<String, Sprite>, LoadModelError> {

  let mut ret = BTreeMap::new();
  try!(parse_2(data, &SpriteDataDefaults::new(), &mut ret));
  Ok(ret)
}

/// Just the recursive version of `parse`.
///
/// This fills in `ret` with the processed data. It returns Ok(()) on success.
fn parse_2(data: &Vec<Json>,
           defaults: &SpriteDataDefaults,
           ret: &mut BTreeMap<String, Sprite> ) -> Result<(), LoadModelError> {

  for obj in data {
    match obj {
      &Json::Object(ref with_obj) => {
        if with_obj.contains_key("with") {
          if with_obj.len() > 1 {
            return try!(Err(ModelError::MultiKeyWith));
          }
          try!(process_with(with_obj, defaults, ret));
        }
      },
      _ => return try!(Err(
                   ModelError::TypeError { obj: "\"sprite_data\" list element",
                                           expected: "object" }))
    }
  }
  unimplemented!();
}

fn process_with(with_obj: &BTreeMap<String, Json>,
                defaults: &SpriteDataDefaults,
                ret: &mut BTreeMap<String, Sprite> )
                                                -> Result<(), LoadModelError> {

  let new_defaults = defaults.clone();
  for (key, val) in with_obj.iter() {
    match key as &str {
      "defaults" => {},
      "data" => {},
      other => try!(Err(ModelError::InvalidKey { key: other.to_string(),
                                                 context: "\"with\" object" }))
    };
  };
  Ok(())
}
<commit_msg>Add sprite_data key list<commit_after>use std::collections::BTreeMap;

use rustc_serialize::json::Json;

use super::Sprite;
use super::error::{LoadModelError, ModelError};

/// The `sprite_data` keys
const KEYS: &'static [&'static str] = &[
  "cut_from",
  "cut_offset",
  "file",
  "frame",
  "pin_offset",
  "pin_to",
  "size",
  "sprite",
];

/// This struct simplifies the implementation of `parse`
#[derive(Clone, Debug)]
struct SpriteDataDefaults {
  pub sprite: String,
  pub frame: u64,
  pub cut_from: (u16, u16),
  pub cut_offset: (i8, i8),
  pub size: (u16, u16),
  pub pin_to: (i32, i32),
  pub pin_offset: (i8, i8),
}

impl SpriteDataDefaults {
  pub fn new() -> SpriteDataDefaults {
    SpriteDataDefaults {
      sprite: "default".to_string(),
      frame: 0,
      cut_from: (0, 0),
      cut_offset: (0, 0),
      size: (1, 1),
      pin_to: (0, 0),
      pin_offset: (0, 0),
    }
  }
}

/// Process sprite data.
pub fn parse(data: &Vec<Json>)
                          -> Result<BTreeMap<String, Sprite>, LoadModelError> {

  let mut ret = BTreeMap::new();
  try!(parse_2(data, &SpriteDataDefaults::new(), &mut ret));
  Ok(ret)
}

/// Just the recursive version of `parse`.
///
/// This fills in `ret` with the processed data. It returns Ok(()) on success.
fn parse_2(data: &Vec<Json>,
           defaults: &SpriteDataDefaults,
           ret: &mut BTreeMap<String, Sprite> ) -> Result<(), LoadModelError> {

  for obj in data {
    match obj {
      &Json::Object(ref with_obj) => {
        if with_obj.contains_key("with") {
          if with_obj.len() > 1 {
            return try!(Err(ModelError::MultiKeyWith));
          }
          try!(process_with(with_obj, defaults, ret));
        }
      },
      _ => return try!(Err(
                   ModelError::TypeError { obj: "\"sprite_data\" list element",
                                           expected: "object" }))
    }
  }
  unimplemented!();
}

fn process_with(with_obj: &BTreeMap<String, Json>,
                defaults: &SpriteDataDefaults,
                ret: &mut BTreeMap<String, Sprite> )
                                                -> Result<(), LoadModelError> {

  let new_defaults = defaults.clone();
  for (key, val) in with_obj.iter() {
    match key as &str {
      "defaults" => {},
      "data" => {},
      other => try!(Err(ModelError::InvalidKey { key: other.to_string(),
                                                 context: "\"with\" object" }))
    };
  };
  Ok(())
}
<|endoftext|>


<commit_before>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

#[cfg(test)]
mod test {
    use testing::flt_eq;

    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(1, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(2, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(3, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(4, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(5, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(6, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(7, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(8, &input, &mut output); assert!(output[0] == -1.0);
    }

    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(flt_eq(output[0], -0.8));
        osc.tick(1, &input, &mut output); assert!(flt_eq(output[0], -0.6));
        osc.tick(2, &input, &mut output); assert!(flt_eq(output[0], -0.4));
        osc.tick(3, &input, &mut output); assert!(flt_eq(output[0], -0.2));
        osc.tick(4, &input, &mut output); assert!(flt_eq(output[0], 0.0));
        osc.tick(5, &input, &mut output); assert!(flt_eq(output[0], 0.2));
        osc.tick(6, &input, &mut output); assert!(flt_eq(output[0], 0.4));
        osc.tick(7, &input, &mut output); assert!(flt_eq(output[0], 0.6));
        osc.tick(8, &input, &mut output); assert!(flt_eq(output[0], 0.8));
    }
}
<commit_msg>Improve oscillator test ergonomics.<commit_after>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

#[cfg(test)]
mod test {
    use testing::flt_eq;
    use super::{Aliased, Oscillator, Waveform};
    use types::{AudioDevice, Sample, Time};

    const FREQ: f32 = 4410.0;
    fn get_one_cycle(osc: &mut Oscillator) -> [Sample; 10] {
        let mut output = [0.0; 10];
        for t in 0..10 {
            osc.tick(t as Time, &[], &mut output[t..t+1]);
        }
        output
    }

    fn check(actual: &[Sample], expected: &[Sample]) {
        println!("actual:\n    {:?}", actual);
        println!("expected:\n    {:?}", expected);
        assert_eq!(actual.len(), expected.len());
        for (a, e) in actual.iter().zip(expected) {
            assert!(flt_eq(*a, *e));
        }
    }

    #[test]
    fn test_naive_square() {
        let mut osc = Oscillator::new(Waveform::Square(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0]);
    }

    #[test]
    fn test_naive_saw() {
        let mut osc = Oscillator::new(Waveform::Saw(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, -1.0]);
    }

    #[test]
    fn test_pulse() {
        let mut osc = Oscillator::new(Waveform::PulseTrain).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
    }
}
<|endoftext|>


<commit_before>use serialize::RawSerialize;
use deserialize::RawDeserialize;
use std::io::{ Read, Write };
use std::slice;
use std::mem;
use std::io::Error;

const SIZE_OF_U128: usize = 16;
const SIZE_OF_I128: usize = 16;
const SIZE_OF_U64: usize = 8;
const SIZE_OF_U32: usize = 4;
const SIZE_OF_U16: usize = 2;
const SIZE_OF_U8:  usize = 1;
const SIZE_OF_I64: usize = 8;
const SIZE_OF_I32: usize = 4;
const SIZE_OF_I16: usize = 2;
const SIZE_OF_I8:  usize = 1;

/// Serializing usize should be avoided if you want your data to be portable.
impl RawSerialize for bool {
    #[inline(always)]
    fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
        if *self {
            1u8.raw_serialize(to)
        } else {
            0u8.raw_serialize(to)
        }
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawDeserialize for usize {
    #[inline(always)]
    fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
        let x;
        check!(u8::raw_deserialize(from), x);
        Ok(x == 1)
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawSerialize for usize {
    #[inline(always)]
    fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
        let x = [*self];
        let y = unsafe { slice::from_raw_parts((&x).as_ptr() as *const u8, 8) };
        if let Err(e) = to.write_all(y) {
            Err(e)
        } else {
            Ok(mem::size_of::<usize>() as u64)
        }
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawDeserialize for usize {
    #[inline(always)]
    fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
        let mut buffer = [0u8; 8];
        match from.read_exact(&mut buffer) {
            Ok(_) => Ok(unsafe { mem::transmute::<[u8; 8], u64>(buffer) as usize } ),
            Err(e) => Err(e)
        }
    }
}

/// Generates code to serialize primitives, uses a bit of unsafe code to (hopefully)
/// speed things up.
macro_rules! serialize_primitive {
    ( $prim:ty, $size:expr ) => (
        impl RawSerialize for $prim {
            #[inline(always)]
            fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
                let x = [*self];
                let y = unsafe { slice::from_raw_parts((&x).as_ptr() as *const u8, $size) };
                if let Err(e) = to.write_all(y) {
                    Err(e)
                } else {
                    Ok($size as u64)
                }
            }
            fn raw_serialize_slice(x: &[Self], to: &mut Write) -> Result<u64, Error> {
                let len = x.len() as u64;
                match len.raw_serialize(to) {
                    Err(e) => return Err(e),
                    Ok(_) => ()
                };
                let y = unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, $size * (len as usize)) };
                if let Err(e) = to.write_all(y) {
                    Err(e)
                } else {
                    Ok($size as u64 * len + 8)
                }
            }
        }
        impl RawDeserialize for $prim {
            #[inline(always)]
            fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
                let mut buffer = [0u8; $size];

                match from.read_exact(&mut buffer) {
                    Ok(_) => Ok( unsafe { mem::transmute::<[u8; $size], $prim>(buffer) } ),
                    Err(e) => Err(e)
                }
            }
            fn raw_deserialize_vec(from: &mut Read) -> Result<Vec<Self>, Error> {
                let size: u64;
                match u64::raw_deserialize(from) {
                    Ok(x) => {
                        size = x;
                    },
                    Err(e) => return Err(e)
                };
                let mut dat = vec![0u8; size as usize * $size];
                check!(from.read_exact(&mut dat));
                unsafe {
                    Ok(Vec::<$prim>::from_raw_parts(Box::into_raw(dat.into_boxed_slice()) as *mut $prim, size as usize, size as usize))
                }
            }
        }

        impl<'b> RawSerialize for &'b [$prim] {
            fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
                let len = self.len() as u64;
                match len.raw_serialize(to) {
                    Err(e) => return Err(e),
                    Ok(_) => {}
                };
                let y = unsafe { slice::from_raw_parts((*self).as_ptr() as *const u8, $size * self.len()) };
                if let Err(e) = to.write_all(&y) {
                    Err(e)
                } else {
                    Ok($size as u64 * len + 8)
                }
            }
        }
    )
}

serialize_primitive!(i8,  SIZE_OF_I8);
serialize_primitive!(u64, SIZE_OF_U64);
serialize_primitive!(u8,  SIZE_OF_U8);

serialize_primitive!(i16, SIZE_OF_I16);
serialize_primitive!(i32, SIZE_OF_I32);
serialize_primitive!(i64, SIZE_OF_I64);
serialize_primitive!(u16, SIZE_OF_U16);
serialize_primitive!(u32, SIZE_OF_U32);

serialize_primitive!(f32, SIZE_OF_U32);
serialize_primitive!(f64, SIZE_OF_U64);

serialize_primitive!(i128, SIZE_OF_I128);
serialize_primitive!(u128, SIZE_OF_U128);

impl RawSerialize for String {
    fn raw_serialize(&self, from: &mut Write) -> Result<u64, Error> {
        self.as_bytes().raw_serialize(from)
    }
}

impl RawDeserialize for String {
    fn raw_deserialize(to: &mut Read) -> Result<Self, Error> {
        match u8::raw_deserialize_vec(to) {
            Ok(ret) => {
                Ok(String::from_utf8_lossy(&ret).into_owned())
            },
            Err(e) => Err(e)
        }
    }
}
<commit_msg>Fixed support for bool serialization<commit_after>use serialize::RawSerialize;
use deserialize::RawDeserialize;
use std::io::{ Read, Write };
use std::slice;
use std::mem;
use std::io::Error;

const SIZE_OF_U128: usize = 16;
const SIZE_OF_I128: usize = 16;
const SIZE_OF_U64: usize = 8;
const SIZE_OF_U32: usize = 4;
const SIZE_OF_U16: usize = 2;
const SIZE_OF_U8:  usize = 1;
const SIZE_OF_I64: usize = 8;
const SIZE_OF_I32: usize = 4;
const SIZE_OF_I16: usize = 2;
const SIZE_OF_I8:  usize = 1;

/// Serializing usize should be avoided if you want your data to be portable.
impl RawSerialize for bool {
    #[inline(always)]
    fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
        if *self {
            1u8.raw_serialize(to)
        } else {
            0u8.raw_serialize(to)
        }
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawDeserialize for bool {
    #[inline(always)]
    fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
        let x;
        check!(u8::raw_deserialize(from), x);
        Ok(x == 1)
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawSerialize for usize {
    #[inline(always)]
    fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
        let x = [*self];
        let y = unsafe { slice::from_raw_parts((&x).as_ptr() as *const u8, 8) };
        if let Err(e) = to.write_all(y) {
            Err(e)
        } else {
            Ok(mem::size_of::<usize>() as u64)
        }
    }
}

/// Serializing usize should be avoided if you want your data to be portable.
impl RawDeserialize for usize {
    #[inline(always)]
    fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
        let mut buffer = [0u8; 8];
        match from.read_exact(&mut buffer) {
            Ok(_) => Ok(unsafe { mem::transmute::<[u8; 8], u64>(buffer) as usize } ),
            Err(e) => Err(e)
        }
    }
}

/// Generates code to serialize primitives, uses a bit of unsafe code to (hopefully)
/// speed things up.
macro_rules! serialize_primitive {
    ( $prim:ty, $size:expr ) => (
        impl RawSerialize for $prim {
            #[inline(always)]
            fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
                let x = [*self];
                let y = unsafe { slice::from_raw_parts((&x).as_ptr() as *const u8, $size) };
                if let Err(e) = to.write_all(y) {
                    Err(e)
                } else {
                    Ok($size as u64)
                }
            }
            fn raw_serialize_slice(x: &[Self], to: &mut Write) -> Result<u64, Error> {
                let len = x.len() as u64;
                match len.raw_serialize(to) {
                    Err(e) => return Err(e),
                    Ok(_) => ()
                };
                let y = unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, $size * (len as usize)) };
                if let Err(e) = to.write_all(y) {
                    Err(e)
                } else {
                    Ok($size as u64 * len + 8)
                }
            }
        }
        impl RawDeserialize for $prim {
            #[inline(always)]
            fn raw_deserialize(from: &mut Read) -> Result<Self, Error> {
                let mut buffer = [0u8; $size];

                match from.read_exact(&mut buffer) {
                    Ok(_) => Ok( unsafe { mem::transmute::<[u8; $size], $prim>(buffer) } ),
                    Err(e) => Err(e)
                }
            }
            fn raw_deserialize_vec(from: &mut Read) -> Result<Vec<Self>, Error> {
                let size: u64;
                match u64::raw_deserialize(from) {
                    Ok(x) => {
                        size = x;
                    },
                    Err(e) => return Err(e)
                };
                let mut dat = vec![0u8; size as usize * $size];
                check!(from.read_exact(&mut dat));
                unsafe {
                    Ok(Vec::<$prim>::from_raw_parts(Box::into_raw(dat.into_boxed_slice()) as *mut $prim, size as usize, size as usize))
                }
            }
        }

        impl<'b> RawSerialize for &'b [$prim] {
            fn raw_serialize(&self, to: &mut Write) -> Result<u64, Error> {
                let len = self.len() as u64;
                match len.raw_serialize(to) {
                    Err(e) => return Err(e),
                    Ok(_) => {}
                };
                let y = unsafe { slice::from_raw_parts((*self).as_ptr() as *const u8, $size * self.len()) };
                if let Err(e) = to.write_all(&y) {
                    Err(e)
                } else {
                    Ok($size as u64 * len + 8)
                }
            }
        }
    )
}

serialize_primitive!(i8,  SIZE_OF_I8);
serialize_primitive!(u64, SIZE_OF_U64);
serialize_primitive!(u8,  SIZE_OF_U8);

serialize_primitive!(i16, SIZE_OF_I16);
serialize_primitive!(i32, SIZE_OF_I32);
serialize_primitive!(i64, SIZE_OF_I64);
serialize_primitive!(u16, SIZE_OF_U16);
serialize_primitive!(u32, SIZE_OF_U32);

serialize_primitive!(f32, SIZE_OF_U32);
serialize_primitive!(f64, SIZE_OF_U64);

serialize_primitive!(i128, SIZE_OF_I128);
serialize_primitive!(u128, SIZE_OF_U128);

impl RawSerialize for String {
    fn raw_serialize(&self, from: &mut Write) -> Result<u64, Error> {
        self.as_bytes().raw_serialize(from)
    }
}

impl RawDeserialize for String {
    fn raw_deserialize(to: &mut Read) -> Result<Self, Error> {
        match u8::raw_deserialize_vec(to) {
            Ok(ret) => {
                Ok(String::from_utf8_lossy(&ret).into_owned())
            },
            Err(e) => Err(e)
        }
    }
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr, ToSocketAddrs};
use std::iter::Iterator;
use std::io::Result as IoResult;
use std::sync::Arc;
use mioco;
use mioco::tcp::TcpListener;
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

macro_rules! try_com {
    ($com: expr, err => $errexpr: expr) => {
        match $com {
            ConnResult::Ok(x) => x,
            ConnResult::ZeroPacket => return Ok(()),
            ConnResult::ParseErr(_) => $errexpr,
            ConnResult::IoError(_) => $errexpr,
        }
    }
}

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();

        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        self.serve_custom(|&mut _, &mut _| {}, |&mut _| {})
    }

    pub fn serve_custom<RQ, RS>(&self, on_request: RQ, on_response: RS) -> IoResult<()>
        where RQ: Fn(&mut Request, &mut Option<Response>) + 'static + Send + Sync,
              RS: Fn(&mut Response) + 'static + Send + Sync
    {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        let handlers = Arc::new((on_request, on_response));
        mioco::start(move || -> IoResult<()> {
            for _ in 0..mioco::thread_num() {
                let listener: TcpListener = try!(listener.try_clone());
                let _handlers = handlers.clone();

                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let mut src_conn = Connection::new(try!(listener.accept()));
                        let __handlers = _handlers.clone();

                        mioco::spawn(move || -> IoResult<()> {
                            // recieve source request
                            let mut request: Request = try_com!(src_conn.recieve(), err=>return
                            Ok(()));
                            debug!("receive from client.");

                            // connect to the server
                            let mut dest_conn = match Connection::from(&request.host()
                                                                               .as_str(),
                                                                       &request.port()) {
                                Some(conn) => conn,
                                None => return Ok(()),
                            };
                            debug!("connect to server.");

                            let mut user_res = None;
                            __handlers.0(&mut request, &mut user_res);

                            // send request to destination host
                            try_com!(dest_conn.send(&request), err=>return Ok(()));

                            debug!("send to server.");

                            // recieve destination response
                            let mut response: Response = match user_res {
                                Some(r) => r,
                                None => try_com!(dest_conn.recieve(), err=>return Ok(())),
                            };

                            debug!("recieved from server.");

                            __handlers.1(&mut response);

                            // send response to source host
                            try_com!(src_conn.send(&response), err=>return Ok(()));

                            debug!("send to client");

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}
<commit_msg>change request handler's signature.<commit_after>use std::net::{SocketAddr, ToSocketAddrs};
use std::iter::Iterator;
use std::io::Result as IoResult;
use std::sync::Arc;
use mioco;
use mioco::tcp::TcpListener;
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

macro_rules! try_com {
    ($com: expr, err => $errexpr: expr) => {
        match $com {
            ConnResult::Ok(x) => x,
            ConnResult::ZeroPacket => return Ok(()),
            ConnResult::ParseErr(_) => $errexpr,
            ConnResult::IoError(_) => $errexpr,
        }
    }
}

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();

        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        self.serve_custom(|_| None, |_| {})
    }

    pub fn serve_custom<RQ, RS>(&self, on_request: RQ, on_response: RS) -> IoResult<()>
        where RQ: Fn(&mut Request) -> Option<Response> + 'static + Send + Sync,
              RS: Fn(&mut Response) + 'static + Send + Sync
    {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        let handlers = Arc::new((on_request, on_response));
        mioco::start(move || -> IoResult<()> {
            for _ in 0..mioco::thread_num() {
                let listener: TcpListener = try!(listener.try_clone());
                let _handlers = handlers.clone();

                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let mut src_conn = Connection::new(try!(listener.accept()));
                        let __handlers = _handlers.clone();

                        mioco::spawn(move || -> IoResult<()> {
                            // recieve source request
                            let mut request: Request = try_com!(src_conn.recieve(), err=>return
                            Ok(()));
                            debug!("receive from client.");

                            // connect to the server
                            let mut dest_conn = match Connection::from(&request.host()
                                                                               .as_str(),
                                                                       &request.port()) {
                                Some(conn) => conn,
                                None => return Ok(()),
                            };
                            debug!("connect to server.");

                            let mut user_res = __handlers.0(&mut request);

                            // send request to destination host
                            try_com!(dest_conn.send(&request), err=>return Ok(()));

                            debug!("send to server.");

                            // recieve destination response
                            let mut response: Response = match user_res {
                                Some(r) => r,
                                None => try_com!(dest_conn.recieve(), err=>return Ok(())),
                            };

                            debug!("recieved from server.");

                            __handlers.1(&mut response);

                            // send response to source host
                            try_com!(src_conn.send(&response), err=>return Ok(()));

                            debug!("send to client");

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder};
use std::io;

const HEADER_LENGTH: usize = 2;
const MAX_DATAGRAM_LENGTH: usize = 1 << 16;
const MAX_BLOCK_LENGTH: usize = HEADER_LENGTH + MAX_DATAGRAM_LENGTH;

const TAG: &'static str = "DatagramBuffer";

/// Circular buffer to store datagrams (preserving their boundaries).
///
/// ```text
///     circularBufferLength
/// |<------------------------->| extra space for storing the last datagram in one block
/// +---------------------------+------+
/// |                           |      |
/// |[D4]     [  D1  ][ D2 ][  D3  ]   |
/// +---------------------------+------+
///     ^     ^
///  head     tail
/// ```
pub struct DatagramBuffer {
    buf: Box<[u8]>,
    head: usize,
    tail: usize,
    circular_buffer_length: usize,
}

impl DatagramBuffer {
    pub fn new(capacity: usize) -> Self {
        Self {
            buf: vec![0; capacity + MAX_BLOCK_LENGTH].into_boxed_slice(),
            head: 0,
            tail: 0,
            circular_buffer_length: capacity + 1,
        }
    }

    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    pub fn has_enough_space_for(&self, datagram_length: usize) -> bool {
        if self.head >= self.tail {
            // there is at least the extra space for storing 1 packet
            return true;
        }
        let remaining = self.tail - self.head + 1;
        HEADER_LENGTH + datagram_length < remaining
    }

    pub fn write_to<W: io::Write>(&mut self, destination: &mut W) -> io::Result<()> {
        let length = self.read_length() as usize;
        let source_slice = &self.buf[self.tail..self.tail + length];
        self.tail += length;
        if self.tail >= self.circular_buffer_length {
            self.tail = 0;
        }
        let w = destination.write(source_slice)?;
        if w != length {
            error!(target: TAG, "Cannot write the whole datagram to the buffer (only {}/{})", w, length);
            return Err(io::Error::new(io::ErrorKind::Other, "Cannot write the whole datagram"))
        }
        Ok(())
    }

    pub fn read_from(&mut self, source: &[u8]) -> io::Result<()> {
        let length = source.len();
        assert!(length <= MAX_DATAGRAM_LENGTH, "Datagram length may not be greater than {} bytes", MAX_DATAGRAM_LENGTH);
        if !self.has_enough_space_for(length) {
            return Err(io::Error::new(io::ErrorKind::Other, "Datagram buffer is full"));
        }
        self.write_length(length as u16);
        let target_slice = &mut self.buf[self.head..self.head + length];
        target_slice.copy_from_slice(source);
        self.head += length;
        if self.head >= self.circular_buffer_length {
            self.head = 0;
        }
        Ok(())
    }

    fn read_length(&mut self) -> u16 {
        self.tail += 2;
        BigEndian::read_u16(&self.buf[self.tail - 2..self.tail])
    }

    fn write_length(&mut self, length: u16) {
        BigEndian::write_u16(&mut self.buf[self.head..self.head + 2], length);
        self.head += 2;
    }
}

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

    fn create_datagram(length: u8) -> Vec<u8> {
        (0..length).collect()
    }

    #[test]
    fn bufferize_datagram() {
        let datagram = create_datagram(5);
        let mut datagram_buffer = DatagramBuffer::new(9);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.read_from(&datagram);
        datagram_buffer.write_to(&mut cursor).unwrap();

        assert_eq!(cursor.get_ref(), &datagram);
    }

    #[test]
    fn split_datagrams_at_boundaries() {
        let mut datagram_buffer = DatagramBuffer::new(32);

        let datagram5 = create_datagram(5);
        let datagram0 = create_datagram(0);
        let datagram3 = create_datagram(3);
        let datagram4 = create_datagram(4);

        datagram_buffer.read_from(&datagram5);
        datagram_buffer.read_from(&datagram0);
        datagram_buffer.read_from(&datagram3);
        datagram_buffer.read_from(&datagram4);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram5);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram0);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram3);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram4);
    }

    #[test]
    fn circular() {
        let datagram5 = create_datagram(5);
        let datagram3 = create_datagram(3);

        let mut datagram_buffer = DatagramBuffer::new(14);

        // write and consume 10 bytes
        datagram_buffer.read_from(&create_datagram(10));
        {
            // write and forget
            let mut cursor = io::Cursor::new(vec![]);
            datagram_buffer.write_to(&mut cursor);
        }

        // DatagramBuffer is expected to store the whole datagram (even if it exceeds its "capacity")
        datagram_buffer.read_from(&datagram5).unwrap();
        datagram_buffer.read_from(&datagram3).unwrap();

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram5);

        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        assert_eq!(cursor.get_ref(), &datagram3);
    }
}
<commit_msg>Factorize DatagramBuffer tests<commit_after>use byteorder::{BigEndian, ByteOrder};
use std::io;

const HEADER_LENGTH: usize = 2;
const MAX_DATAGRAM_LENGTH: usize = 1 << 16;
const MAX_BLOCK_LENGTH: usize = HEADER_LENGTH + MAX_DATAGRAM_LENGTH;

const TAG: &'static str = "DatagramBuffer";

/// Circular buffer to store datagrams (preserving their boundaries).
///
/// ```text
///     circularBufferLength
/// |<------------------------->| extra space for storing the last datagram in one block
/// +---------------------------+------+
/// |                           |      |
/// |[D4]     [  D1  ][ D2 ][  D3  ]   |
/// +---------------------------+------+
///     ^     ^
///  head     tail
/// ```
pub struct DatagramBuffer {
    buf: Box<[u8]>,
    head: usize,
    tail: usize,
    circular_buffer_length: usize,
}

impl DatagramBuffer {
    pub fn new(capacity: usize) -> Self {
        Self {
            buf: vec![0; capacity + MAX_BLOCK_LENGTH].into_boxed_slice(),
            head: 0,
            tail: 0,
            circular_buffer_length: capacity + 1,
        }
    }

    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    pub fn has_enough_space_for(&self, datagram_length: usize) -> bool {
        if self.head >= self.tail {
            // there is at least the extra space for storing 1 packet
            return true;
        }
        let remaining = self.tail - self.head + 1;
        HEADER_LENGTH + datagram_length < remaining
    }

    pub fn write_to<W: io::Write>(&mut self, destination: &mut W) -> io::Result<()> {
        let length = self.read_length() as usize;
        let source_slice = &self.buf[self.tail..self.tail + length];
        self.tail += length;
        if self.tail >= self.circular_buffer_length {
            self.tail = 0;
        }
        let w = destination.write(source_slice)?;
        if w != length {
            error!(target: TAG, "Cannot write the whole datagram to the buffer (only {}/{})", w, length);
            return Err(io::Error::new(io::ErrorKind::Other, "Cannot write the whole datagram"))
        }
        Ok(())
    }

    pub fn read_from(&mut self, source: &[u8]) -> io::Result<()> {
        let length = source.len();
        assert!(length <= MAX_DATAGRAM_LENGTH, "Datagram length may not be greater than {} bytes", MAX_DATAGRAM_LENGTH);
        if !self.has_enough_space_for(length) {
            return Err(io::Error::new(io::ErrorKind::Other, "Datagram buffer is full"));
        }
        self.write_length(length as u16);
        let target_slice = &mut self.buf[self.head..self.head + length];
        target_slice.copy_from_slice(source);
        self.head += length;
        if self.head >= self.circular_buffer_length {
            self.head = 0;
        }
        Ok(())
    }

    fn read_length(&mut self) -> u16 {
        self.tail += 2;
        BigEndian::read_u16(&self.buf[self.tail - 2..self.tail])
    }

    fn write_length(&mut self, length: u16) {
        BigEndian::write_u16(&mut self.buf[self.head..self.head + 2], length);
        self.head += 2;
    }
}

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

    fn create_datagram(length: u8) -> Vec<u8> {
        (0..length).collect()
    }

    #[test]
    fn bufferize_datagram() {
        let datagram = create_datagram(5);
        let mut datagram_buffer = DatagramBuffer::new(9);

        datagram_buffer.read_from(&datagram);
        assert_eq!(read_datagram(&mut datagram_buffer), datagram);
    }

    #[test]
    fn split_datagrams_at_boundaries() {
        let mut datagram_buffer = DatagramBuffer::new(32);

        let datagram5 = create_datagram(5);
        let datagram0 = create_datagram(0);
        let datagram3 = create_datagram(3);
        let datagram4 = create_datagram(4);

        datagram_buffer.read_from(&datagram5).unwrap();
        datagram_buffer.read_from(&datagram0).unwrap();
        datagram_buffer.read_from(&datagram3).unwrap();
        datagram_buffer.read_from(&datagram4).unwrap();

        assert_eq!(read_datagram(&mut datagram_buffer), datagram5);
        assert_eq!(read_datagram(&mut datagram_buffer), datagram0);
        assert_eq!(read_datagram(&mut datagram_buffer), datagram3);
        assert_eq!(read_datagram(&mut datagram_buffer), datagram4);
    }

    #[test]
    fn circular() {
        let datagram5 = create_datagram(5);
        let datagram3 = create_datagram(3);

        let mut datagram_buffer = DatagramBuffer::new(14);

        // write and consume 10 bytes
        datagram_buffer.read_from(&create_datagram(10));
        {
            // write and forget
            let mut cursor = io::Cursor::new(vec![]);
            datagram_buffer.write_to(&mut cursor);
        }

        // DatagramBuffer is expected to store the whole datagram (even if it exceeds its "capacity")
        datagram_buffer.read_from(&datagram5).unwrap();
        datagram_buffer.read_from(&datagram3).unwrap();

        assert_eq!(read_datagram(&mut datagram_buffer), datagram5);
        assert_eq!(read_datagram(&mut datagram_buffer), datagram3);
    }

    fn read_datagram(datagram_buffer: &mut DatagramBuffer) -> Vec<u8> {
        let mut cursor = io::Cursor::new(vec![]);
        datagram_buffer.write_to(&mut cursor).unwrap();
        cursor.into_inner()
    }
}
<|endoftext|>


<commit_before>
use std::ty::Unsafe;

macro_rules! is_pow2(
    ($x:ident) => (
      (($x != 0) && ($x & ($x - 1)) == 0)
    );
)

/// A container for data inside the RingBuffer
///
/// Slot must be implemented by the user.  A Slot implementation will provide
/// a generic container which holds data to be placed inside of Turbine.  The
/// contents of this container are irrelevant to Turbine, it simply needs to
/// implement the Slot trait.
///
/// Slot's must be Sendable since they are passed between tasks.
///
/// *Note:* The size of the buffer in memory, allocated immediately upon instantiation
/// of Turbine, will be `buffer_size * sizeof(YourSlot)`.
pub trait Slot: Send {
    /// Create a new Slot
    ///
    /// All Slot implementations must provide a new constructor method so that
    /// Turbine can instantiate the object.  If your Slots do not need any instantiation,
    /// simply return an empty struct in this method.
    ///
    ///##Example
    ///
    ///```
    ///struct TestSlot {
    /// pub value: int
    ///}
    ///
    ///impl Slot for TestSlot {
    ///  fn new() -> TestSlot {
    ///    TestSlot {
    ///      value: -1
    ///    }
    ///  }
    ///}
    ///```
    fn new() -> Self;
}

pub struct RingBuffer<T> {
    entries: Unsafe<Vec<T>>
}

impl<T: Slot + Send> RingBuffer<T> {

    pub fn new(size: uint) -> RingBuffer<T> {
        let entries: Unsafe<Vec<T>> = match size {
            0 => fail!("Buffer Size must be greater than zero."),
            s if !(is_pow2!(s)) => fail!("Buffer Size must be a power of two"),
            _ => Unsafe::new(Vec::from_fn(size, |_| Slot::new()))
        };

        RingBuffer::<T> {
            entries: entries
        }
    }

    pub fn get_capacity(&self) -> uint {
        let v: *mut Vec<T> = unsafe { self.entries.get() };
        unsafe { (*v).len() }
    }

    // Unsafe because we have no guarantees the caller won't invalidate this slot
    pub unsafe fn get(&self, from: uint, size: uint) -> &[T] {
        debug!("              RingBuffer get({}, {})", from, size);
        let v: *mut Vec<T> = self.entries.get();
        (*v).slice(from, size)
    }

    // Unsafe because we have no guarantees the caller won't invalidate this slot
    pub unsafe fn write(&self, position: uint, data: T) {
        let v: *mut Vec<T> = self.entries.get();
        let slot = (*v).get_mut(position);
        *slot = data;
    }
}

#[cfg(test)]
mod tests {

    use super::{RingBuffer, Slot};

    #[deriving(Show)]
    struct TestSlot;

    impl Slot for TestSlot {
        fn new() -> TestSlot {
            TestSlot
        }
    }

    #[test]
    fn new_ringbuf() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(2);
    }

    #[test]
    #[should_fail]
    fn new_ringbuff_non_power_of_two() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(5);
    }

    #[test]
    #[should_fail]
    fn new_ringbuff_zero() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(0);
    }
}
<commit_msg>Explicitly drop old slot before writing.<commit_after>
use std::ty::Unsafe;

macro_rules! is_pow2(
    ($x:ident) => (
      (($x != 0) && ($x & ($x - 1)) == 0)
    );
)

/// A container for data inside the RingBuffer
///
/// Slot must be implemented by the user.  A Slot implementation will provide
/// a generic container which holds data to be placed inside of Turbine.  The
/// contents of this container are irrelevant to Turbine, it simply needs to
/// implement the Slot trait.
///
/// Slot's must be Sendable since they are passed between tasks.
///
/// *Note:* The size of the buffer in memory, allocated immediately upon instantiation
/// of Turbine, will be `buffer_size * sizeof(YourSlot)`.
pub trait Slot: Send {
    /// Create a new Slot
    ///
    /// All Slot implementations must provide a new constructor method so that
    /// Turbine can instantiate the object.  If your Slots do not need any instantiation,
    /// simply return an empty struct in this method.
    ///
    ///##Example
    ///
    ///```
    ///struct TestSlot {
    /// pub value: int
    ///}
    ///
    ///impl Slot for TestSlot {
    ///  fn new() -> TestSlot {
    ///    TestSlot {
    ///      value: -1
    ///    }
    ///  }
    ///}
    ///```
    fn new() -> Self;
}

pub struct RingBuffer<T> {
    entries: Unsafe<Vec<T>>
}

impl<T: Slot + Send> RingBuffer<T> {

    pub fn new(size: uint) -> RingBuffer<T> {
        let entries: Unsafe<Vec<T>> = match size {
            0 => fail!("Buffer Size must be greater than zero."),
            s if !(is_pow2!(s)) => fail!("Buffer Size must be a power of two"),
            _ => Unsafe::new(Vec::from_fn(size, |_| Slot::new()))
        };

        RingBuffer::<T> {
            entries: entries
        }
    }

    pub fn get_capacity(&self) -> uint {
        let v: *mut Vec<T> = unsafe { self.entries.get() };
        unsafe { (*v).len() }
    }

    // Unsafe because we have no guarantees the caller won't invalidate this slot
    pub unsafe fn get(&self, from: uint, size: uint) -> &[T] {
        debug!("              RingBuffer get({}, {})", from, size);
        let v: *mut Vec<T> = self.entries.get();
        (*v).slice(from, size)
    }

    // Unsafe because we have no guarantees the caller won't invalidate this slot
    pub unsafe fn write(&self, position: uint, data: T) {
        let v: *mut Vec<T> = self.entries.get();
        let slot = (*v).get_mut(position);
        drop(&*slot);
        *slot = data;
    }
}

#[cfg(test)]
mod tests {

    use super::{RingBuffer, Slot};

    #[deriving(Show)]
    struct TestSlot;

    impl Slot for TestSlot {
        fn new() -> TestSlot {
            TestSlot
        }
    }

    #[test]
    fn new_ringbuf() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(2);
    }

    #[test]
    #[should_fail]
    fn new_ringbuff_non_power_of_two() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(5);
    }

    #[test]
    #[should_fail]
    fn new_ringbuff_zero() {
        let _: RingBuffer<TestSlot> = RingBuffer::new(0);
    }
}
<|endoftext|>


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

use text_writer::{mod, TextWriter};

use ast::*;
use ast::ComponentValue::*;

pub trait ToCss for Sized? {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter;

    fn to_css_string(&self) -> String {
        let mut s = String::new();
        self.to_css(&mut s).unwrap();
        s
    }
}

impl ToCss for ComponentValue {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match self {
            &Ident(ref value) => try!(serialize_identifier(value.as_slice(), dest)),
            &AtKeyword(ref value) => {
                try!(dest.write_char('@'));
                try!(serialize_identifier(value.as_slice(), dest));
            },
            &Hash(ref value) => {
                try!(dest.write_char('#'));
                for c in value.as_slice().chars() {
                    try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                }
            },
            &IDHash(ref value) => {
                try!(dest.write_char('#'));
                try!(serialize_identifier(value.as_slice(), dest));
            }
            &QuotedString(ref value) => try!(serialize_string(value.as_slice(), dest)),
            &URL(ref value) => {
                try!(dest.write_str("url("));
                try!(serialize_string(value.as_slice(), dest));
                try!(dest.write_char(')'));
            },
            &Delim(value) => try!(dest.write_char(value)),

            &Number(ref value) => try!(dest.write_str(value.representation.as_slice())),
            &Percentage(ref value) => {
                try!(dest.write_str(value.representation.as_slice()));
                try!(dest.write_char('%'));
            },
            &Dimension(ref value, ref unit) => {
                try!(dest.write_str(value.representation.as_slice()));
                // Disambiguate with scientific notation.
                let unit = unit.as_slice();
                if unit == "e" || unit == "E" || unit.starts_with("e-") || unit.starts_with("E-") {
                    try!(dest.write_str("\\65 "));
                    for c in unit.slice_from(1).chars() {
                        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                    }
                } else {
                    try!(serialize_identifier(unit, dest));
                }
            },

            &UnicodeRange(start, end) => {
                try!(dest.write_str(format!("U+{:X}", start).as_slice()));
                if end != start {
                    try!(dest.write_str(format!("-{:X}", end).as_slice()));
                }
            }

            &WhiteSpace => try!(dest.write_char(' ')),
            &Colon => try!(dest.write_char(':')),
            &Semicolon => try!(dest.write_char(';')),
            &Comma => try!(dest.write_char(',')),
            &IncludeMatch => try!(dest.write_str("~=")),
            &DashMatch => try!(dest.write_str("|=")),
            &PrefixMatch => try!(dest.write_str("^=")),
            &SuffixMatch => try!(dest.write_str("$=")),
            &SubstringMatch => try!(dest.write_str("*=")),
            &Column => try!(dest.write_str("||")),
            &CDO => try!(dest.write_str("<!--")),
            &CDC => try!(dest.write_str("-->")),

            &Function(ref name, ref arguments) => {
                try!(serialize_identifier(name.as_slice(), dest));
                try!(dest.write_char('('));
                try!(arguments.to_css(dest));
                try!(dest.write_char(')'));
            },
            &ParenthesisBlock(ref content) => {
                try!(dest.write_char('('));
                try!(content.to_css(dest));
                try!(dest.write_char(')'));
            },
            &SquareBracketBlock(ref content) => {
                try!(dest.write_char('['));
                try!(content.to_css(dest));
                try!(dest.write_char(']'));
            },
            &CurlyBracketBlock(ref content) => {
                try!(dest.write_char('{'));
                let component_values = content.iter().map(|t| match *t { (ref c, _) => c });
                try!(component_values_to_css(component_values, dest));
                try!(dest.write_char('}'));
            },

            &BadURL => try!(dest.write_str("url(<bad url>)")),
            &BadString => try!(dest.write_str("\"<bad string>\n")),
            &CloseParenthesis => try!(dest.write_char(')')),
            &CloseSquareBracket => try!(dest.write_char(']')),
            &CloseCurlyBracket => try!(dest.write_char('}')),
        }
        Ok(())
    }
}

pub fn serialize_identifier<W>(value: &str, dest: &mut W) -> text_writer::Result
where W:TextWriter {
    // TODO: avoid decoding/re-encoding UTF-8?
    let mut iter = value.chars();
    let mut c = iter.next().unwrap();
    if c == '-' {
        c = match iter.next() {
            None => return dest.write_str("\\-"),
            Some(c) => { try!(dest.write_char('-')); c },
        }
    };
    try!(serialize_char(c, dest, /* is_identifier_start = */ true));
    for c in iter {
        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
    }
    Ok(())
}

#[inline]
fn serialize_char<W>(c: char, dest: &mut W, is_identifier_start: bool) -> text_writer::Result
where W: TextWriter {
    match c {
        '0'...'9' if is_identifier_start => try!(dest.write_str(format!("\\3{} ", c).as_slice())),
        '-' if is_identifier_start => try!(dest.write_str("\\-")),
        '0'...'9' | 'A'...'Z' | 'a'...'z' | '_' | '-' => try!(dest.write_char(c)),
        _ if c > '\x7F' => try!(dest.write_char(c)),
        '\n' => try!(dest.write_str("\\A ")),
        '\r' => try!(dest.write_str("\\D ")),
        '\x0C' => try!(dest.write_str("\\C ")),
        _ => { try!(dest.write_char('\\')); try!(dest.write_char(c)) },
    };
    Ok(())
}

pub fn serialize_string<W>(value: &str, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    try!(dest.write_char('"'));
    // TODO: avoid decoding/re-encoding UTF-8?
    for c in value.chars() {
        match c {
            '"' => try!(dest.write_str("\\\"")),
            '\\' => try!(dest.write_str("\\\\")),
            '\n' => try!(dest.write_str("\\A ")),
            '\r' => try!(dest.write_str("\\D ")),
            '\x0C' => try!(dest.write_str("\\C ")),
            _ => try!(dest.write_char(c)),
        };
    }
    dest.write_char('"')
}

impl<'a> ToCss for [ComponentValue] {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        component_values_to_css(self.iter(), dest)
    }
}

fn component_values_to_css<'a, I, W>(mut iter: I, dest: &mut W) -> text_writer::Result
where I: Iterator<&'a ComponentValue>, W: TextWriter {
    let mut previous = match iter.next() {
        None => return Ok(()),
        Some(first) => { try!(first.to_css(dest)); first }
    };
    macro_rules! matches(
        ($value:expr, $($pattern:pat)|+) => (
            match $value { $($pattern)|+ => true, _ => false }
        );
    )
    // This does not borrow-check: for component_value in iter {
    loop { match iter.next() { None => break, Some(component_value) => {
        let (a, b) = (previous, component_value);
        if (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) |
                         Dimension(..) | Delim('#') | Delim('-') | Number(..)) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..) |
                         Number(..) | Percentage(..) | Dimension(..) | UnicodeRange(..))
        ) || (
            matches!(*a, Ident(..)) &&
            matches!(*b, ParenthesisBlock(..))
        ) || (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) | Dimension(..)) &&
            matches!(*b, Delim('-') | CDC)
        ) || (
            matches!(*a, Delim('#') | Delim('-') | Number(..) | Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..))
        ) || (
            matches!(*a, Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..) |
                         UnicodeRange(..) | Delim('-'))
        ) || (
            matches!(*a, UnicodeRange(..) | Delim('.') | Delim('+')) &&
            matches!(*b, Number(..) | Percentage(..) | Dimension(..))
        ) || (
            matches!(*a, UnicodeRange(..)) &&
            matches!(*b, Ident(..) | Function(..) | Delim('?'))
        ) || (match (a, b) { (&Delim(a), &Delim(b)) => matches!((a, b),
            ('#', '-') |
            ('$', '=') |
            ('*', '=') |
            ('^', '=') |
            ('~', '=') |
            ('|', '=') |
            ('|', '|') |
            ('/', '*')
        ), _ => false }) {
            try!(dest.write_str("/**/"));
        }
        // Skip whitespace when '\n' was previously written at the previous iteration.
        if !matches!((previous, component_value), (&Delim('\\'), &WhiteSpace)) {
            try!(component_value.to_css(dest));
        }
        if component_value == &Delim('\\') {
            try!(dest.write_char('\n'));
        }
        previous = component_value;
    }}}
    Ok(())
}
<commit_msg>Implement ToCss for more AST things.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use text_writer::{mod, TextWriter};

use ast::*;
use ast::ComponentValue::*;

pub trait ToCss for Sized? {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter;

    fn to_css_string(&self) -> String {
        let mut s = String::new();
        self.to_css(&mut s).unwrap();
        s
    }
}

impl ToCss for ComponentValue {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match self {
            &Ident(ref value) => try!(serialize_identifier(value.as_slice(), dest)),
            &AtKeyword(ref value) => {
                try!(dest.write_char('@'));
                try!(serialize_identifier(value.as_slice(), dest));
            },
            &Hash(ref value) => {
                try!(dest.write_char('#'));
                for c in value.as_slice().chars() {
                    try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                }
            },
            &IDHash(ref value) => {
                try!(dest.write_char('#'));
                try!(serialize_identifier(value.as_slice(), dest));
            }
            &QuotedString(ref value) => try!(serialize_string(value.as_slice(), dest)),
            &URL(ref value) => {
                try!(dest.write_str("url("));
                try!(serialize_string(value.as_slice(), dest));
                try!(dest.write_char(')'));
            },
            &Delim(value) => try!(dest.write_char(value)),

            &Number(ref value) => try!(dest.write_str(value.representation.as_slice())),
            &Percentage(ref value) => {
                try!(dest.write_str(value.representation.as_slice()));
                try!(dest.write_char('%'));
            },
            &Dimension(ref value, ref unit) => {
                try!(dest.write_str(value.representation.as_slice()));
                // Disambiguate with scientific notation.
                let unit = unit.as_slice();
                if unit == "e" || unit == "E" || unit.starts_with("e-") || unit.starts_with("E-") {
                    try!(dest.write_str("\\65 "));
                    for c in unit.slice_from(1).chars() {
                        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
                    }
                } else {
                    try!(serialize_identifier(unit, dest));
                }
            },

            &UnicodeRange(start, end) => {
                try!(dest.write_str(format!("U+{:X}", start).as_slice()));
                if end != start {
                    try!(dest.write_str(format!("-{:X}", end).as_slice()));
                }
            }

            &WhiteSpace => try!(dest.write_char(' ')),
            &Colon => try!(dest.write_char(':')),
            &Semicolon => try!(dest.write_char(';')),
            &Comma => try!(dest.write_char(',')),
            &IncludeMatch => try!(dest.write_str("~=")),
            &DashMatch => try!(dest.write_str("|=")),
            &PrefixMatch => try!(dest.write_str("^=")),
            &SuffixMatch => try!(dest.write_str("$=")),
            &SubstringMatch => try!(dest.write_str("*=")),
            &Column => try!(dest.write_str("||")),
            &CDO => try!(dest.write_str("<!--")),
            &CDC => try!(dest.write_str("-->")),

            &Function(ref name, ref arguments) => {
                try!(serialize_identifier(name.as_slice(), dest));
                try!(dest.write_char('('));
                try!(arguments.to_css(dest));
                try!(dest.write_char(')'));
            },
            &ParenthesisBlock(ref content) => {
                try!(dest.write_char('('));
                try!(content.to_css(dest));
                try!(dest.write_char(')'));
            },
            &SquareBracketBlock(ref content) => {
                try!(dest.write_char('['));
                try!(content.to_css(dest));
                try!(dest.write_char(']'));
            },
            &CurlyBracketBlock(ref content) => {
                try!(dest.write_char('{'));
                try!(content.to_css(dest));
                try!(dest.write_char('}'));
            },

            &BadURL => try!(dest.write_str("url(<bad url>)")),
            &BadString => try!(dest.write_str("\"<bad string>\n")),
            &CloseParenthesis => try!(dest.write_char(')')),
            &CloseSquareBracket => try!(dest.write_char(']')),
            &CloseCurlyBracket => try!(dest.write_char('}')),
        }
        Ok(())
    }
}

pub fn serialize_identifier<W>(value: &str, dest: &mut W) -> text_writer::Result
where W:TextWriter {
    // TODO: avoid decoding/re-encoding UTF-8?
    let mut iter = value.chars();
    let mut c = iter.next().unwrap();
    if c == '-' {
        c = match iter.next() {
            None => return dest.write_str("\\-"),
            Some(c) => { try!(dest.write_char('-')); c },
        }
    };
    try!(serialize_char(c, dest, /* is_identifier_start = */ true));
    for c in iter {
        try!(serialize_char(c, dest, /* is_identifier_start = */ false));
    }
    Ok(())
}

#[inline]
fn serialize_char<W>(c: char, dest: &mut W, is_identifier_start: bool) -> text_writer::Result
where W: TextWriter {
    match c {
        '0'...'9' if is_identifier_start => try!(dest.write_str(format!("\\3{} ", c).as_slice())),
        '-' if is_identifier_start => try!(dest.write_str("\\-")),
        '0'...'9' | 'A'...'Z' | 'a'...'z' | '_' | '-' => try!(dest.write_char(c)),
        _ if c > '\x7F' => try!(dest.write_char(c)),
        '\n' => try!(dest.write_str("\\A ")),
        '\r' => try!(dest.write_str("\\D ")),
        '\x0C' => try!(dest.write_str("\\C ")),
        _ => { try!(dest.write_char('\\')); try!(dest.write_char(c)) },
    };
    Ok(())
}

pub fn serialize_string<W>(value: &str, dest: &mut W) -> text_writer::Result
where W: TextWriter {
    try!(dest.write_char('"'));
    // TODO: avoid decoding/re-encoding UTF-8?
    for c in value.chars() {
        match c {
            '"' => try!(dest.write_str("\\\"")),
            '\\' => try!(dest.write_str("\\\\")),
            '\n' => try!(dest.write_str("\\A ")),
            '\r' => try!(dest.write_str("\\D ")),
            '\x0C' => try!(dest.write_str("\\C ")),
            _ => try!(dest.write_char(c)),
        };
    }
    dest.write_char('"')
}

impl<'a> ToCss for [ComponentValue] {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        component_values_to_css(self.iter(), dest)
    }
}

impl<'a> ToCss for [Node] {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        let component_values = self.iter().map(|n| match n { &(ref c, _) => c });
        component_values_to_css(component_values, dest)
    }
}

fn component_values_to_css<'a, I, W>(mut iter: I, dest: &mut W) -> text_writer::Result
where I: Iterator<&'a ComponentValue>, W: TextWriter {
    let mut previous = match iter.next() {
        None => return Ok(()),
        Some(first) => { try!(first.to_css(dest)); first }
    };
    macro_rules! matches(
        ($value:expr, $($pattern:pat)|+) => (
            match $value { $($pattern)|+ => true, _ => false }
        );
    )
    // This does not borrow-check: for component_value in iter {
    loop { match iter.next() { None => break, Some(component_value) => {
        let (a, b) = (previous, component_value);
        if (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) |
                         Dimension(..) | Delim('#') | Delim('-') | Number(..)) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..) |
                         Number(..) | Percentage(..) | Dimension(..) | UnicodeRange(..))
        ) || (
            matches!(*a, Ident(..)) &&
            matches!(*b, ParenthesisBlock(..))
        ) || (
            matches!(*a, Ident(..) | AtKeyword(..) | Hash(..) | IDHash(..) | Dimension(..)) &&
            matches!(*b, Delim('-') | CDC)
        ) || (
            matches!(*a, Delim('#') | Delim('-') | Number(..) | Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..))
        ) || (
            matches!(*a, Delim('@')) &&
            matches!(*b, Ident(..) | Function(..) | URL(..) | BadURL(..) |
                         UnicodeRange(..) | Delim('-'))
        ) || (
            matches!(*a, UnicodeRange(..) | Delim('.') | Delim('+')) &&
            matches!(*b, Number(..) | Percentage(..) | Dimension(..))
        ) || (
            matches!(*a, UnicodeRange(..)) &&
            matches!(*b, Ident(..) | Function(..) | Delim('?'))
        ) || (match (a, b) { (&Delim(a), &Delim(b)) => matches!((a, b),
            ('#', '-') |
            ('$', '=') |
            ('*', '=') |
            ('^', '=') |
            ('~', '=') |
            ('|', '=') |
            ('|', '|') |
            ('/', '*')
        ), _ => false }) {
            try!(dest.write_str("/**/"));
        }
        // Skip whitespace when '\n' was previously written at the previous iteration.
        if !matches!((previous, component_value), (&Delim('\\'), &WhiteSpace)) {
            try!(component_value.to_css(dest));
        }
        if component_value == &Delim('\\') {
            try!(dest.write_char('\n'));
        }
        previous = component_value;
    }}}
    Ok(())
}

impl ToCss for Declaration {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        try!(dest.write_str(self.name.as_slice()));
        try!(dest.write_char(':'));
        try!(self.value.to_css(dest));
        Ok(())
    }
}

impl ToCss for QualifiedRule {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        try!(self.prelude.to_css(dest));
        try!(dest.write_char('{'));
        try!(self.block.to_css(dest));
        try!(dest.write_char('}'));
        Ok(())
    }
}

impl ToCss for AtRule {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        try!(dest.write_char('@'));
        try!(dest.write_str(self.name.as_slice()));
        try!(self.prelude.to_css(dest));
        match self.block {
            Some(ref block) => {
                try!(dest.write_char('{'));
                try!(block.to_css(dest));
                try!(dest.write_char('}'));
            }
            None => try!(dest.write_char(';'))
        }
        Ok(())
    }
}

impl ToCss for DeclarationListItem {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match *self {
            DeclarationListItem::Declaration(ref declaration) => declaration.to_css(dest),
            DeclarationListItem::AtRule(ref at_rule) => at_rule.to_css(dest),
        }
    }
}

impl ToCss for Rule {
    fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
        match *self {
            Rule::QualifiedRule(ref rule) => rule.to_css(dest),
            Rule::AtRule(ref rule) => rule.to_css(dest),
        }
    }
}
<|endoftext|>