<commit_before>use polynomial::Polynomial;
use nalgebra::Vector2;
use std::cmp::max;
use roots::find_roots_quartic;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn multiply_and_shift_avoiding_overflow_by_rounding (stuff: & [Coordinate], shift: i32)->Coordinate {
let mut sign: Coordinate = 1;
let mut product = 1u64;
let mut shift = shift;
for thing in stuff {
let mut factor = thing.clone();
if factor <0 {factor*= -1; sign *= -1;}
let mut factor = factor as u64;
while product >= (1u64) << 32 && shift >0 {product >>= 1; shift -= 1;}
while factor >= (1u64) << 32 && shift >0 {factor >>= 1; shift -= 1;}
//printlnerr!(" {}, {}, {}", product, factor, shift);
product = product*factor;
}
((product as Coordinate)*sign) >> shift
}

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the unnecessary heap-allocation and other inefficiencies of Polynomial, and other pointless inefficiencies I introduced
// TODO replace f64 with a deterministic type (probably mpfr)
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone,)]
pub struct QuadraticTrajectory {
  data: Vector2<Polynomial<Coordinate>>,
  time_scale_shift: i32,
}
fn updated_by(poly: &Polynomial<Coordinate>,
              time: Coordinate,
              time_scale_shift: i32)
              -> Polynomial<Coordinate> {
  &*poly +
  Polynomial::new(vec![multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(1).cloned().unwrap_or(0), time], time_scale_shift) +
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time, time], time_scale_shift * 2),
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time * 2], time_scale_shift),
                       0i64])
}
impl QuadraticTrajectory {
  pub fn new(time_scale_shift: i32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: Vector2::new(Polynomial::new(vec![coordinates[0], coordinates[2], coordinates[4]]),
                         Polynomial::new(vec![coordinates[1], coordinates[3], coordinates[5]])),
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    QuadraticTrajectory {
      data: Vector2::new(updated_by(&self.data[0], time, self.time_scale_shift),
                         updated_by(&self.data[1], time, self.time_scale_shift)),
      ..self.clone()
    }
  }

  pub fn update_by(&mut self, time: Coordinate) {
    *self = self.updated_by(time);
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    let changed = &self.data[0] + Polynomial::new(vec![0, 0, acceleration[0]*2]);
    self.data[0].clone_from(&changed);
    let changed = &self.data[1] + Polynomial::new(vec![0, 0, acceleration[1]*2]);
    self.data[1].clone_from(&changed);
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0].data().get(0).cloned().unwrap_or(0),
                 self.data[1].data().get(0).cloned().unwrap_or(0))

  }

  pub fn approximate_starting_distance_squared (first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            ->Coordinate {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
        let checker = third.data.clone() - more.data.clone();

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);
real_distance_squared
  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");
    let error = distance * 12 + 6;
    let ratio = (1i64 << first.1.time_scale_shift) as f64;

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
    let displacement_function: Vector2<Polynomial<Coordinate>> = third.data.clone() - more.data.clone();
    let distance_function = &displacement_function[0] * &displacement_function[0] +
                            &displacement_function[1] * &displacement_function[1];
                            //printlnerr!(" distance function {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}", first.1.data, second.1.data, error, ratio, third.data, more.data, displacement_function, distance_function);
    let roots = find_roots_quartic(distance_function.data().get(4).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(4),
                                   distance_function.data().get(3).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(3),
                                   distance_function.data().get(2).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(2),
                                   distance_function.data().get(1).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(1),
                                   (distance_function.data().get(0).cloned().unwrap_or(0) -
                                    (distance * distance +
                                     error * direction)) as f64);

    for root in roots.as_ref() {
    //printlnerr!(" found group {}", root);
      let result = root.ceil() as Coordinate;
      if result > 0 {
    let third = first.1.updated_by(base + result - first.0);
    let more = second.1.updated_by(base + result - second.0);
        let checker = third.data.clone() - more.data.clone();
        //Vector2::new(updated_by(&displacement_function[0],
                                              //result,
                                              //first.1.time_scale_shift),
                                   //updated_by(&displacement_function[1],
                                              //result,
                                              //first.1.time_scale_shift));

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);

        if (real_distance_squared - distance * distance) * direction > 0 {
        //printlnerr!(" check past");
          return Some(base + result);
        }
      }
    }
    None
  }
}
<commit_msg>handle "already passed" case<commit_after>use polynomial::Polynomial;
use nalgebra::Vector2;
use std::cmp::max;
use roots::find_roots_quartic;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn multiply_and_shift_avoiding_overflow_by_rounding (stuff: & [Coordinate], shift: i32)->Coordinate {
let mut sign: Coordinate = 1;
let mut product = 1u64;
let mut shift = shift;
for thing in stuff {
let mut factor = thing.clone();
if factor <0 {factor*= -1; sign *= -1;}
let mut factor = factor as u64;
while product >= (1u64) << 32 && shift >0 {product >>= 1; shift -= 1;}
while factor >= (1u64) << 32 && shift >0 {factor >>= 1; shift -= 1;}
//printlnerr!(" {}, {}, {}", product, factor, shift);
product = product*factor;
}
((product as Coordinate)*sign) >> shift
}

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the unnecessary heap-allocation and other inefficiencies of Polynomial, and other pointless inefficiencies I introduced
// TODO replace f64 with a deterministic type (probably mpfr)
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone,)]
pub struct QuadraticTrajectory {
  data: Vector2<Polynomial<Coordinate>>,
  time_scale_shift: i32,
}
fn updated_by(poly: &Polynomial<Coordinate>,
              time: Coordinate,
              time_scale_shift: i32)
              -> Polynomial<Coordinate> {
  &*poly +
  Polynomial::new(vec![multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(1).cloned().unwrap_or(0), time], time_scale_shift) +
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time, time], time_scale_shift * 2),
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time * 2], time_scale_shift),
                       0i64])
}
impl QuadraticTrajectory {
  pub fn new(time_scale_shift: i32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: Vector2::new(Polynomial::new(vec![coordinates[0], coordinates[2], coordinates[4]]),
                         Polynomial::new(vec![coordinates[1], coordinates[3], coordinates[5]])),
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    QuadraticTrajectory {
      data: Vector2::new(updated_by(&self.data[0], time, self.time_scale_shift),
                         updated_by(&self.data[1], time, self.time_scale_shift)),
      ..self.clone()
    }
  }

  pub fn update_by(&mut self, time: Coordinate) {
    *self = self.updated_by(time);
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    let changed = &self.data[0] + Polynomial::new(vec![0, 0, acceleration[0]*2]);
    self.data[0].clone_from(&changed);
    let changed = &self.data[1] + Polynomial::new(vec![0, 0, acceleration[1]*2]);
    self.data[1].clone_from(&changed);
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0].data().get(0).cloned().unwrap_or(0),
                 self.data[1].data().get(0).cloned().unwrap_or(0))

  }

  pub fn approximate_starting_distance_squared (first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            ->Coordinate {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
        let checker = third.data.clone() - more.data.clone();

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);
real_distance_squared
  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");
    let error = distance * 12 + 6;
    let ratio = (1i64 << first.1.time_scale_shift) as f64;

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
    let displacement_function: Vector2<Polynomial<Coordinate>> = third.data.clone() - more.data.clone();

        let starting_distance_squared = displacement_function[0].data().get(0).cloned().unwrap_or(0) *
                                    displacement_function[0].data().get(0).cloned().unwrap_or(0) +
                                    displacement_function[1].data().get(0).cloned().unwrap_or(0) *
                                    displacement_function[1].data().get(0).cloned().unwrap_or(0);

        if (starting_distance_squared - distance * distance) * direction > 0 {
          return Some(base);
        }

    let distance_function = &displacement_function[0] * &displacement_function[0] +
                            &displacement_function[1] * &displacement_function[1];
                            //printlnerr!(" distance function {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}", first.1.data, second.1.data, error, ratio, third.data, more.data, displacement_function, distance_function);
    let roots = find_roots_quartic(distance_function.data().get(4).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(4),
                                   distance_function.data().get(3).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(3),
                                   distance_function.data().get(2).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(2),
                                   distance_function.data().get(1).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(1),
                                   (distance_function.data().get(0).cloned().unwrap_or(0) -
                                    (distance * distance +
                                     error * direction)) as f64);

    for root in roots.as_ref() {
    //printlnerr!(" found group {}", root);
      let result = root.ceil() as Coordinate;
      if result > 0 {
    let third = first.1.updated_by(base + result - first.0);
    let more = second.1.updated_by(base + result - second.0);
        let checker = third.data.clone() - more.data.clone();
        //Vector2::new(updated_by(&displacement_function[0],
                                              //result,
                                              //first.1.time_scale_shift),
                                   //updated_by(&displacement_function[1],
                                              //result,
                                              //first.1.time_scale_shift));

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);

        if (real_distance_squared - distance * distance) * direction > 0 {
        //printlnerr!(" check past");
          return Some(base + result);
        }
      }
    }
    None
  }
}
<|endoftext|>


<commit_before>//! The module contains implementations of the transport layer functionality
//! that HTTP/2 requires. It exposes APIs that allow the HTTP/2 connection to
//! use the transport layer without requiring it to know which exact
//! implementation they are using (i.e. a clear-text TCP connection, a TLS
//! protected connection, or even a mock implementation).
<commit_msg>Add a `TransportStream` trait for transport-layer implementations<commit_after>//! The module contains implementations of the transport layer functionality
//! that HTTP/2 requires. It exposes APIs that allow the HTTP/2 connection to
//! use the transport layer without requiring it to know which exact
//! implementation they are using (i.e. a clear-text TCP connection, a TLS
//! protected connection, or even a mock implementation).

use std::old_io::Stream;

/// A trait that any struct that wants to provide the transport layer for
/// HTTP/2 needs to implement.
///
/// For now, we do not define any additional methods on top of those required
/// by the `Stream` trait.
pub trait TransportStream: Stream {}
<|endoftext|>


<commit_before>// Original authorship burntsushi.

use std::str;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8    = 0b1000_0000;
const TAG_TWO_B: u8   = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8  = 0b1111_0000;
const MAX_ONE_B: u32   =     0x80;
const MAX_TWO_B: u32   =    0x800;
const MAX_THREE_B: u32 =  0x10000;

/// Write a utf-8 char as a sequence of bytes.
#[inline]
pub fn encode_utf8(character: char, dst: &mut [u8]) -> Option<usize> {
    let code = character as u32;
    if code < MAX_ONE_B && !dst.is_empty() {
        dst[0] = code as u8;
        Some(1)
    } else if code < MAX_TWO_B && dst.len() >= 2 {
        dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
        dst[1] = (code & 0x3F) as u8 | TAG_CONT;
        Some(2)
    } else if code < MAX_THREE_B && dst.len() >= 3  {
        dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
        dst[1] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
        dst[2] = (code & 0x3F) as u8 | TAG_CONT;
        Some(3)
    } else if dst.len() >= 4 {
        dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
        dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
        dst[2] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
        dst[3] = (code & 0x3F) as u8 | TAG_CONT;
        Some(4)
    } else {
        None
    }
}

/// Converts a sequence of bytes into a char, if possible. Also returns the byte len of the char.
#[inline]
pub fn decode_utf8(src: &[u8]) -> Option<(usize, char)> {
    if src.len() == 0 {
        return None;
    }
    match utf8_char_width(src[0]) {
        0 => None,
        1 => Some((1, src[0] as char)),
        n if src.len() < n => None,
        n => {
            match str::from_utf8(&src[0..n]) {
                Ok(s) => Some((n, s.chars().next().unwrap())),
                Err(_) => None,
            }
        }
    }
}

// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
];

/// Given a first byte, determine how many bytes are in this UTF-8 character
#[inline]
pub fn utf8_char_width(b: u8) -> usize {
    UTF8_CHAR_WIDTH[b as usize] as usize
}
<commit_msg>Don't rustfmt util/char_utf8.rs<commit_after>// Original authorship burntsushi.
#![cfg_attr(rustfmt, rustfmt_skip)]
use std::str;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8    = 0b1000_0000;
const TAG_TWO_B: u8   = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8  = 0b1111_0000;
const MAX_ONE_B: u32   =     0x80;
const MAX_TWO_B: u32   =    0x800;
const MAX_THREE_B: u32 =  0x10000;

/// Write a utf-8 char as a sequence of bytes.
#[inline]
pub fn encode_utf8(character: char, dst: &mut [u8]) -> Option<usize> {
    let code = character as u32;
    if code < MAX_ONE_B && !dst.is_empty() {
        dst[0] = code as u8;
        Some(1)
    } else if code < MAX_TWO_B && dst.len() >= 2 {
        dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
        dst[1] = (code & 0x3F) as u8 | TAG_CONT;
        Some(2)
    } else if code < MAX_THREE_B && dst.len() >= 3  {
        dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
        dst[1] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
        dst[2] = (code & 0x3F) as u8 | TAG_CONT;
        Some(3)
    } else if dst.len() >= 4 {
        dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
        dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
        dst[2] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
        dst[3] = (code & 0x3F) as u8 | TAG_CONT;
        Some(4)
    } else {
        None
    }
}

/// Converts a sequence of bytes into a char, if possible. Also returns the byte len of the char.
#[inline]
pub fn decode_utf8(src: &[u8]) -> Option<(usize, char)> {
    if src.len() == 0 {
        return None;
    }
    match utf8_char_width(src[0]) {
        0 => None,
        1 => Some((1, src[0] as char)),
        n if src.len() < n => None,
        n => {
            match str::from_utf8(&src[0..n]) {
                Ok(s) => Some((n, s.chars().next().unwrap())),
                Err(_) => None,
            }
        }
    }
}

// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
];

/// Given a first byte, determine how many bytes are in this UTF-8 character
#[inline]
pub fn utf8_char_width(b: u8) -> usize {
    UTF8_CHAR_WIDTH[b as usize] as usize
}
<|endoftext|>


<commit_before>//! Handle network connections for a varlink service

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;
use std::env;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::net::{Shutdown, TcpListener, TcpStream};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<i32>> {
    match env::var("LISTEN_FDS") {
        Ok(ref nfds) if nfds.parse::<u32>() == Ok(1) => {}
        _ => return Ok(None),
    }

    unsafe {
        match env::var("LISTEN_PID") {
            //FIXME: replace Ok(getpid()) with Ok(process::id())
            Ok(ref pid) if pid.parse::<i32>() == Ok(getpid()) => {}
            _ => return Ok(None),
        }

        //syscall.CloseOnExec(3)
        //let listener = UnixListener::from_raw_fd(3);
        env::remove_var("LISTEN_PID");
        env::remove_var("LISTEN_FDS");

        Ok(Some(3))
    }
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            if address.starts_with("tcp:") {
                unsafe {
                    return Ok(VarlinkListener::TCP(TcpListener::from_raw_fd(l)));
                }
            } else if address.starts_with("unix:") {
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(l)));
                }
            } else {
                return Err(Error::new(ErrorKind::Other, "unknown varlink address"));
            }
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(&*addr);
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

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

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();

            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }

        let service = service.clone();

        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");

            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<commit_msg>honor env LISTEN_FDNAMES<commit_after>//! Handle network connections for a varlink service

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;
use std::env;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::net::{Shutdown, TcpListener, TcpStream};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<i32>> {
    let nfds: u32;

    match env::var("LISTEN_FDS") {
        Ok(ref n) => match n.parse::<u32>() {
            Ok(n) if n >= 1 => nfds = n,
            _ => return Ok(None),
        },
        _ => return Ok(None),
    }

    unsafe {
        match env::var("LISTEN_PID") {
            //FIXME: replace Ok(getpid()) with Ok(process::id())
            Ok(ref pid) if pid.parse::<i32>() == Ok(getpid()) => {}
            _ => return Ok(None),
        }
    }

    let fdnames: String;

    match env::var("LISTEN_FDNAMES") {
        Ok(n) => {
            fdnames = n;
        }
        _ => if nfds == 1 {
            return Ok(Some(3));
        } else {
            return Ok(None);
        },
    }

    for (i, v) in fdnames.split(":").enumerate() {
        if v == "varlink" {
            return Ok(Some(3 + i as i32));
        }
    }

    Ok(None)
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            if address.starts_with("tcp:") {
                unsafe {
                    return Ok(VarlinkListener::TCP(TcpListener::from_raw_fd(l)));
                }
            } else if address.starts_with("unix:") {
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(l)));
                }
            } else {
                return Err(Error::new(ErrorKind::Other, "unknown varlink address"));
            }
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(&*addr);
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

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

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();

            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }

        let service = service.clone();

        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");

            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<|endoftext|>


<commit_before>use core::ptr::Unique;
use spin::Mutex;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;
const VGA_BUFFER_ADDRESS: usize = 0xb8000;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    /// Contructor
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[CharCell; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }
    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }
    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        // TODO: boundary check
        self.row = row;
        self.col = col;
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    raw_mode: bool,
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }
    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let mut buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col] = CharCell {
                    character: b' ',
                    color: clear_color,
                };
            }
        }
    }
    /// Write string to terminal's stdout
    pub fn write_str(&mut self, string: &str) {
        let sb = string.as_bytes();
        for index in 0..sb.len() {
            self.write_byte(sb[index]);
        }
    }
    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }

            self.get_buffer().chars[self.cursor.row][self.cursor.col] = CharCell {
                character: byte,
                color: self.output_color,
            };
            self.cursor.next();
        }
    }
    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        if self.cursor.newline() {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        for row in 0..(SCREEN_HEIGHT-1) {
            self.get_buffer().chars[row] = self.get_buffer().chars[row+1];
        }
        self.get_buffer().chars[SCREEN_HEIGHT-1] = [CharCell {character: b' ', color: self.output_color}; SCREEN_WIDTH];
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.get_mut()}
    }
}
/// Format macros
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    raw_mode: false,
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new(VGA_BUFFER_ADDRESS as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().write_fmt(format_args!($($arg)*)).unwrap();
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
<commit_msg>Remove unused raw_mode<commit_after>use core::ptr::Unique;
use spin::Mutex;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;
const VGA_BUFFER_ADDRESS: usize = 0xb8000;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    /// Contructor
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[CharCell; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }
    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }
    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        // TODO: boundary check
        self.row = row;
        self.col = col;
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }
    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let mut buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col] = CharCell {
                    character: b' ',
                    color: clear_color,
                };
            }
        }
    }
    /// Write string to terminal's stdout
    pub fn write_str(&mut self, string: &str) {
        let sb = string.as_bytes();
        for index in 0..sb.len() {
            self.write_byte(sb[index]);
        }
    }
    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }

            self.get_buffer().chars[self.cursor.row][self.cursor.col] = CharCell {
                character: byte,
                color: self.output_color,
            };
            self.cursor.next();
        }
    }
    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        if self.cursor.newline() {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        for row in 0..(SCREEN_HEIGHT-1) {
            self.get_buffer().chars[row] = self.get_buffer().chars[row+1];
        }
        self.get_buffer().chars[SCREEN_HEIGHT-1] = [CharCell {character: b' ', color: self.output_color}; SCREEN_WIDTH];
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.get_mut()}
    }
}
/// Format macros
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new(VGA_BUFFER_ADDRESS as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().write_fmt(format_args!($($arg)*)).unwrap();
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
<|endoftext|>


<commit_before>use std::{thread, time};
use std::fs;
use std::process::Command;

pub struct Python {
    user: String,
    subject: String,
}

pub struct Scala {
    user: String,
    subject: String,
}

pub trait Lang {
    fn new(user: String, subject: String) -> Self;
    fn run_test(&self);
}

impl Lang for Python {
    fn new(user: String, subject: String) -> Python {
        Python { user: user, subject: subject}
    }

    fn run_test(&self) {
        let from = format!("/home/{}/Code-Fight/python/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/python/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);
        fs::copy(&from, &to);

        let result = Command::new("nosetests")
               .arg(&to)
               .output()
               .expect("cat error to start");

        println!("result: {:?}", &result);
        //let sleep_time = time::Duration::new(10, 0);;
        //thread::sleep(sleep_time);
    }
}

impl Lang for Scala {
    fn new(user: String, subject: String) -> Scala {
        Scala { user: user, subject: subject}
    }

    fn run_test(&self) {
        let from = format!("/home/{}/Code-Fight/scala/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/scala/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        fs::copy(&from, &to);
        //Command::new("nosetests")
        //       .arg(&to)
        //       .spawn()
        //       .expect("cat error to start");

        let sleep_time = time::Duration::new(10, 0);;
        thread::sleep(sleep_time);

    }
}
<commit_msg>add scala support<commit_after>use std::{thread, time};
use std::fs;
use std::process::Command;
use std::path::Path;
use std::env;

pub struct Python {
    user: String,
    subject: String,
}

pub struct Scala {
    user: String,
    subject: String,
}

pub trait Lang {
    fn new(user: String, subject: String) -> Self;
    fn run_test(&self);
}

impl Lang for Python {
    fn new(user: String, subject: String) -> Python {
        Python { user: user, subject: subject}
    }

    fn run_test(&self) {
        let from = format!("/home/{}/Code-Fight/python/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/python/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);
        fs::copy(&from, &to);

        let result = Command::new("nosetests")
               .arg(&to)
               .output()
               .expect("cat error to start");

        println!("result: {:?}", &result);
        //let sleep_time = time::Duration::new(10, 0);;
        //thread::sleep(sleep_time);
    }
}

impl Lang for Scala {
    fn new(user: String, subject: String) -> Scala {
        Scala { user: user, subject: subject}
    }

    fn run_test(&self) {
        let from = format!("/home/{}/Code-Fight/scala/{}", self.user, self.subject);
        let to = format!("/test/{}/Code-Fight/scala/{}", self.user, self.subject);
        println!("from => {}, to => {}", &from, &to);

        fs::copy(&from, &to);

        let path = Path::new(&to);
        env::set_current_dir(&path).is_ok();

        let result = Command::new("sbt")
               .arg("test")
               .output()
               .expect("cat error to start");

        println!("result: {:?}", &result);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Entry point of thread panic, for details, see std::macros
#[macro_export]
#[allow_internal_unstable]
macro_rules! panic {
    () => (
        panic!("explicit panic")
    );
    ($msg:expr) => ({
        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
        $crate::panicking::panic(&_MSG_FILE_LINE)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        // The leading _'s are to avoid dead code warnings if this is
        // used inside a dead function. Just `#[allow(dead_code)]` is
        // insufficient, since the user may have
        // `#[forbid(dead_code)]` and which cannot be overridden.
        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
        $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
    });
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// This macro has a second version, where a custom panic message can be provided.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
///
/// fn some_computation() -> bool { true } // a very simple function
///
/// assert!(some_computation());
///
/// // assert with a custom message
/// let x = true;
/// assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert {
    ($cond:expr) => (
        if !$cond {
            panic!(concat!("assertion failed: ", stringify!($cond)))
        }
    );
    ($cond:expr, $($arg:tt)+) => (
        if !$cond {
            panic!($($arg)+)
        }
    );
}

/// Asserts that two expressions are equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// assert_eq!(a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
    ($left:expr , $right:expr) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion failed: `(left == right)` \
                           (left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
                }
            }
        }
    })
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Like `assert!`, this macro also has a second version, where a custom panic
/// message can be provided.
///
/// Unlike `assert!`, `debug_assert!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
///
/// fn some_expensive_computation() -> bool { true } // a very simple function
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// let x = true;
/// debug_assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
}

/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_eq!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}

/// Short circuiting evaluation on Err
///
/// `libstd` contains a more general `try!` macro that uses `From<E>`.
#[macro_export]
macro_rules! try {
    ($e:expr) => ({
        use $crate::result::Result::{Ok, Err};

        match $e {
            Ok(e) => e,
            Err(e) => return Err(e),
        }
    })
}

/// Use the `format!` syntax to write data into a buffer.
///
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
///
/// See [`std::fmt`][fmt] for more information on format syntax.
///
/// [fmt]: fmt/index.html
/// [write]: io/trait.Write.html
///
/// # Examples
///
/// ```
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// write!(&mut w, "test").unwrap();
/// write!(&mut w, "formatted {}", "arguments").unwrap();
///
/// assert_eq!(w, b"testformatted arguments");
/// ```
#[macro_export]
macro_rules! write {
    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
}

/// Use the `format!` syntax to write data into a buffer, appending a newline.
///
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
///
/// See [`std::fmt`][fmt] for more information on format syntax.
///
/// [fmt]: fmt/index.html
/// [write]: io/trait.Write.html
///
/// # Examples
///
/// ```
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// writeln!(&mut w, "test").unwrap();
/// writeln!(&mut w, "formatted {}", "arguments").unwrap();
///
/// assert_eq!(&w[..], "test\nformatted arguments\n".as_bytes());
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! writeln {
    ($dst:expr, $fmt:expr) => (
        write!($dst, concat!($fmt, "\n"))
    );
    ($dst:expr, $fmt:expr, $($arg:tt)*) => (
        write!($dst, concat!($fmt, "\n"), $($arg)*)
    );
}

/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```
/// fn foo(x: Option<i32>) {
///     match x {
///         Some(n) if n >= 0 => println!("Some(Non-negative)"),
///         Some(n) if n <  0 => println!("Some(Negative)"),
///         Some(_)           => unreachable!(), // compile error if commented out
///         None              => println!("None")
///     }
/// }
/// ```
///
/// Iterators:
///
/// ```
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
///     for i in 0.. {
///         if 3*i < i { panic!("u32 overflow"); }
///         if x < 3*i { return i-1; }
///     }
///     unreachable!();
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear",
           issue = "27701")]
macro_rules! unreachable {
    () => ({
        panic!("internal error: entered unreachable code")
    });
    ($msg:expr) => ({
        unreachable!("{}", $msg)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
    });
}

/// A standardized placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
///
/// This can be useful if you are prototyping and are just looking to have your
/// code typecheck, or if you're implementing a trait that requires multiple
/// methods, and you're only planning on using one of them.
///
/// # Examples
///
/// Here's an example of some in-progress code. We have a trait `Foo`:
///
/// ```
/// trait Foo {
///     fn bar(&self);
///     fn baz(&self);
/// }
/// ```
///
/// We want to implement `Foo` on one of our types, but we also want to work on
/// just `bar()` first. In order for our code to compile, we need to implement
/// `baz()`, so we can use `unimplemented!`:
///
/// ```
/// # trait Foo {
/// #     fn foo(&self);
/// #     fn bar(&self);
/// # }
/// struct MyStruct;
///
/// impl Foo for MyStruct {
///     fn foo(&self) {
///         // implementation goes here
///     }
///
///     fn bar(&self) {
///         // let's not worry about implementing bar() for now
///         unimplemented!();
///     }
/// }
///
/// fn main() {
///     let s = MyStruct;
///     s.foo();
///
///     // we aren't even using bar() yet, so this is fine.
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear",
           issue = "27701")]
macro_rules! unimplemented {
    () => (panic!("not yet implemented"))
}
<commit_msg>Allow none Sized types in assert_eq!<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Entry point of thread panic, for details, see std::macros
#[macro_export]
#[allow_internal_unstable]
macro_rules! panic {
    () => (
        panic!("explicit panic")
    );
    ($msg:expr) => ({
        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
        $crate::panicking::panic(&_MSG_FILE_LINE)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        // The leading _'s are to avoid dead code warnings if this is
        // used inside a dead function. Just `#[allow(dead_code)]` is
        // insufficient, since the user may have
        // `#[forbid(dead_code)]` and which cannot be overridden.
        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
        $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
    });
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// This macro has a second version, where a custom panic message can be provided.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
///
/// fn some_computation() -> bool { true } // a very simple function
///
/// assert!(some_computation());
///
/// // assert with a custom message
/// let x = true;
/// assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert {
    ($cond:expr) => (
        if !$cond {
            panic!(concat!("assertion failed: ", stringify!($cond)))
        }
    );
    ($cond:expr, $($arg:tt)+) => (
        if !$cond {
            panic!($($arg)+)
        }
    );
}

/// Asserts that two expressions are equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// assert_eq!(a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
    ($left:expr , $right:expr) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion failed: `(left == right)` \
                           (left: `{:?}`, right: `{:?}`)", left_val, right_val)
                }
            }
        }
    })
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Like `assert!`, this macro also has a second version, where a custom panic
/// message can be provided.
///
/// Unlike `assert!`, `debug_assert!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
///
/// fn some_expensive_computation() -> bool { true } // a very simple function
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// let x = true;
/// debug_assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
}

/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_eq!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}

/// Short circuiting evaluation on Err
///
/// `libstd` contains a more general `try!` macro that uses `From<E>`.
#[macro_export]
macro_rules! try {
    ($e:expr) => ({
        use $crate::result::Result::{Ok, Err};

        match $e {
            Ok(e) => e,
            Err(e) => return Err(e),
        }
    })
}

/// Use the `format!` syntax to write data into a buffer.
///
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
///
/// See [`std::fmt`][fmt] for more information on format syntax.
///
/// [fmt]: fmt/index.html
/// [write]: io/trait.Write.html
///
/// # Examples
///
/// ```
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// write!(&mut w, "test").unwrap();
/// write!(&mut w, "formatted {}", "arguments").unwrap();
///
/// assert_eq!(w, b"testformatted arguments");
/// ```
#[macro_export]
macro_rules! write {
    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
}

/// Use the `format!` syntax to write data into a buffer, appending a newline.
///
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
///
/// See [`std::fmt`][fmt] for more information on format syntax.
///
/// [fmt]: fmt/index.html
/// [write]: io/trait.Write.html
///
/// # Examples
///
/// ```
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// writeln!(&mut w, "test").unwrap();
/// writeln!(&mut w, "formatted {}", "arguments").unwrap();
///
/// assert_eq!(&w[..], "test\nformatted arguments\n".as_bytes());
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! writeln {
    ($dst:expr, $fmt:expr) => (
        write!($dst, concat!($fmt, "\n"))
    );
    ($dst:expr, $fmt:expr, $($arg:tt)*) => (
        write!($dst, concat!($fmt, "\n"), $($arg)*)
    );
}

/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```
/// fn foo(x: Option<i32>) {
///     match x {
///         Some(n) if n >= 0 => println!("Some(Non-negative)"),
///         Some(n) if n <  0 => println!("Some(Negative)"),
///         Some(_)           => unreachable!(), // compile error if commented out
///         None              => println!("None")
///     }
/// }
/// ```
///
/// Iterators:
///
/// ```
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
///     for i in 0.. {
///         if 3*i < i { panic!("u32 overflow"); }
///         if x < 3*i { return i-1; }
///     }
///     unreachable!();
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear",
           issue = "27701")]
macro_rules! unreachable {
    () => ({
        panic!("internal error: entered unreachable code")
    });
    ($msg:expr) => ({
        unreachable!("{}", $msg)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
    });
}

/// A standardized placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
///
/// This can be useful if you are prototyping and are just looking to have your
/// code typecheck, or if you're implementing a trait that requires multiple
/// methods, and you're only planning on using one of them.
///
/// # Examples
///
/// Here's an example of some in-progress code. We have a trait `Foo`:
///
/// ```
/// trait Foo {
///     fn bar(&self);
///     fn baz(&self);
/// }
/// ```
///
/// We want to implement `Foo` on one of our types, but we also want to work on
/// just `bar()` first. In order for our code to compile, we need to implement
/// `baz()`, so we can use `unimplemented!`:
///
/// ```
/// # trait Foo {
/// #     fn foo(&self);
/// #     fn bar(&self);
/// # }
/// struct MyStruct;
///
/// impl Foo for MyStruct {
///     fn foo(&self) {
///         // implementation goes here
///     }
///
///     fn bar(&self) {
///         // let's not worry about implementing bar() for now
///         unimplemented!();
///     }
/// }
///
/// fn main() {
///     let s = MyStruct;
///     s.foo();
///
///     // we aren't even using bar() yet, so this is fine.
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear",
           issue = "27701")]
macro_rules! unimplemented {
    () => (panic!("not yet implemented"))
}
<|endoftext|>


<commit_before>//! Binding Rust with Python, both ways!
//!
//! This library will generate and handle type conversions between Python and
//! Rust. To use Python from Rust refer to the
//! [library wiki](https://github.com/iduartgomez/rustypy/wiki), more general examples
//! and information on how to use Rust in Python can also be found there.
//!
//! Checkout the [PyTypes](../rustypy/pytypes/index.html) module documentation for more information
//! on how to write foreign functions that are compliant with Python as well as using the custom
//! types that will ease type conversion.
#![crate_type = "cdylib"]

extern crate cpython;
extern crate libc;
extern crate syn;
extern crate walkdir;

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::ptr;

use libc::size_t;

mod macros;
pub mod pytypes;

// re-export
pub use self::pytypes::pybool::PyBool;
pub use self::pytypes::pydict::PyDict;
pub use self::pytypes::pylist::PyList;
pub use self::pytypes::pystring::PyString;
pub use self::pytypes::pytuple::PyTuple;
pub use self::pytypes::PyArg;

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn parse_src(
    path: *mut PyString,
    krate_data: &mut KrateData,
) -> *mut PyString {
    let path = PyString::from_ptr_to_string(path);
    let path: &Path = path.as_ref();
    let dir = if let Some(parent) = path.parent() {
        parent
    } else {
        // unlikely this happens, but just in case
        return PyString::from("crate in root directory not allowed".to_string()).into_raw();
    };
    for entry in walkdir::WalkDir::new(dir)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| {
            if let Some(ext) = e.path().extension() {
                ext == "rs"
            } else {
                false
            }
        })
    {
        if let Err(err) = parse_file(krate_data, entry.path()) {
            return err;
        }
    }
    ptr::null_mut::<PyString>()
}

fn parse_file(krate_data: &mut KrateData, path: &Path) -> Result<(), *mut PyString> {
    let mut f = match File::open(path) {
        Ok(file) => file,
        Err(_) => {
            return Err(
                PyString::from(format!("path not found: {}", path.to_str().unwrap())).into_raw(),
            )
        }
    };
    let mut src = String::new();
    if f.read_to_string(&mut src).is_err() {
        return Err(PyString::from(format!(
            "failed to read the source file: {}",
            path.to_str().unwrap()
        ))
        .into_raw());
    }
    eprintln!("{}", src);
    match syn::parse_file(&src) {
        Ok(krate) => {
            syn::visit::visit_file(krate_data, &krate);
            krate_data.collect_values();
            if krate_data.collected.is_empty() {
                return Err(PyString::from("zero function calls parsed".to_string()).into_raw());
            }
        }
        Err(err) => return Err(PyString::from(format!("{}", err)).into_raw()),
    };
    Ok(())
}

#[doc(hidden)]
pub struct KrateData {
    functions: Vec<FnDef>,
    collected: Vec<String>,
    prefixes: Vec<String>,
}

impl KrateData {
    fn new(prefixes: Vec<String>) -> KrateData {
        KrateData {
            functions: vec![],
            collected: vec![],
            prefixes,
        }
    }

    fn collect_values(&mut self) {
        let mut add = true;
        for v in self.functions.drain(..) {
            let FnDef {
                name: mut fndef,
                args,
                output,
            } = v;
            if !args.is_empty() {
                fndef.push_str("::");
                args.iter().fold(&mut fndef, |acc, arg| {
                    if let Ok(repr) = type_repr(arg, None) {
                        acc.push_str(&repr);
                        acc.push(';');
                    } else {
                        add = false;
                    }
                    acc
                });
            }
            if add {
                match output {
                    syn::ReturnType::Default => fndef.push_str("type(void)"),
                    syn::ReturnType::Type(_, ty) => {
                        if let Ok(ty) = type_repr(&ty, None) {
                            fndef.push_str(&ty)
                        } else {
                            continue;
                        }
                    }
                }
                self.collected.push(fndef);
            } else {
                add = true
            }
        }
    }

    fn add_fn(&mut self, name: String, fn_decl: &syn::ItemFn) {
        for prefix in &self.prefixes {
            if name.starts_with(prefix) {
                let syn::ItemFn { sig, .. } = fn_decl.clone();
                let mut args = vec![];
                for arg in sig.inputs {
                    match arg {
                        syn::FnArg::Typed(pat_ty) => args.push(*pat_ty.ty),
                        _ => continue,
                    }
                }
                self.functions.push(FnDef {
                    name,
                    args,
                    output: sig.output,
                });
                break;
            }
        }
    }

    fn iter_krate(&self, idx: usize) -> Option<&str> {
        if self.collected.len() >= (idx + 1) {
            Some(&self.collected[idx])
        } else {
            None
        }
    }
}

fn type_repr(ty: &syn::Type, r: Option<&str>) -> Result<String, ()> {
    let mut repr = String::new();
    match ty {
        syn::Type::Path(path) => {
            let syn::TypePath { path, .. } = path;
            if let Some(ty) = path.segments.last() {
                if let Some(r) = r {
                    Ok(format!("type({} {})", r, ty.ident))
                } else {
                    Ok(format!("type({})", ty.ident))
                }
            } else {
                Err(())
            }
        }
        syn::Type::Ptr(ty) => {
            let syn::TypePtr {
                elem, mutability, ..
            } = ty;
            let m = match mutability {
                Some(_) => "*mut",
                _ => "*const",
            };
            repr.push_str(&type_repr(&*elem, Some(m))?);
            Ok(repr)
        }
        syn::Type::Reference(ty) => {
            let syn::TypeReference {
                elem, mutability, ..
            } = ty;
            let m = match mutability {
                Some(_) => "&mut",
                _ => "&",
            };
            repr.push_str(&type_repr(&*elem, Some(m))?);
            Ok(repr)
        }
        _ => Err(()),
    }
}

impl<'ast> syn::visit::Visit<'ast> for KrateData {
    fn visit_item(&mut self, item: &syn::Item) {
        match item {
            syn::Item::Fn(fn_decl, ..) => {
                if let syn::Visibility::Public(_) = fn_decl.vis {
                    let name = format!("{}", fn_decl.sig.ident);
                    self.add_fn(name, &*fn_decl)
                }
            }
            syn::Item::Mod(mod_item) if mod_item.content.is_some() => {
                for item in &mod_item.content.as_ref().unwrap().1 {
                    self.visit_item(item);
                }
            }
            _ => {}
        }
    }
}

struct FnDef {
    name: String,
    output: syn::ReturnType,
    args: Vec<syn::Type>,
}

// C FFI for KrateData objects:
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn krate_data_new(ptr: *mut PyList) -> *mut KrateData {
    let p = PyList::from_ptr(ptr);
    let p: Vec<String> = PyList::into(p);
    Box::into_raw(Box::new(KrateData::new(p)))
}

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn krate_data_free(ptr: *mut KrateData) {
    if ptr.is_null() {
        return;
    }
    Box::from_raw(ptr);
}

#[doc(hidden)]
#[no_mangle]
pub extern "C" fn krate_data_len(krate: &KrateData) -> size_t {
    krate.collected.len()
}

#[doc(hidden)]
#[no_mangle]
pub extern "C" fn krate_data_iter(krate: &KrateData, idx: size_t) -> *mut PyString {
    match krate.iter_krate(idx as usize) {
        Some(val) => PyString::from(val).into_raw(),
        None => PyString::from("NO_IDX_ERROR").into_raw(),
    }
}

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

    #[test]
    #[ignore]
    fn parse_lib() {
        let path = std::env::home_dir()
            .unwrap()
            .join("workspace/sources/rustypy_debug/rust_code/src/lib.rs");
        // the entry point to the library:
        let entry_point = PyString::from(path.to_str().unwrap().to_string()).into_raw();
        let mut krate_data = KrateData::new(vec![]);
        unsafe {
            let response = parse_src(entry_point, &mut krate_data);
            let response: String = PyString::from_ptr_to_string(response);
            assert!(!response.is_empty());
        }
    }
}
<commit_msg>Remove debug print line<commit_after>//! Binding Rust with Python, both ways!
//!
//! This library will generate and handle type conversions between Python and
//! Rust. To use Python from Rust refer to the
//! [library wiki](https://github.com/iduartgomez/rustypy/wiki), more general examples
//! and information on how to use Rust in Python can also be found there.
//!
//! Checkout the [PyTypes](../rustypy/pytypes/index.html) module documentation for more information
//! on how to write foreign functions that are compliant with Python as well as using the custom
//! types that will ease type conversion.
#![crate_type = "cdylib"]

extern crate cpython;
extern crate libc;
extern crate syn;
extern crate walkdir;

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::ptr;

use libc::size_t;

mod macros;
pub mod pytypes;

// re-export
pub use self::pytypes::pybool::PyBool;
pub use self::pytypes::pydict::PyDict;
pub use self::pytypes::pylist::PyList;
pub use self::pytypes::pystring::PyString;
pub use self::pytypes::pytuple::PyTuple;
pub use self::pytypes::PyArg;

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn parse_src(
    path: *mut PyString,
    krate_data: &mut KrateData,
) -> *mut PyString {
    let path = PyString::from_ptr_to_string(path);
    let path: &Path = path.as_ref();
    let dir = if let Some(parent) = path.parent() {
        parent
    } else {
        // unlikely this happens, but just in case
        return PyString::from("crate in root directory not allowed".to_string()).into_raw();
    };
    for entry in walkdir::WalkDir::new(dir)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| {
            if let Some(ext) = e.path().extension() {
                ext == "rs"
            } else {
                false
            }
        })
    {
        if let Err(err) = parse_file(krate_data, entry.path()) {
            return err;
        }
    }
    ptr::null_mut::<PyString>()
}

fn parse_file(krate_data: &mut KrateData, path: &Path) -> Result<(), *mut PyString> {
    let mut f = match File::open(path) {
        Ok(file) => file,
        Err(_) => {
            return Err(
                PyString::from(format!("path not found: {}", path.to_str().unwrap())).into_raw(),
            )
        }
    };
    let mut src = String::new();
    if f.read_to_string(&mut src).is_err() {
        return Err(PyString::from(format!(
            "failed to read the source file: {}",
            path.to_str().unwrap()
        ))
        .into_raw());
    }
    // eprintln!("{}", src);
    match syn::parse_file(&src) {
        Ok(krate) => {
            syn::visit::visit_file(krate_data, &krate);
            krate_data.collect_values();
            if krate_data.collected.is_empty() {
                return Err(PyString::from("zero function calls parsed".to_string()).into_raw());
            }
        }
        Err(err) => return Err(PyString::from(format!("{}", err)).into_raw()),
    };
    Ok(())
}

#[doc(hidden)]
pub struct KrateData {
    functions: Vec<FnDef>,
    collected: Vec<String>,
    prefixes: Vec<String>,
}

impl KrateData {
    fn new(prefixes: Vec<String>) -> KrateData {
        KrateData {
            functions: vec![],
            collected: vec![],
            prefixes,
        }
    }

    fn collect_values(&mut self) {
        let mut add = true;
        for v in self.functions.drain(..) {
            let FnDef {
                name: mut fndef,
                args,
                output,
            } = v;
            if !args.is_empty() {
                fndef.push_str("::");
                args.iter().fold(&mut fndef, |acc, arg| {
                    if let Ok(repr) = type_repr(arg, None) {
                        acc.push_str(&repr);
                        acc.push(';');
                    } else {
                        add = false;
                    }
                    acc
                });
            }
            if add {
                match output {
                    syn::ReturnType::Default => fndef.push_str("type(void)"),
                    syn::ReturnType::Type(_, ty) => {
                        if let Ok(ty) = type_repr(&ty, None) {
                            fndef.push_str(&ty)
                        } else {
                            continue;
                        }
                    }
                }
                self.collected.push(fndef);
            } else {
                add = true
            }
        }
    }

    fn add_fn(&mut self, name: String, fn_decl: &syn::ItemFn) {
        for prefix in &self.prefixes {
            if name.starts_with(prefix) {
                let syn::ItemFn { sig, .. } = fn_decl.clone();
                let mut args = vec![];
                for arg in sig.inputs {
                    match arg {
                        syn::FnArg::Typed(pat_ty) => args.push(*pat_ty.ty),
                        _ => continue,
                    }
                }
                self.functions.push(FnDef {
                    name,
                    args,
                    output: sig.output,
                });
                break;
            }
        }
    }

    fn iter_krate(&self, idx: usize) -> Option<&str> {
        if self.collected.len() >= (idx + 1) {
            Some(&self.collected[idx])
        } else {
            None
        }
    }
}

fn type_repr(ty: &syn::Type, r: Option<&str>) -> Result<String, ()> {
    let mut repr = String::new();
    match ty {
        syn::Type::Path(path) => {
            let syn::TypePath { path, .. } = path;
            if let Some(ty) = path.segments.last() {
                if let Some(r) = r {
                    Ok(format!("type({} {})", r, ty.ident))
                } else {
                    Ok(format!("type({})", ty.ident))
                }
            } else {
                Err(())
            }
        }
        syn::Type::Ptr(ty) => {
            let syn::TypePtr {
                elem, mutability, ..
            } = ty;
            let m = match mutability {
                Some(_) => "*mut",
                _ => "*const",
            };
            repr.push_str(&type_repr(&*elem, Some(m))?);
            Ok(repr)
        }
        syn::Type::Reference(ty) => {
            let syn::TypeReference {
                elem, mutability, ..
            } = ty;
            let m = match mutability {
                Some(_) => "&mut",
                _ => "&",
            };
            repr.push_str(&type_repr(&*elem, Some(m))?);
            Ok(repr)
        }
        _ => Err(()),
    }
}

impl<'ast> syn::visit::Visit<'ast> for KrateData {
    fn visit_item(&mut self, item: &syn::Item) {
        match item {
            syn::Item::Fn(fn_decl, ..) => {
                if let syn::Visibility::Public(_) = fn_decl.vis {
                    let name = format!("{}", fn_decl.sig.ident);
                    self.add_fn(name, &*fn_decl)
                }
            }
            syn::Item::Mod(mod_item) if mod_item.content.is_some() => {
                for item in &mod_item.content.as_ref().unwrap().1 {
                    self.visit_item(item);
                }
            }
            _ => {}
        }
    }
}

struct FnDef {
    name: String,
    output: syn::ReturnType,
    args: Vec<syn::Type>,
}

// C FFI for KrateData objects:
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn krate_data_new(ptr: *mut PyList) -> *mut KrateData {
    let p = PyList::from_ptr(ptr);
    let p: Vec<String> = PyList::into(p);
    Box::into_raw(Box::new(KrateData::new(p)))
}

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn krate_data_free(ptr: *mut KrateData) {
    if ptr.is_null() {
        return;
    }
    Box::from_raw(ptr);
}

#[doc(hidden)]
#[no_mangle]
pub extern "C" fn krate_data_len(krate: &KrateData) -> size_t {
    krate.collected.len()
}

#[doc(hidden)]
#[no_mangle]
pub extern "C" fn krate_data_iter(krate: &KrateData, idx: size_t) -> *mut PyString {
    match krate.iter_krate(idx as usize) {
        Some(val) => PyString::from(val).into_raw(),
        None => PyString::from("NO_IDX_ERROR").into_raw(),
    }
}

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

    #[test]
    #[ignore]
    fn parse_lib() {
        let path = std::env::home_dir()
            .unwrap()
            .join("workspace/sources/rustypy_debug/rust_code/src/lib.rs");
        // the entry point to the library:
        let entry_point = PyString::from(path.to_str().unwrap().to_string()).into_raw();
        let mut krate_data = KrateData::new(vec![]);
        unsafe {
            let response = parse_src(entry_point, &mut krate_data);
            let response: String = PyString::from_ptr_to_string(response);
            assert!(!response.is_empty());
        }
    }
}
<|endoftext|>