<commit_before>#![allow(dead_code)]
extern crate polydraw;

use std::i64;
use std::cmp::min;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::geom::ring::Ring;
use polydraw::draw::RGB;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Poly {
   color: RGB,
   start: usize,
   end: usize,
}

impl Poly {
   #[inline]
   pub fn new(color: RGB, start: usize, end: usize) -> Self {
      Poly {
         color: color,
         start: start,
         end: end,
      }
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Edge {
   Inclined(usize),
   InclinedRev(usize),
   Horizontal(i64),
   HorizontalRev(i64),
   Vertical(i64),
   VerticalRev(i64),
}

impl Default for Edge {
   #[inline]
   fn default() -> Edge {
      Edge::Inclined(0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct InclinedEdge {
   p1: usize,
   p2: usize,
}

impl InclinedEdge {
   #[inline]
   pub fn new(p1: usize, p2: usize) -> Self {
      InclinedEdge {
         p1: p1,
         p2: p2,
      }
   }
}

impl Default for InclinedEdge {
   #[inline]
   fn default() -> InclinedEdge {
      InclinedEdge::new(0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyRef {
   src: usize,
   start: usize,
   end: usize,
}

impl PolyRef {
   #[inline]
   pub fn new(src: usize, start: usize, end: usize) -> Self {
      PolyRef {
         src: src,
         start: start,
         end: end,
      }
   }
}

impl Default for PolyRef {
   #[inline]
   fn default() -> PolyRef {
      PolyRef::new(0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct InclinedEdgeRef {
   p1: usize,
   p2: usize,
   src_p1: usize,
   src_p2: usize,
}

impl InclinedEdgeRef {
   #[inline]
   pub fn new(p1: usize, p2: usize, src_p1: usize, src_p2: usize) -> Self {
      InclinedEdgeRef {
         p1: p1,
         p2: p2,
         src_p1: src_p1,
         src_p2: src_p2,
      }
   }
}

impl Default for InclinedEdgeRef {
   #[inline]
   fn default() -> InclinedEdgeRef {
      InclinedEdgeRef::new(0, 0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyMinYRef {
   poly: usize,
   min_y: i64,
}

struct PolySource {
   polys: Vec<Poly>,
   edges: Vec<Edge>,
   inclined: Vec<InclinedEdge>,
   points: Vec<Point>,
}

impl PolySource {
   fn new() -> Self {
      let polys = vec![
         // A
         Poly::new(RGB::new(18, 78, 230), 0, 3),
         // B
         Poly::new(RGB::new(47, 11, 206), 3, 6),
         // C
         Poly::new(RGB::new(170, 44, 206), 6, 9),
         // D
         Poly::new(RGB::new(243, 0, 149), 9, 12),
         // E
         Poly::new(RGB::new(170, 36, 14), 12, 15),
         // F
         Poly::new(RGB::new(219, 65, 18), 15, 18),
         // G
         Poly::new(RGB::new(254, 185, 21), 18, 21),
         // H
         Poly::new(RGB::new(244, 239, 114), 21, 24),
         // I
         Poly::new(RGB::new(109, 233, 158), 24, 27),
         // J
         Poly::new(RGB::new(66, 222, 241), 27, 30),
      ];

      let edges = vec![
         // 0: A
         Edge::Vertical(0),
         Edge::InclinedRev(0),
         Edge::InclinedRev(1),

         // 1: B
         Edge::Inclined(1),
         Edge::InclinedRev(2),
         Edge::InclinedRev(3),

         // 2: C
         Edge::Inclined(3),
         Edge::InclinedRev(4),
         Edge::HorizontalRev(0),

         // 3: D
         Edge::Inclined(4),
         Edge::Inclined(5),
         Edge::InclinedRev(6),

         // 4: E
         Edge::Inclined(6),
         Edge::Inclined(7),
         Edge::VerticalRev(10),

         // 5: F
         Edge::Inclined(2),
         Edge::Inclined(8),
         Edge::InclinedRev(9),

         // 6: G
         Edge::Inclined(9),
         Edge::InclinedRev(10),
         Edge::InclinedRev(5),

         // 7: H
         Edge::Inclined(0),
         Edge::InclinedRev(11),
         Edge::InclinedRev(8),

         // 8: I
         Edge::Inclined(10),
         Edge::Inclined(12),
         Edge::InclinedRev(7),

         // 9: J
         Edge::Inclined(11),
         Edge::Horizontal(10),
         Edge::InclinedRev(12),
      ];

      let inclined = vec![
         InclinedEdge::new(2, 1),  // 0
         InclinedEdge::new(0, 2),  // 1
         InclinedEdge::new(3, 2),  // 2
         InclinedEdge::new(0, 3),  // 3
         InclinedEdge::new(4, 3),  // 4
         InclinedEdge::new(3, 5),  // 5
         InclinedEdge::new(4, 5),  // 6
         InclinedEdge::new(5, 6),  // 7
         InclinedEdge::new(2, 7),  // 8
         InclinedEdge::new(3, 7),  // 9
         InclinedEdge::new(5, 7),  // 10
         InclinedEdge::new(7, 1),  // 11
         InclinedEdge::new(7, 6),  // 12
      ];

      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(0, 10),  // 1
         Point::new(2, 5),   // 2
         Point::new(3, 1),   // 3
         Point::new(10, 0),  // 4
         Point::new(8, 5),   // 5
         Point::new(10, 10), // 6
         Point::new(7, 9),   // 7
      ];

      PolySource {
         polys: polys,
         edges: edges,
         inclined: inclined,
         points: points,
      }
   }

   pub fn polys_min_y(&self) -> Vec<PolyMinYRef> {
      let mut v = Vec::new();

      for (poly_index, poly) in self.polys.iter().enumerate() {
         let mut min_y = i64::MAX;

         for edge_index in poly.start..poly.end {
            let y = match self.edges[edge_index] {
               Edge::Inclined(i) => {
                  self.inclined_min_y(i)
               },
               Edge::InclinedRev(i) => {
                  self.inclined_min_y(i)
               },
               Edge::Horizontal(y) => {
                  y
               },
               Edge::HorizontalRev(y) => {
                  y
               },
               _ => {
                  continue;
               }
            };

            if y < min_y {
               min_y = y;
            }
         }

         v.push(PolyMinYRef {
            poly: poly_index,
            min_y: min_y,
         });
      }

      v.sort_by(|a, b| a.min_y.cmp(&b.min_y));

      v
   }

   #[inline]
   fn inclined_min_y(&self, i: usize) -> i64 {
      let inclined = self.inclined[i];
      min(
         self.points[inclined.p1].y,
         self.points[inclined.p2].y
      )
   }

   #[inline]
   fn min_max_x_y(&self) -> (i64, i64, i64, i64) {
      let mut min_x = i64::MAX;
      let mut max_x = i64::MIN;

      let mut min_y = i64::MAX;
      let mut max_y = i64::MIN;

      for p in &self.points {
         if p.x < min_x {
            min_x = p.x;
         }

         if p.x > max_x {
            max_x = p.x;
         }

         if p.y < min_y {
            min_y = p.y;
         }

         if p.y > max_y {
            max_y = p.y;
         }
      }

      (min_x, max_x, min_y, max_y)
   }
}

struct TriangleRenderer {
   src: PolySource,
   src_min_y: Vec<PolyMinYRef>,

   upper_polys: Ring<PolyRef>,
   upper_edges: Ring<Edge>,

   lower_polys: Ring<PolyRef>,
   lower_edges: Ring<Edge>,

   points: Ring<Point>,
   inclined: Ring<InclinedEdgeRef>,
}

impl TriangleRenderer {
   fn new() -> Self {
      let src = PolySource::new();
      let src_min_y = src.polys_min_y();

      TriangleRenderer {
         src: src,
         src_min_y: src_min_y,

         upper_polys: Ring::new(65536),
         upper_edges: Ring::new(262144),

         lower_polys: Ring::new(65536),
         lower_edges: Ring::new(262144),

         points: Ring::new(262144),
         inclined: Ring::new(262144),
      }
   }

   pub fn clear(&mut self) {
      self.upper_polys.clear();
      self.upper_edges.clear();

      self.lower_polys.clear();
      self.lower_edges.clear();

      self.points.clear();
      self.inclined.clear();
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.clear();
   }
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle3")
      .run();
}
<commit_msg>Improving the Edge model<commit_after>#![allow(dead_code)]
extern crate polydraw;

use std::i64;
use std::cmp::min;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::geom::ring::Ring;
use polydraw::draw::RGB;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Poly {
   color: RGB,
   start: usize,
   end: usize,
}

impl Poly {
   #[inline]
   pub fn new(color: RGB, start: usize, end: usize) -> Self {
      Poly {
         color: color,
         start: start,
         end: end,
      }
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum EdgeType {
   Inclined,
   InclinedRev,
   Horizontal,
   HorizontalRev,
   Vertical,
   VerticalRev,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Edge {
   etype: EdgeType,
   points: usize,
}

impl Edge {
   #[inline]
   pub fn new(etype: EdgeType, points: usize) -> Self {
      Edge {
         etype: etype,
         points: points,
      }
   }

   #[inline]
   pub fn inclined(points: usize) -> Self {
      Edge::new(EdgeType::Inclined, points)
   }

   #[inline]
   pub fn inclined_rev(points: usize) -> Self {
      Edge::new(EdgeType::InclinedRev, points)
   }

   #[inline]
   pub fn horizontal(points: usize) -> Self {
      Edge::new(EdgeType::Horizontal, points)
   }

   #[inline]
   pub fn horizontal_rev(points: usize) -> Self {
      Edge::new(EdgeType::HorizontalRev, points)
   }

   #[inline]
   pub fn vertical(points: usize) -> Self {
      Edge::new(EdgeType::Vertical, points)
   }

   #[inline]
   pub fn vertical_rev(points: usize) -> Self {
      Edge::new(EdgeType::VerticalRev, points)
   }
}

impl Default for Edge {
   #[inline]
   fn default() -> Edge {
      Edge::inclined(0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct EdgePoints {
   p1: usize,
   p2: usize,
}

impl EdgePoints {
   #[inline]
   pub fn new(p1: usize, p2: usize) -> Self {
      EdgePoints {
         p1: p1,
         p2: p2,
      }
   }
}

impl Default for EdgePoints {
   #[inline]
   fn default() -> EdgePoints {
      EdgePoints::new(0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct EdgePointsRef {
   p1: usize,
   p2: usize,
   src_p1: usize,
   src_p2: usize,
}

impl EdgePointsRef {
   #[inline]
   pub fn new(p1: usize, p2: usize, src_p1: usize, src_p2: usize) -> Self {
      EdgePointsRef {
         p1: p1,
         p2: p2,
         src_p1: src_p1,
         src_p2: src_p2,
      }
   }
}

impl Default for EdgePointsRef {
   #[inline]
   fn default() -> EdgePointsRef {
      EdgePointsRef::new(0, 0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyRef {
   src: usize,
   start: usize,
   end: usize,
}

impl PolyRef {
   #[inline]
   pub fn new(src: usize, start: usize, end: usize) -> Self {
      PolyRef {
         src: src,
         start: start,
         end: end,
      }
   }
}

impl Default for PolyRef {
   #[inline]
   fn default() -> PolyRef {
      PolyRef::new(0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyMinYRef {
   poly: usize,
   min_y: i64,
}

struct PolySource {
   polys: Vec<Poly>,
   edges: Vec<Edge>,
   edge_points: Vec<EdgePoints>,
   points: Vec<Point>,
}

impl PolySource {
   fn new() -> Self {
      let polys = vec![
         // A
         Poly::new(RGB::new(18, 78, 230), 0, 3),
         // B
         Poly::new(RGB::new(47, 11, 206), 3, 6),
         // C
         Poly::new(RGB::new(170, 44, 206), 6, 9),
         // D
         Poly::new(RGB::new(243, 0, 149), 9, 12),
         // E
         Poly::new(RGB::new(170, 36, 14), 12, 15),
         // F
         Poly::new(RGB::new(219, 65, 18), 15, 18),
         // G
         Poly::new(RGB::new(254, 185, 21), 18, 21),
         // H
         Poly::new(RGB::new(244, 239, 114), 21, 24),
         // I
         Poly::new(RGB::new(109, 233, 158), 24, 27),
         // J
         Poly::new(RGB::new(66, 222, 241), 27, 30),
      ];

      let edges = vec![
         // 0: A
         Edge::vertical(13),
         Edge::inclined_rev(0),
         Edge::inclined_rev(1),

         // 1: B
         Edge::inclined(1),
         Edge::inclined_rev(2),
         Edge::inclined_rev(3),

         // 2: C
         Edge::inclined(3),
         Edge::inclined_rev(4),
         Edge::horizontal_rev(14),

         // 3: D
         Edge::inclined(4),
         Edge::inclined(5),
         Edge::inclined_rev(6),

         // 4: E
         Edge::inclined(6),
         Edge::inclined(7),
         Edge::vertical_rev(15),

         // 5: F
         Edge::inclined(2),
         Edge::inclined(8),
         Edge::inclined_rev(9),

         // 6: G
         Edge::inclined(9),
         Edge::inclined_rev(10),
         Edge::inclined_rev(5),

         // 7: H
         Edge::inclined(0),
         Edge::inclined_rev(11),
         Edge::inclined_rev(8),

         // 8: I
         Edge::inclined(10),
         Edge::inclined(12),
         Edge::inclined_rev(7),

         // 9: J
         Edge::inclined(11),
         Edge::horizontal(16),
         Edge::inclined_rev(12),
      ];

      let edge_points = vec![
         EdgePoints::new(2, 1),  // 0
         EdgePoints::new(0, 2),  // 1
         EdgePoints::new(3, 2),  // 2
         EdgePoints::new(0, 3),  // 3
         EdgePoints::new(4, 3),  // 4
         EdgePoints::new(3, 5),  // 5
         EdgePoints::new(4, 5),  // 6
         EdgePoints::new(5, 6),  // 7
         EdgePoints::new(2, 7),  // 8
         EdgePoints::new(3, 7),  // 9
         EdgePoints::new(5, 7),  // 10
         EdgePoints::new(7, 1),  // 11
         EdgePoints::new(7, 6),  // 12
         EdgePoints::new(0, 1),  // 13
         EdgePoints::new(0, 4),  // 14
         EdgePoints::new(4, 6),  // 15
         EdgePoints::new(1, 6),  // 16
      ];

      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(0, 10),  // 1
         Point::new(2, 5),   // 2
         Point::new(3, 1),   // 3
         Point::new(10, 0),  // 4
         Point::new(8, 5),   // 5
         Point::new(10, 10), // 6
         Point::new(7, 9),   // 7
      ];

      PolySource {
         polys: polys,
         edges: edges,
         edge_points: edge_points,
         points: points,
      }
   }

   pub fn polys_min_y(&self) -> Vec<PolyMinYRef> {
      let mut v = Vec::new();

      for (poly_index, poly) in self.polys.iter().enumerate() {
         let mut min_y = i64::MAX;

         for edge_index in poly.start..poly.end {
            let edge_points = self.edge_points[self.edges[edge_index].points];
            let y = min(
               self.points[edge_points.p1].y,
               self.points[edge_points.p2].y
            );

            if y < min_y {
               min_y = y;
            }
         }

         v.push(PolyMinYRef {
            poly: poly_index,
            min_y: min_y,
         });
      }

      v.sort_by(|a, b| a.min_y.cmp(&b.min_y));

      v
   }

   #[inline]
   fn min_max_x_y(&self) -> (i64, i64, i64, i64) {
      let mut min_x = i64::MAX;
      let mut max_x = i64::MIN;

      let mut min_y = i64::MAX;
      let mut max_y = i64::MIN;

      for p in &self.points {
         if p.x < min_x {
            min_x = p.x;
         }

         if p.x > max_x {
            max_x = p.x;
         }

         if p.y < min_y {
            min_y = p.y;
         }

         if p.y > max_y {
            max_y = p.y;
         }
      }

      (min_x, max_x, min_y, max_y)
   }
}

struct TriangleRenderer {
   src: PolySource,
   src_min_y: Vec<PolyMinYRef>,

   upper_polys: Ring<PolyRef>,
   upper_edges: Ring<Edge>,

   lower_polys: Ring<PolyRef>,
   lower_edges: Ring<Edge>,

   edge_points: Ring<EdgePointsRef>,
   points: Ring<Point>,
}

impl TriangleRenderer {
   fn new() -> Self {
      let src = PolySource::new();
      let src_min_y = src.polys_min_y();

      TriangleRenderer {
         src: src,
         src_min_y: src_min_y,

         upper_polys: Ring::new(65536),
         upper_edges: Ring::new(262144),

         lower_polys: Ring::new(65536),
         lower_edges: Ring::new(262144),

         edge_points: Ring::new(262144),
         points: Ring::new(262144),
      }
   }

   pub fn clear(&mut self) {
      self.upper_polys.clear();
      self.upper_edges.clear();

      self.lower_polys.clear();
      self.lower_edges.clear();

      self.edge_points.clear();
      self.points.clear();
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.clear();
   }
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle3")
      .run();
}
<|endoftext|>


<commit_before>mod http;
mod udp;

use std::sync::{mpsc, atomic};
use byteorder::{BigEndian, ReadBytesExt};
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::thread;
use {CONTROL, PORT};
use torrent::Torrent;
use bencode::BEncode;
use url::Url;

pub struct Tracker {
    queue: mpsc::Receiver<Request>,
    http: http::Announcer,
    udp: udp::Announcer,
}

impl Tracker {
    pub fn new(queue: mpsc::Receiver<Request>) -> Tracker {
        Tracker {
            queue,
            http: http::Announcer::new(),
            udp: udp::Announcer::new(),
        }
    }

    pub fn run(&mut self) {
        loop {
            if let Ok(req) = self.queue.recv() {
                let id = req.id;
                let response = if let Ok(url) = Url::parse(&req.url) {
                    match url.scheme() {
                        "http" => self.http.announce(req),
                        "udp" => self.udp.announce(req),
                        _ => Err(TrackerError::InvalidURL),
                    }
                } else {
                    Err(TrackerError::InvalidURL)
                };
                CONTROL.trk_tx.lock().unwrap().send((id, response)).unwrap();
            } else {
                break;
            }
        }
    }
}

pub struct Handle {
    pub tx: mpsc::Sender<Request>,
}

impl Handle {
    pub fn get(&self) -> mpsc::Sender<Request> {
        self.tx.clone()
    }
}

unsafe impl Sync for Handle {}

#[derive(Debug)]
pub struct Request {
    id: usize,
    url: String,
    hash: [u8; 20],
    port: u16,
    uploaded: usize,
    downloaded: usize,
    left: usize,
    event: Option<Event>,
}

impl Request {
    pub fn new(torrent: &Torrent, event: Option<Event>) -> Request {
        Request {
            id: torrent.id,
            url: torrent.info.announce.clone(),
            hash: torrent.info.hash,
            port: PORT.load(atomic::Ordering::Relaxed) as u16,
            uploaded: torrent.uploaded,
            downloaded: torrent.downloaded,
            left: torrent.info.total_len - torrent.downloaded,
            event,
        }
    }

    pub fn started(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Started))
    }

    pub fn stopped(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Started))
    }

    pub fn completed(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Completed))
    }

    pub fn interval(torrent: &Torrent) -> Request {
        Request::new(torrent, None)
    }
}

#[derive(Debug)]
pub enum Event {
    Started,
    Stopped,
    Completed,
}

pub type Response = (usize, TrackerRes);
pub type TrackerRes = Result<TrackerResponse, TrackerError>;

#[derive(Clone, Debug)]
pub enum TrackerError {
    Error(String),
    InvalidURL,
    ConnectionFailure,
    InvalidResponse(&'static str),
}

#[derive(Debug)]
pub struct TrackerResponse {
    pub peers: Vec<SocketAddr>,
    pub interval: u32,
    pub leechers: u32,
    pub seeders: u32,
}

impl TrackerResponse {
    pub fn empty() -> TrackerResponse {
        TrackerResponse {
            peers: vec![],
            interval: 900,
            leechers: 0,
            seeders: 0,
        }
    }

    pub fn from_bencode(data: BEncode) -> TrackerRes {
        let mut d = data.to_dict().ok_or(TrackerError::InvalidResponse("File must be a dictionary type!"))?;
        match d.remove("failure_reason") {
            Some(BEncode::String(data)) => {
                return Err(TrackerError::Error(String::from_utf8(data).map_err(|_| TrackerError::InvalidResponse("Failure reason must be UTF8!"))?));
            }
            _ => { }
        }
        let mut resp = TrackerResponse::empty();
        match d.remove("peers") {
            Some(BEncode::String(ref data)) => {
                for p in data.chunks(6) {
                    let ip = Ipv4Addr::new(p[0], p[1], p[2], p[3]);
                    let socket = SocketAddrV4::new(ip, (&p[4..]).read_u16::<BigEndian>().unwrap());
                    resp.peers.push(SocketAddr::V4(socket));
                }
            }
            _ => {
                return Err(TrackerError::InvalidResponse("Response must have peers field!"));
            }
        };
        match d.remove("interval") {
            Some(BEncode::Int(ref i)) => {
                resp.interval = *i as u32;
            }
            _ => {
                return Err(TrackerError::InvalidResponse("Response must have interval!"));
            }
        };
        Ok(resp)
    }
}

pub fn start() -> Handle {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let mut d = Tracker::new(rx);
        d.run();
    });
    Handle { tx }
}
<commit_msg>Properly report tracker upload and download<commit_after>mod http;
mod udp;

use std::sync::{mpsc, atomic};
use byteorder::{BigEndian, ReadBytesExt};
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::thread;
use {CONTROL, PORT};
use torrent::Torrent;
use bencode::BEncode;
use url::Url;

pub struct Tracker {
    queue: mpsc::Receiver<Request>,
    http: http::Announcer,
    udp: udp::Announcer,
}

impl Tracker {
    pub fn new(queue: mpsc::Receiver<Request>) -> Tracker {
        Tracker {
            queue,
            http: http::Announcer::new(),
            udp: udp::Announcer::new(),
        }
    }

    pub fn run(&mut self) {
        loop {
            if let Ok(req) = self.queue.recv() {
                let id = req.id;
                let response = if let Ok(url) = Url::parse(&req.url) {
                    match url.scheme() {
                        "http" => self.http.announce(req),
                        "udp" => self.udp.announce(req),
                        _ => Err(TrackerError::InvalidURL),
                    }
                } else {
                    Err(TrackerError::InvalidURL)
                };
                CONTROL.trk_tx.lock().unwrap().send((id, response)).unwrap();
            } else {
                break;
            }
        }
    }
}

pub struct Handle {
    pub tx: mpsc::Sender<Request>,
}

impl Handle {
    pub fn get(&self) -> mpsc::Sender<Request> {
        self.tx.clone()
    }
}

unsafe impl Sync for Handle {}

#[derive(Debug)]
pub struct Request {
    id: usize,
    url: String,
    hash: [u8; 20],
    port: u16,
    uploaded: u64,
    downloaded: u64,
    left: usize,
    event: Option<Event>,
}

impl Request {
    pub fn new(torrent: &Torrent, event: Option<Event>) -> Request {
        Request {
            id: torrent.id,
            url: torrent.info.announce.clone(),
            hash: torrent.info.hash,
            port: PORT.load(atomic::Ordering::Relaxed) as u16,
            uploaded: torrent.uploaded as u64 * torrent.info.piece_len as u64,
            downloaded: torrent.downloaded as u64 * torrent.info.piece_len as u64,
            left: torrent.info.total_len - torrent.downloaded,
            event,
        }
    }

    pub fn started(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Started))
    }

    pub fn stopped(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Started))
    }

    pub fn completed(torrent: &Torrent) -> Request {
        Request::new(torrent, Some(Event::Completed))
    }

    pub fn interval(torrent: &Torrent) -> Request {
        Request::new(torrent, None)
    }
}

#[derive(Debug)]
pub enum Event {
    Started,
    Stopped,
    Completed,
}

pub type Response = (usize, TrackerRes);
pub type TrackerRes = Result<TrackerResponse, TrackerError>;

#[derive(Clone, Debug)]
pub enum TrackerError {
    Error(String),
    InvalidURL,
    ConnectionFailure,
    InvalidResponse(&'static str),
}

#[derive(Debug)]
pub struct TrackerResponse {
    pub peers: Vec<SocketAddr>,
    pub interval: u32,
    pub leechers: u32,
    pub seeders: u32,
}

impl TrackerResponse {
    pub fn empty() -> TrackerResponse {
        TrackerResponse {
            peers: vec![],
            interval: 900,
            leechers: 0,
            seeders: 0,
        }
    }

    pub fn from_bencode(data: BEncode) -> TrackerRes {
        let mut d = data.to_dict().ok_or(TrackerError::InvalidResponse("Tracker response must be a dictionary type!"))?;
        match d.remove("failure_reason") {
            Some(BEncode::String(data)) => {
                return Err(TrackerError::Error(String::from_utf8(data).map_err(|_| TrackerError::InvalidResponse("Failure reason must be UTF8!"))?));
            }
            _ => { }
        }
        let mut resp = TrackerResponse::empty();
        match d.remove("peers") {
            Some(BEncode::String(ref data)) => {
                for p in data.chunks(6) {
                    let ip = Ipv4Addr::new(p[0], p[1], p[2], p[3]);
                    let socket = SocketAddrV4::new(ip, (&p[4..]).read_u16::<BigEndian>().unwrap());
                    resp.peers.push(SocketAddr::V4(socket));
                }
            }
            _ => {
                return Err(TrackerError::InvalidResponse("Response must have peers field!"));
            }
        };
        match d.remove("interval") {
            Some(BEncode::Int(ref i)) => {
                resp.interval = *i as u32;
            }
            _ => {
                return Err(TrackerError::InvalidResponse("Response must have interval!"));
            }
        };
        Ok(resp)
    }
}

pub fn start() -> Handle {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let mut d = Tracker::new(rx);
        d.run();
    });
    Handle { tx }
}
<|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 command_line::command_line_init;
use geom::size::TypedSize2D;
use glfw_app;
use libc::{c_int, c_void};
use native;
use servo::Browser;
use servo_util::opts;
use servo_util::opts::OpenGL;
use types::{cef_app_t, cef_main_args_t, cef_settings_t};

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 _settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }
    unsafe {
        command_line_init((*args).argc, (*args).argv);
        (*application).get_browser_process_handler.map(|cb| {
                let handler = cb(application);
                if handler.is_not_null() {
                    (*handler).on_context_initialized.map(|hcb| hcb(handler));
                }
        });
    }
    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    let mut urls = Vec::new();
    urls.push("http://s27.postimg.org/vqbtrolyr/servo.jpg".to_string());
    opts::set_opts(opts::Opts {
        urls: urls,
        n_render_threads: 1,
        gpu_painting: false,
        tile_size: 512,
        device_pixels_per_px: None,
        time_profiler_period: None,
        memory_profiler_period: None,
        enable_experimental: false,
        layout_threads: 1,
        nonincremental_layout: false,
        //layout_threads: cmp::max(rt::default_sched_threads() * 3 / 4, 1),
        exit_after_load: false,
        output_file: None,
        headless: false,
        hard_fail: false,
        bubble_inline_sizes_separately: false,
        show_debug_borders: false,
        show_debug_fragment_borders: false,
        enable_text_antialiasing: true,
        trace_layout: false,
        devtools_port: None,
        initial_window_size: TypedSize2D(800, 600),
        profile_tasks: false,
        user_agent: None,
        dump_flow_tree: false,
        validate_display_list_geometry: false,
        render_api: OpenGL,
    });
    native::start(0, 0 as *const *const u8, proc() {
        let window = glfw_app::create_window();
        let mut browser = Browser::new(Some(window.clone()));
        while browser.handle_event(window.wait_events()) {}
        browser.shutdown()
    });
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
   -1
}
<commit_msg>embedding: implement cef_execute_process() stub<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 command_line::command_line_init;
use geom::size::TypedSize2D;
use glfw_app;
use libc::funcs::c95::string::strlen;
use libc::{c_int, c_void};
use native;
use servo::Browser;
use servo_util::opts;
use servo_util::opts::OpenGL;
use std::slice;
use switches::{KPROCESSTYPE, KWAITFORDEBUGGER};
use types::{cef_app_t, cef_main_args_t, cef_settings_t};

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 _settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }
    unsafe {
        command_line_init((*args).argc, (*args).argv);
        (*application).get_browser_process_handler.map(|cb| {
                let handler = cb(application);
                if handler.is_not_null() {
                    (*handler).on_context_initialized.map(|hcb| hcb(handler));
                }
        });
    }
    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    let mut urls = Vec::new();
    urls.push("http://s27.postimg.org/vqbtrolyr/servo.jpg".to_string());
    opts::set_opts(opts::Opts {
        urls: urls,
        n_render_threads: 1,
        gpu_painting: false,
        tile_size: 512,
        device_pixels_per_px: None,
        time_profiler_period: None,
        memory_profiler_period: None,
        enable_experimental: false,
        layout_threads: 1,
        nonincremental_layout: false,
        //layout_threads: cmp::max(rt::default_sched_threads() * 3 / 4, 1),
        exit_after_load: false,
        output_file: None,
        headless: false,
        hard_fail: false,
        bubble_inline_sizes_separately: false,
        show_debug_borders: false,
        show_debug_fragment_borders: false,
        enable_text_antialiasing: true,
        trace_layout: false,
        devtools_port: None,
        initial_window_size: TypedSize2D(800, 600),
        profile_tasks: false,
        user_agent: None,
        dump_flow_tree: false,
        validate_display_list_geometry: false,
        render_api: OpenGL,
    });
    native::start(0, 0 as *const *const u8, proc() {
        let window = glfw_app::create_window();
        let mut browser = Browser::new(Some(window.clone()));
        while browser.handle_event(window.wait_events()) {}
        browser.shutdown()
    });
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
    unsafe {
        if args.is_null() {
            println!("args must be passed");
            return -1;
        }
        for i in range(0u, (*args).argc as uint) {
             let u = (*args).argv.offset(i as int) as *const u8;
             slice::raw::buf_as_slice(u, strlen(u as *const i8) as uint, |s| {
                 if s.starts_with("--".as_bytes()) {
                     if s.slice_from(2) == KWAITFORDEBUGGER.as_bytes() {
                         //FIXME: this is NOT functionally equivalent to chromium!

                         //this should be a pause() call with an installed signal
                         //handler callback, something which is impossible now in rust
                     } else if s.slice_from(2) == KPROCESSTYPE.as_bytes() {
                         //TODO: run other process now
                     }
                 }
             });
        }
    }
   //process type not specified, must be browser process (NOOP)
   -1
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
//! Aims to provide platform-independent methods to obtain login records
//!
//! **ONLY** support linux, macos and freebsd for the time being
//!
//! # Examples:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records() {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```
//!
//! Specifying the path to login record:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records().read_from("/some/where/else") {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```

pub extern crate time;
use self::time::{Timespec, Tm};

use std::ffi::CString;
use std::io::Error as IOError;
use std::io::Result as IOResult;
use std::ptr;

pub use self::ut::*;
use libc::utmpx;
// pub use libc::getutxid;
// pub use libc::getutxline;
// pub use libc::pututxline;
pub use libc::endutxent;
pub use libc::getutxent;
pub use libc::setutxent;
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub use libc::utmpxname;
#[cfg(target_os = "freebsd")]
pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

// In case the c_char array doesn't end with NULL
macro_rules! chars2string {
    ($arr:expr) => {
        $arr.iter()
            .take_while(|i| **i > 0)
            .map(|&i| i as u8 as char)
            .collect::<String>()
    };
}

#[cfg(target_os = "linux")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmp";

    pub use libc::__UT_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::__UT_LINESIZE as UT_LINESIZE;
    pub use libc::__UT_NAMESIZE as UT_NAMESIZE;
    pub const UT_IDSIZE: usize = 4;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "macos")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "freebsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "";

    pub const UT_LINESIZE: usize = 16;
    pub const UT_NAMESIZE: usize = 32;
    pub const UT_IDSIZE: usize = 8;
    pub const UT_HOSTSIZE: usize = 128;

    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::USER_PROCESS;
}

pub struct Utmpx {
    inner: utmpx,
}

impl Utmpx {
    /// A.K.A. ut.ut_type
    pub fn record_type(&self) -> i16 {
        self.inner.ut_type as i16
    }
    /// A.K.A. ut.ut_pid
    pub fn pid(&self) -> i32 {
        self.inner.ut_pid as i32
    }
    /// A.K.A. ut.ut_id
    pub fn terminal_suffix(&self) -> String {
        chars2string!(self.inner.ut_id)
    }
    /// A.K.A. ut.ut_user
    pub fn user(&self) -> String {
        chars2string!(self.inner.ut_user)
    }
    /// A.K.A. ut.ut_host
    pub fn host(&self) -> String {
        chars2string!(self.inner.ut_host)
    }
    /// A.K.A. ut.ut_line
    pub fn tty_device(&self) -> String {
        chars2string!(self.inner.ut_line)
    }
    /// A.K.A. ut.ut_tv
    pub fn login_time(&self) -> Tm {
        time::at(Timespec::new(
            self.inner.ut_tv.tv_sec as i64,
            self.inner.ut_tv.tv_usec as i32,
        ))
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (e_termination, e_exit)
    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub fn exit_status(&self) -> (i16, i16) {
        (self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit)
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (0, 0) on Non-Linux platform
    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    pub fn exit_status(&self) -> (i16, i16) {
        (0, 0)
    }
    /// Consumes the `Utmpx`, returning the underlying C struct utmpx
    pub fn into_inner(self) -> utmpx {
        self.inner
    }
    pub fn is_user_process(&self) -> bool {
        !self.user().is_empty() && self.record_type() == USER_PROCESS
    }

    /// Canonicalize host name using DNS
    pub fn canon_host(&self) -> IOResult<String> {
        const AI_CANONNAME: libc::c_int = 0x2;
        let host = self.host();
        let host = host.split(':').next().unwrap();
        let hints = libc::addrinfo {
            ai_flags: AI_CANONNAME,
            ai_family: 0,
            ai_socktype: 0,
            ai_protocol: 0,
            ai_addrlen: 0,
            ai_addr: ptr::null_mut(),
            ai_canonname: ptr::null_mut(),
            ai_next: ptr::null_mut(),
        };
        let c_host = CString::new(host).unwrap();
        let mut res = ptr::null_mut();
        let status = unsafe {
            libc::getaddrinfo(
                c_host.as_ptr(),
                ptr::null(),
                &hints as *const _,
                &mut res as *mut _,
            )
        };
        if status == 0 {
            let info: libc::addrinfo = unsafe { ptr::read(res as *const _) };
            // http://lists.gnu.org/archive/html/bug-coreutils/2006-09/msg00300.html
            // says Darwin 7.9.0 getaddrinfo returns 0 but sets
            // res->ai_canonname to NULL.
            let ret = if info.ai_canonname.is_null() {
                Ok(String::from(host))
            } else {
                Ok(unsafe { CString::from_raw(info.ai_canonname).into_string().unwrap() })
            };
            unsafe {
                libc::freeaddrinfo(res);
            }
            ret
        } else {
            Err(IOError::last_os_error())
        }
    }
    pub fn iter_all_records() -> UtmpxIter {
        UtmpxIter
    }
}

/// Iterator of login records
pub struct UtmpxIter;

impl UtmpxIter {
    /// Sets the name of the utmpx-format file for the other utmpx functions to access.
    ///
    /// If not set, default record file will be used(file path depends on the target OS)
    pub fn read_from(self, f: &str) -> Self {
        let res = unsafe { utmpxname(CString::new(f).unwrap().as_ptr()) };
        if res != 0 {
            println!("Warning: {}", IOError::last_os_error());
        }
        unsafe {
            setutxent();
        }
        self
    }
}

impl Iterator for UtmpxIter {
    type Item = Utmpx;
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let res = getutxent();
            if !res.is_null() {
                Some(Utmpx {
                    inner: ptr::read(res as *const _),
                })
            } else {
                endutxent();
                None
            }
        }
    }
}
<commit_msg>uucore/refactor ~ fix `cargo clippy` complaints (*allow* temporary_cstring_as_ptr; added FixME note)<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
//! Aims to provide platform-independent methods to obtain login records
//!
//! **ONLY** support linux, macos and freebsd for the time being
//!
//! # Examples:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records() {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```
//!
//! Specifying the path to login record:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records().read_from("/some/where/else") {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```

pub extern crate time;
use self::time::{Timespec, Tm};

use std::ffi::CString;
use std::io::Error as IOError;
use std::io::Result as IOResult;
use std::ptr;

pub use self::ut::*;
use libc::utmpx;
// pub use libc::getutxid;
// pub use libc::getutxline;
// pub use libc::pututxline;
pub use libc::endutxent;
pub use libc::getutxent;
pub use libc::setutxent;
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub use libc::utmpxname;
#[cfg(target_os = "freebsd")]
pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

// In case the c_char array doesn't end with NULL
macro_rules! chars2string {
    ($arr:expr) => {
        $arr.iter()
            .take_while(|i| **i > 0)
            .map(|&i| i as u8 as char)
            .collect::<String>()
    };
}

#[cfg(target_os = "linux")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmp";

    pub use libc::__UT_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::__UT_LINESIZE as UT_LINESIZE;
    pub use libc::__UT_NAMESIZE as UT_NAMESIZE;
    pub const UT_IDSIZE: usize = 4;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "macos")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "freebsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "";

    pub const UT_LINESIZE: usize = 16;
    pub const UT_NAMESIZE: usize = 32;
    pub const UT_IDSIZE: usize = 8;
    pub const UT_HOSTSIZE: usize = 128;

    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::USER_PROCESS;
}

pub struct Utmpx {
    inner: utmpx,
}

impl Utmpx {
    /// A.K.A. ut.ut_type
    pub fn record_type(&self) -> i16 {
        self.inner.ut_type as i16
    }
    /// A.K.A. ut.ut_pid
    pub fn pid(&self) -> i32 {
        self.inner.ut_pid as i32
    }
    /// A.K.A. ut.ut_id
    pub fn terminal_suffix(&self) -> String {
        chars2string!(self.inner.ut_id)
    }
    /// A.K.A. ut.ut_user
    pub fn user(&self) -> String {
        chars2string!(self.inner.ut_user)
    }
    /// A.K.A. ut.ut_host
    pub fn host(&self) -> String {
        chars2string!(self.inner.ut_host)
    }
    /// A.K.A. ut.ut_line
    pub fn tty_device(&self) -> String {
        chars2string!(self.inner.ut_line)
    }
    /// A.K.A. ut.ut_tv
    pub fn login_time(&self) -> Tm {
        time::at(Timespec::new(
            self.inner.ut_tv.tv_sec as i64,
            self.inner.ut_tv.tv_usec as i32,
        ))
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (e_termination, e_exit)
    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub fn exit_status(&self) -> (i16, i16) {
        (self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit)
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (0, 0) on Non-Linux platform
    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    pub fn exit_status(&self) -> (i16, i16) {
        (0, 0)
    }
    /// Consumes the `Utmpx`, returning the underlying C struct utmpx
    pub fn into_inner(self) -> utmpx {
        self.inner
    }
    pub fn is_user_process(&self) -> bool {
        !self.user().is_empty() && self.record_type() == USER_PROCESS
    }

    /// Canonicalize host name using DNS
    pub fn canon_host(&self) -> IOResult<String> {
        const AI_CANONNAME: libc::c_int = 0x2;
        let host = self.host();
        let host = host.split(':').next().unwrap();
        let hints = libc::addrinfo {
            ai_flags: AI_CANONNAME,
            ai_family: 0,
            ai_socktype: 0,
            ai_protocol: 0,
            ai_addrlen: 0,
            ai_addr: ptr::null_mut(),
            ai_canonname: ptr::null_mut(),
            ai_next: ptr::null_mut(),
        };
        let c_host = CString::new(host).unwrap();
        let mut res = ptr::null_mut();
        let status = unsafe {
            libc::getaddrinfo(
                c_host.as_ptr(),
                ptr::null(),
                &hints as *const _,
                &mut res as *mut _,
            )
        };
        if status == 0 {
            let info: libc::addrinfo = unsafe { ptr::read(res as *const _) };
            // http://lists.gnu.org/archive/html/bug-coreutils/2006-09/msg00300.html
            // says Darwin 7.9.0 getaddrinfo returns 0 but sets
            // res->ai_canonname to NULL.
            let ret = if info.ai_canonname.is_null() {
                Ok(String::from(host))
            } else {
                Ok(unsafe { CString::from_raw(info.ai_canonname).into_string().unwrap() })
            };
            unsafe {
                libc::freeaddrinfo(res);
            }
            ret
        } else {
            Err(IOError::last_os_error())
        }
    }
    pub fn iter_all_records() -> UtmpxIter {
        UtmpxIter
    }
}

/// Iterator of login records
pub struct UtmpxIter;

impl UtmpxIter {
    /// Sets the name of the utmpx-format file for the other utmpx functions to access.
    ///
    /// If not set, default record file will be used(file path depends on the target OS)
    pub fn read_from(self, f: &str) -> Self {
        // FixME: discuss and revise a rewrite which is correct and satisfies clippy/rustc
        #[allow(clippy::temporary_cstring_as_ptr)]
        let res = unsafe { utmpxname(CString::new(f).unwrap().as_ptr()) };
        if res != 0 {
            println!("Warning: {}", IOError::last_os_error());
        }
        unsafe {
            setutxent();
        }
        self
    }
}

impl Iterator for UtmpxIter {
    type Item = Utmpx;
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let res = getutxent();
            if !res.is_null() {
                Some(Utmpx {
                    inner: ptr::read(res as *const _),
                })
            } else {
                endutxent();
                None
            }
        }
    }
}
<|endoftext|>


<commit_before>use color::Color3;
use id_allocator::IdAllocator;
use nalgebra::{Pnt3, Vec3, normalize};
use ncollide::bounding_volume::AABB;
use noise::Seed;
use state::EntityId;
use std::cmp::{partial_min, partial_max};
use terrain_block::TerrainBlock;
use terrain_heightmap::HeightMap;

/// Use one-octave perlin noise local maxima to place trees.
pub struct TreePlacer {
  tree_field: HeightMap,
}

impl TreePlacer {
  pub fn new(seed: Seed) -> TreePlacer {
    let octaves = 1;
    let frequency = 1.0 / 4.0;
    let persistence = 1.0;
    let lacunarity = 1.0;
    let amplitude = 1.0;
    TreePlacer {
      tree_field: HeightMap::new(seed, octaves, frequency, persistence, lacunarity, amplitude),
    }
  }

  pub fn should_place_tree(&self, center: &Pnt3<f32>) -> bool {
    let center = self.tree_field.point_at(center.x, center.z);

    let delta = 0.1;
    let corners = [
      (-delta, -delta),
      (-delta,  delta),
      ( delta,  delta),
      ( delta, -delta),
    ];

    corners.iter()
      .all(|&(l, h)| center.y > self.tree_field.point_at(center.x + l, center.z + h).y)
  }

  pub fn place_tree(
    &self,
    mut center: Pnt3<f32>,
    id_allocator: &mut IdAllocator<EntityId>,
    block: &mut TerrainBlock,
  ) {
    let normals = [
      normalize(&Vec3::new(-1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0, -1.0)),
    ];

    let mut place_side =
      |&mut:
        corners: &[Pnt3<f32>],
        color: &Color3<f32>,
        idx1,
        idx2,
        idx3,
        idx4,
      | {
        let n1 = normals.get(idx1).unwrap();
        let n2 = normals.get(idx2).unwrap();
        let n3 = normals.get(idx3).unwrap();
        let n4 = normals.get(idx4).unwrap();

        let v1 = corners.get(idx1).unwrap();
        let v2 = corners.get(idx2).unwrap();
        let v3 = corners.get(idx3).unwrap();
        let v4 = corners.get(idx4).unwrap();

        block.vertex_coordinates.push_all(&[
          v1.x, v1.y, v1.z,
          v2.x, v2.y, v2.z,
          v4.x, v4.y, v4.z,

          v1.x, v1.y, v1.z,
          v4.x, v4.y, v4.z,
          v3.x, v3.y, v3.z,
        ]);

        block.normals.push_all(&[
          n1.x, n1.y, n1.z,
          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,

          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,
          n3.x, n3.y, n3.z,
        ]);

        block.colors.push_all(&[
          color.r, color.g, color.b,
          color.r, color.g, color.b,
        ]);

        let minx = partial_min(v1.x, v2.x).unwrap();
        let maxx = partial_max(v1.x, v2.x).unwrap();
        let minz = partial_min(v1.z, v2.z).unwrap();
        let maxz = partial_max(v1.z, v2.z).unwrap();

        let bounds =
          AABB::new(
            Pnt3::new(minx, v1.y, minz),
            Pnt3::new(maxx, v3.y, maxz),
          );

        let id1 = id_allocator.allocate();
        let id2 = id_allocator.allocate();
        block.ids.push_all(&[id1, id2]);

        block.bounds.insert(id1, bounds.clone());
        block.bounds.insert(id2, bounds);
      };

    let mut mass = self.tree_field.point_at(center.x, center.z).y;
    if mass < 0.0 || mass > 1.0 {
      warn!("clamping out-of-bounds mass: {}", mass);
      mass = partial_min(partial_max(0.0, mass).unwrap(), 1.0).unwrap();
    }
    mass = 1.0 - mass;

    {
      let radius = mass * mass * 2.0;
      let height = mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.4, 0.3, 0.1);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);

      center = center + Vec3::new(0.0, height, 0.0);
    }

    {
      let radius = mass * mass * 16.0;
      let height = mass * mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.0, 0.4, 0.0);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);
      place_side(&corners, &color, 4, 5, 7, 6);
      place_side(&corners, &color, 1, 0, 2, 3);
    }
  }
}
<commit_msg>Fixed tree normals.<commit_after>use color::Color3;
use id_allocator::IdAllocator;
use nalgebra::{Pnt3, Vec3, normalize};
use ncollide::bounding_volume::AABB;
use noise::Seed;
use state::EntityId;
use std::cmp::{partial_min, partial_max};
use terrain_block::TerrainBlock;
use terrain_heightmap::HeightMap;

/// Use one-octave perlin noise local maxima to place trees.
pub struct TreePlacer {
  tree_field: HeightMap,
}

impl TreePlacer {
  pub fn new(seed: Seed) -> TreePlacer {
    let octaves = 1;
    let frequency = 1.0 / 4.0;
    let persistence = 1.0;
    let lacunarity = 1.0;
    let amplitude = 1.0;
    TreePlacer {
      tree_field: HeightMap::new(seed, octaves, frequency, persistence, lacunarity, amplitude),
    }
  }

  pub fn should_place_tree(&self, center: &Pnt3<f32>) -> bool {
    let center = self.tree_field.point_at(center.x, center.z);

    let delta = 0.1;
    let corners = [
      (-delta, -delta),
      (-delta,  delta),
      ( delta,  delta),
      ( delta, -delta),
    ];

    corners.iter()
      .all(|&(l, h)| center.y > self.tree_field.point_at(center.x + l, center.z + h).y)
  }

  pub fn place_tree(
    &self,
    mut center: Pnt3<f32>,
    id_allocator: &mut IdAllocator<EntityId>,
    block: &mut TerrainBlock,
  ) {
    let normals = [
      normalize(&Vec3::new(-1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0, -1.0)),
    ];

    let mut place_side =
      |&mut:
        corners: &[Pnt3<f32>],
        color: &Color3<f32>,
        idx1,
        idx2,
        idx3,
        idx4,
      | {
        let n1 = normals.get(idx1).unwrap();
        let n2 = normals.get(idx2).unwrap();
        let n3 = normals.get(idx3).unwrap();
        let n4 = normals.get(idx4).unwrap();

        let v1 = corners.get(idx1).unwrap();
        let v2 = corners.get(idx2).unwrap();
        let v3 = corners.get(idx3).unwrap();
        let v4 = corners.get(idx4).unwrap();

        block.vertex_coordinates.push_all(&[
          v1.x, v1.y, v1.z,
          v2.x, v2.y, v2.z,
          v4.x, v4.y, v4.z,

          v1.x, v1.y, v1.z,
          v4.x, v4.y, v4.z,
          v3.x, v3.y, v3.z,
        ]);

        block.normals.push_all(&[
          n1.x, n1.y, n1.z,
          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,

          n1.x, n1.y, n1.z,
          n4.x, n4.y, n4.z,
          n3.x, n3.y, n3.z,
        ]);

        block.colors.push_all(&[
          color.r, color.g, color.b,
          color.r, color.g, color.b,
        ]);

        let minx = partial_min(v1.x, v2.x).unwrap();
        let maxx = partial_max(v1.x, v2.x).unwrap();
        let minz = partial_min(v1.z, v2.z).unwrap();
        let maxz = partial_max(v1.z, v2.z).unwrap();

        let bounds =
          AABB::new(
            Pnt3::new(minx, v1.y, minz),
            Pnt3::new(maxx, v3.y, maxz),
          );

        let id1 = id_allocator.allocate();
        let id2 = id_allocator.allocate();
        block.ids.push_all(&[id1, id2]);

        block.bounds.insert(id1, bounds.clone());
        block.bounds.insert(id2, bounds);
      };

    let mut mass = self.tree_field.point_at(center.x, center.z).y;
    if mass < 0.0 || mass > 1.0 {
      warn!("clamping out-of-bounds mass: {}", mass);
      mass = partial_min(partial_max(0.0, mass).unwrap(), 1.0).unwrap();
    }
    mass = 1.0 - mass;

    {
      let radius = mass * mass * 2.0;
      let height = mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.4, 0.3, 0.1);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);

      center = center + Vec3::new(0.0, height, 0.0);
    }

    {
      let radius = mass * mass * 16.0;
      let height = mass * mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.0, 0.4, 0.0);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);
      place_side(&corners, &color, 4, 5, 7, 6);
      place_side(&corners, &color, 1, 0, 2, 3);
    }
  }
}
<|endoftext|>


<commit_before>#![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
    revision: u64,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    if f.versions.bottle {
        let bs = f.bottle.stable.as_ref()?;
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                println!(
                    "{sha256} {url} {name}-{version}{revision}.{platform}.bottle{rebuild}.tar.gz",
                    sha256 = bi.sha256,
                    url = bi.url,
                    name = f.name,
                    version = f.versions.stable.as_ref()?,
                    revision = if f.revision == 0 { "".to_owned() } else { format!("_{}", f.revision) },
                    platform = platform,
                    rebuild = if bs.rebuild == 0 { "".to_owned() } else { format!(".{}", bs.rebuild) },
                );
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<commit_msg>Remove try_trait<commit_after>// #![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
    revision: u64,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    if f.versions.bottle {
        let bs = f.bottle.stable.as_ref()?;
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                println!(
                    "{sha256} {url} {name}-{version}{revision}.{platform}.bottle{rebuild}.tar.gz",
                    sha256 = bi.sha256,
                    url = bi.url,
                    name = f.name,
                    version = f.versions.stable.as_ref()?,
                    revision = if f.revision == 0 { "".to_owned() } else { format!("_{}", f.revision) },
                    platform = platform,
                    rebuild = if bs.rebuild == 0 { "".to_owned() } else { format!(".{}", bs.rebuild) },
                );
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove update_sockets_events_if_polling<commit_after><|endoftext|>


<commit_before>#![crate_name = "uname"]
#![allow(unstable)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joao Oliveira <joaoxsouls@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: uname (GNU coreutils) 8.21 */

#![allow(non_camel_case_types)]

extern crate getopts;
extern crate libc;

use std::ffi::c_str_to_bytes;
use std::mem::uninitialized;
use std::io::print;
use c_types::utsname;

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

struct utsrust {
    sysname: String,
    nodename: String,
    release: String,
    version: String,
    machine: String
}

extern {
    fn uname(uts: *mut utsname);
}

unsafe fn string_from_c_str(ptr: *const i8) -> String {
    String::from_utf8_lossy(c_str_to_bytes(&ptr)).to_string()
}

unsafe fn getuname() -> utsrust {
    let mut uts: utsname = uninitialized();
    uname(&mut uts);
    utsrust {
        sysname:  string_from_c_str(uts.sysname.as_ptr()  as *const i8),
        nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8),
        release:  string_from_c_str(uts.release.as_ptr()  as *const i8),
        version:  string_from_c_str(uts.version.as_ptr()  as *const i8),
        machine:  string_from_c_str(uts.machine.as_ptr()  as *const i8)
    }
}

static NAME: &'static str = "uname";

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("a", "all", "Behave as though all of the options -mnrsv were specified."),
        getopts::optflag("m", "machine", "print the machine hardware name."),
        getopts::optflag("n", "nodename", "print the nodename (the nodename may be a name that the system is known by to a communications network)."),
        getopts::optflag("p", "processor", "print the machine processor architecture name."),
        getopts::optflag("r", "release", "print the operating system release."),
        getopts::optflag("s", "sysname", "print the operating system name."),
        getopts::optflag("v", "version", "print the operating system version."),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };
    if matches.opt_present("help") {
        println!("uname 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {}", program);
        println!("");
        print(getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts).as_slice());
        return 0;
    }
    let uname = unsafe { getuname() };
    let mut output = String::new();
    if matches.opt_present("sysname") || matches.opt_present("all")
        || !matches.opts_present(&["nodename".to_string(), "release".to_string(), "version".to_string(), "machine".to_string()]) {
            output.push_str(uname.sysname.as_slice());
            output.push_str(" ");
    }

    if matches.opt_present("nodename") || matches.opt_present("all") {
        output.push_str(uname.nodename.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("release") || matches.opt_present("all") {
        output.push_str(uname.release.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("version") || matches.opt_present("all") {
        output.push_str(uname.version.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("machine") || matches.opt_present("all") {
        output.push_str(uname.machine.as_slice());
        output.push_str(" ");
    }
    println!("{}", output.as_slice().trim_left());

    0
}
<commit_msg>uname: change trim_left() to trim()<commit_after>#![crate_name = "uname"]
#![allow(unstable)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joao Oliveira <joaoxsouls@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: uname (GNU coreutils) 8.21 */

#![allow(non_camel_case_types)]

extern crate getopts;
extern crate libc;

use std::ffi::c_str_to_bytes;
use std::mem::uninitialized;
use std::io::print;
use c_types::utsname;

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

struct utsrust {
    sysname: String,
    nodename: String,
    release: String,
    version: String,
    machine: String
}

extern {
    fn uname(uts: *mut utsname);
}

unsafe fn string_from_c_str(ptr: *const i8) -> String {
    String::from_utf8_lossy(c_str_to_bytes(&ptr)).to_string()
}

unsafe fn getuname() -> utsrust {
    let mut uts: utsname = uninitialized();
    uname(&mut uts);
    utsrust {
        sysname:  string_from_c_str(uts.sysname.as_ptr()  as *const i8),
        nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8),
        release:  string_from_c_str(uts.release.as_ptr()  as *const i8),
        version:  string_from_c_str(uts.version.as_ptr()  as *const i8),
        machine:  string_from_c_str(uts.machine.as_ptr()  as *const i8)
    }
}

static NAME: &'static str = "uname";

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("a", "all", "Behave as though all of the options -mnrsv were specified."),
        getopts::optflag("m", "machine", "print the machine hardware name."),
        getopts::optflag("n", "nodename", "print the nodename (the nodename may be a name that the system is known by to a communications network)."),
        getopts::optflag("p", "processor", "print the machine processor architecture name."),
        getopts::optflag("r", "release", "print the operating system release."),
        getopts::optflag("s", "sysname", "print the operating system name."),
        getopts::optflag("v", "version", "print the operating system version."),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };
    if matches.opt_present("help") {
        println!("uname 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {}", program);
        println!("");
        print(getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts).as_slice());
        return 0;
    }
    let uname = unsafe { getuname() };
    let mut output = String::new();
    if matches.opt_present("sysname") || matches.opt_present("all")
        || !matches.opts_present(&["nodename".to_string(), "release".to_string(), "version".to_string(), "machine".to_string()]) {
            output.push_str(uname.sysname.as_slice());
            output.push_str(" ");
    }

    if matches.opt_present("nodename") || matches.opt_present("all") {
        output.push_str(uname.nodename.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("release") || matches.opt_present("all") {
        output.push_str(uname.release.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("version") || matches.opt_present("all") {
        output.push_str(uname.version.as_slice());
        output.push_str(" ");
    }
    if matches.opt_present("machine") || matches.opt_present("all") {
        output.push_str(uname.machine.as_slice());
        output.push_str(" ");
    }
    println!("{}", output.as_slice().trim());

    0
}
<|endoftext|>


<commit_before>use std::{
    convert::{TryFrom, TryInto},
    mem,
};

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{
    parse::{Parse, ParseStream},
    punctuated::Punctuated,
    visit::Visit,
    DeriveInput, Field, Generics, Ident, Lifetime, Token, Type,
};

use crate::{
    attribute::{Meta, MetaNameValue, MetaValue},
    util,
};

mod incoming;
mod outgoing;

pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
    let fields = match input.data {
        syn::Data::Struct(s) => s.fields,
        _ => panic!("This derive macro only works on structs"),
    };

    let fields = fields.into_iter().map(ResponseField::try_from).collect::<syn::Result<_>>()?;
    let mut error_ty = None;
    for attr in input.attrs {
        if !attr.path.is_ident("ruma_api") {
            continue;
        }

        let meta = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?;
        for MetaNameValue { name, value } in meta {
            match value {
                MetaValue::Type(t) if name == "error_ty" => {
                    error_ty = Some(t);
                }
                _ => unreachable!("invalid ruma_api({}) attribute", name),
            }
        }
    }

    let response = Response {
        ident: input.ident,
        generics: input.generics,
        fields,
        error_ty: error_ty.unwrap(),
    };

    response.check()?;
    Ok(response.expand_all())
}

struct Response {
    ident: Ident,
    generics: Generics,
    fields: Vec<ResponseField>,
    error_ty: Type,
}

impl Response {
    /// Whether or not this request has any data in the HTTP body.
    fn has_body_fields(&self) -> bool {
        self.fields
            .iter()
            .any(|f| matches!(f, ResponseField::Body(_) | &ResponseField::NewtypeBody(_)))
    }

    /// Whether or not this request has a single newtype body field.
    fn has_newtype_body(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, ResponseField::NewtypeBody(_)))
    }

    /// Whether or not this request has a single raw body field.
    fn has_raw_body(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, ResponseField::RawBody(_)))
    }

    /// Whether or not this request has any data in the URL path.
    fn has_header_fields(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, &ResponseField::Header(..)))
    }

    fn expand_all(&self) -> TokenStream {
        let ruma_api = util::import_ruma_api();
        let ruma_api_macros = quote! { #ruma_api::exports::ruma_api_macros };
        let ruma_serde = quote! { #ruma_api::exports::ruma_serde };
        let serde = quote! { #ruma_api::exports::serde };

        let response_body_struct = (!self.has_raw_body()).then(|| {
            let serde_attr = self.has_newtype_body().then(|| quote! { #[serde(transparent)] });
            let fields = self.fields.iter().filter_map(ResponseField::as_body_field);

            quote! {
                /// Data in the response body.
                #[derive(
                    Debug,
                    #ruma_api_macros::_FakeDeriveRumaApi,
                    #ruma_serde::Outgoing,
                    #serde::Deserialize,
                    #serde::Serialize,
                )]
                #serde_attr
                struct ResponseBody { #(#fields),* }
            }
        });

        let outgoing_response_impl = self.expand_outgoing(&ruma_api);
        let incoming_response_impl = self.expand_incoming(&self.error_ty, &ruma_api);

        quote! {
            #response_body_struct

            #outgoing_response_impl
            #incoming_response_impl
        }
    }

    pub fn check(&self) -> syn::Result<()> {
        // TODO: highlight problematic fields

        if !self.generics.params.is_empty() || self.generics.where_clause.is_some() {
            panic!("This macro doesn't support generic types");
        }

        let newtype_body_fields = self
            .fields
            .iter()
            .filter(|f| matches!(f, ResponseField::NewtypeBody(_) | ResponseField::RawBody(_)));

        let has_newtype_body_field = match newtype_body_fields.count() {
            0 => false,
            1 => true,
            _ => {
                return Err(syn::Error::new_spanned(
                    &self.ident,
                    "Can't have more than one newtype body field",
                ))
            }
        };

        let has_body_fields = self.fields.iter().any(|f| matches!(f, ResponseField::Body(_)));
        if has_newtype_body_field && has_body_fields {
            return Err(syn::Error::new_spanned(
                &self.ident,
                "Can't have both a newtype body field and regular body fields",
            ));
        }

        Ok(())
    }
}

/// The types of fields that a response can have.
enum ResponseField {
    /// JSON data in the body of the response.
    Body(Field),

    /// Data in an HTTP header.
    Header(Field, Ident),

    /// A specific data type in the body of the response.
    NewtypeBody(Field),

    /// Arbitrary bytes in the body of the response.
    RawBody(Field),
}

impl ResponseField {
    /// Gets the inner `Field` value.
    fn field(&self) -> &Field {
        match self {
            ResponseField::Body(field)
            | ResponseField::Header(field, _)
            | ResponseField::NewtypeBody(field)
            | ResponseField::RawBody(field) => field,
        }
    }

    /// Return the contained field if this response field is a body kind.
    fn as_body_field(&self) -> Option<&Field> {
        match self {
            ResponseField::Body(field) | ResponseField::NewtypeBody(field) => Some(field),
            _ => None,
        }
    }

    /// Return the contained field if this response field is a raw body kind.
    fn as_raw_body_field(&self) -> Option<&Field> {
        match self {
            ResponseField::RawBody(field) => Some(field),
            _ => None,
        }
    }

    /// Return the contained field and HTTP header ident if this repsonse field is a header kind.
    fn as_header_field(&self) -> Option<(&Field, &Ident)> {
        match self {
            ResponseField::Header(field, ident) => Some((field, ident)),
            _ => None,
        }
    }
}

impl TryFrom<Field> for ResponseField {
    type Error = syn::Error;

    fn try_from(mut field: Field) -> syn::Result<Self> {
        if has_lifetime(&field.ty) {
            return Err(syn::Error::new_spanned(
                field.ident,
                "Lifetimes on Response fields cannot be supported until GAT are stable",
            ));
        }

        let mut field_kind = None;
        let mut header = None;

        for attr in mem::take(&mut field.attrs) {
            let meta = match Meta::from_attribute(&attr)? {
                Some(m) => m,
                None => {
                    field.attrs.push(attr);
                    continue;
                }
            };

            if field_kind.is_some() {
                return Err(syn::Error::new_spanned(
                    attr,
                    "There can only be one field kind attribute",
                ));
            }

            field_kind = Some(match meta {
                Meta::Word(ident) => match &ident.to_string()[..] {
                    "body" => ResponseFieldKind::NewtypeBody,
                    "raw_body" => ResponseFieldKind::RawBody,
                    _ => {
                        return Err(syn::Error::new_spanned(
                            ident,
                            "Invalid #[ruma_api] argument with value, expected `body`",
                        ));
                    }
                },
                Meta::NameValue(MetaNameValue { name, value }) => {
                    if name != "header" {
                        return Err(syn::Error::new_spanned(
                            name,
                            "Invalid #[ruma_api] argument with value, expected `header`",
                        ));
                    }

                    header = Some(value);
                    ResponseFieldKind::Header
                }
            });
        }

        Ok(match field_kind.unwrap_or(ResponseFieldKind::Body) {
            ResponseFieldKind::Body => ResponseField::Body(field),
            ResponseFieldKind::Header => {
                ResponseField::Header(field, header.expect("missing header name"))
            }
            ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
            ResponseFieldKind::RawBody => ResponseField::RawBody(field),
        })
    }
}

impl Parse for ResponseField {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        input.call(Field::parse_named)?.try_into()
    }
}

impl ToTokens for ResponseField {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.field().to_tokens(tokens)
    }
}

/// The types of fields that a response can have, without their values.
enum ResponseFieldKind {
    Body,
    Header,
    NewtypeBody,
    RawBody,
}

fn has_lifetime(ty: &Type) -> bool {
    struct Visitor {
        found_lifetime: bool,
    }

    impl<'ast> Visit<'ast> for Visitor {
        fn visit_lifetime(&mut self, _lt: &'ast Lifetime) {
            self.found_lifetime = true;
        }
    }

    let mut vis = Visitor { found_lifetime: false };
    vis.visit_type(ty);
    vis.found_lifetime
}
<commit_msg>api-macros: Replace if-then-panic with assert<commit_after>use std::{
    convert::{TryFrom, TryInto},
    mem,
};

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{
    parse::{Parse, ParseStream},
    punctuated::Punctuated,
    visit::Visit,
    DeriveInput, Field, Generics, Ident, Lifetime, Token, Type,
};

use crate::{
    attribute::{Meta, MetaNameValue, MetaValue},
    util,
};

mod incoming;
mod outgoing;

pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
    let fields = match input.data {
        syn::Data::Struct(s) => s.fields,
        _ => panic!("This derive macro only works on structs"),
    };

    let fields = fields.into_iter().map(ResponseField::try_from).collect::<syn::Result<_>>()?;
    let mut error_ty = None;
    for attr in input.attrs {
        if !attr.path.is_ident("ruma_api") {
            continue;
        }

        let meta = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?;
        for MetaNameValue { name, value } in meta {
            match value {
                MetaValue::Type(t) if name == "error_ty" => {
                    error_ty = Some(t);
                }
                _ => unreachable!("invalid ruma_api({}) attribute", name),
            }
        }
    }

    let response = Response {
        ident: input.ident,
        generics: input.generics,
        fields,
        error_ty: error_ty.unwrap(),
    };

    response.check()?;
    Ok(response.expand_all())
}

struct Response {
    ident: Ident,
    generics: Generics,
    fields: Vec<ResponseField>,
    error_ty: Type,
}

impl Response {
    /// Whether or not this request has any data in the HTTP body.
    fn has_body_fields(&self) -> bool {
        self.fields
            .iter()
            .any(|f| matches!(f, ResponseField::Body(_) | &ResponseField::NewtypeBody(_)))
    }

    /// Whether or not this request has a single newtype body field.
    fn has_newtype_body(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, ResponseField::NewtypeBody(_)))
    }

    /// Whether or not this request has a single raw body field.
    fn has_raw_body(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, ResponseField::RawBody(_)))
    }

    /// Whether or not this request has any data in the URL path.
    fn has_header_fields(&self) -> bool {
        self.fields.iter().any(|f| matches!(f, &ResponseField::Header(..)))
    }

    fn expand_all(&self) -> TokenStream {
        let ruma_api = util::import_ruma_api();
        let ruma_api_macros = quote! { #ruma_api::exports::ruma_api_macros };
        let ruma_serde = quote! { #ruma_api::exports::ruma_serde };
        let serde = quote! { #ruma_api::exports::serde };

        let response_body_struct = (!self.has_raw_body()).then(|| {
            let serde_attr = self.has_newtype_body().then(|| quote! { #[serde(transparent)] });
            let fields = self.fields.iter().filter_map(ResponseField::as_body_field);

            quote! {
                /// Data in the response body.
                #[derive(
                    Debug,
                    #ruma_api_macros::_FakeDeriveRumaApi,
                    #ruma_serde::Outgoing,
                    #serde::Deserialize,
                    #serde::Serialize,
                )]
                #serde_attr
                struct ResponseBody { #(#fields),* }
            }
        });

        let outgoing_response_impl = self.expand_outgoing(&ruma_api);
        let incoming_response_impl = self.expand_incoming(&self.error_ty, &ruma_api);

        quote! {
            #response_body_struct

            #outgoing_response_impl
            #incoming_response_impl
        }
    }

    pub fn check(&self) -> syn::Result<()> {
        // TODO: highlight problematic fields

        assert!(
            self.generics.params.is_empty() && self.generics.where_clause.is_none(),
            "This macro doesn't support generic types"
        );

        let newtype_body_fields = self
            .fields
            .iter()
            .filter(|f| matches!(f, ResponseField::NewtypeBody(_) | ResponseField::RawBody(_)));

        let has_newtype_body_field = match newtype_body_fields.count() {
            0 => false,
            1 => true,
            _ => {
                return Err(syn::Error::new_spanned(
                    &self.ident,
                    "Can't have more than one newtype body field",
                ))
            }
        };

        let has_body_fields = self.fields.iter().any(|f| matches!(f, ResponseField::Body(_)));
        if has_newtype_body_field && has_body_fields {
            return Err(syn::Error::new_spanned(
                &self.ident,
                "Can't have both a newtype body field and regular body fields",
            ));
        }

        Ok(())
    }
}

/// The types of fields that a response can have.
enum ResponseField {
    /// JSON data in the body of the response.
    Body(Field),

    /// Data in an HTTP header.
    Header(Field, Ident),

    /// A specific data type in the body of the response.
    NewtypeBody(Field),

    /// Arbitrary bytes in the body of the response.
    RawBody(Field),
}

impl ResponseField {
    /// Gets the inner `Field` value.
    fn field(&self) -> &Field {
        match self {
            ResponseField::Body(field)
            | ResponseField::Header(field, _)
            | ResponseField::NewtypeBody(field)
            | ResponseField::RawBody(field) => field,
        }
    }

    /// Return the contained field if this response field is a body kind.
    fn as_body_field(&self) -> Option<&Field> {
        match self {
            ResponseField::Body(field) | ResponseField::NewtypeBody(field) => Some(field),
            _ => None,
        }
    }

    /// Return the contained field if this response field is a raw body kind.
    fn as_raw_body_field(&self) -> Option<&Field> {
        match self {
            ResponseField::RawBody(field) => Some(field),
            _ => None,
        }
    }

    /// Return the contained field and HTTP header ident if this repsonse field is a header kind.
    fn as_header_field(&self) -> Option<(&Field, &Ident)> {
        match self {
            ResponseField::Header(field, ident) => Some((field, ident)),
            _ => None,
        }
    }
}

impl TryFrom<Field> for ResponseField {
    type Error = syn::Error;

    fn try_from(mut field: Field) -> syn::Result<Self> {
        if has_lifetime(&field.ty) {
            return Err(syn::Error::new_spanned(
                field.ident,
                "Lifetimes on Response fields cannot be supported until GAT are stable",
            ));
        }

        let mut field_kind = None;
        let mut header = None;

        for attr in mem::take(&mut field.attrs) {
            let meta = match Meta::from_attribute(&attr)? {
                Some(m) => m,
                None => {
                    field.attrs.push(attr);
                    continue;
                }
            };

            if field_kind.is_some() {
                return Err(syn::Error::new_spanned(
                    attr,
                    "There can only be one field kind attribute",
                ));
            }

            field_kind = Some(match meta {
                Meta::Word(ident) => match &ident.to_string()[..] {
                    "body" => ResponseFieldKind::NewtypeBody,
                    "raw_body" => ResponseFieldKind::RawBody,
                    _ => {
                        return Err(syn::Error::new_spanned(
                            ident,
                            "Invalid #[ruma_api] argument with value, expected `body`",
                        ));
                    }
                },
                Meta::NameValue(MetaNameValue { name, value }) => {
                    if name != "header" {
                        return Err(syn::Error::new_spanned(
                            name,
                            "Invalid #[ruma_api] argument with value, expected `header`",
                        ));
                    }

                    header = Some(value);
                    ResponseFieldKind::Header
                }
            });
        }

        Ok(match field_kind.unwrap_or(ResponseFieldKind::Body) {
            ResponseFieldKind::Body => ResponseField::Body(field),
            ResponseFieldKind::Header => {
                ResponseField::Header(field, header.expect("missing header name"))
            }
            ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
            ResponseFieldKind::RawBody => ResponseField::RawBody(field),
        })
    }
}

impl Parse for ResponseField {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        input.call(Field::parse_named)?.try_into()
    }
}

impl ToTokens for ResponseField {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.field().to_tokens(tokens)
    }
}

/// The types of fields that a response can have, without their values.
enum ResponseFieldKind {
    Body,
    Header,
    NewtypeBody,
    RawBody,
}

fn has_lifetime(ty: &Type) -> bool {
    struct Visitor {
        found_lifetime: bool,
    }

    impl<'ast> Visit<'ast> for Visitor {
        fn visit_lifetime(&mut self, _lt: &'ast Lifetime) {
            self.found_lifetime = true;
        }
    }

    let mut vis = Visitor { found_lifetime: false };
    vis.visit_type(ty);
    vis.found_lifetime
}
<|endoftext|>