<commit_before>//! Bindings for Darknet

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unused_import_braces)]
#![deny(unused_qualifications)]

#[macro_use]
extern crate failure;

/// FFI bindings.
pub mod ffi {
    #![allow(missing_docs)]
    #![allow(missing_debug_implementations)]
    #![allow(missing_copy_implementations)]
    #![allow(trivial_casts)]
    #![allow(trivial_numeric_casts)]
    #![allow(unused_import_braces)]
    #![allow(unused_qualifications)]
    #![allow(dead_code)]
    #![allow(non_upper_case_globals)]
    #![allow(non_camel_case_types)]
    #![allow(non_snake_case)]

    #[cfg(feature = "gen")]
    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

    #[cfg(not(feature = "gen"))]
    #[cfg(target_os = "macos")]
    include!("ffi_osx.rs");

    #[cfg(not(feature = "gen"))]
    #[cfg(not(feature = "nnpack"))]
    #[cfg(target_os = "linux")]
    include!("ffi_linux.rs");

    #[cfg(not(feature = "gen"))]
    #[cfg(feature = "nnpack")]
    #[cfg(target_os = "linux")]
    include!("ffi_linux_nnpack.rs");
}

use std::ffi::{CStr, CString};
use std::path::Path;
pub use failure::Error;

mod errors {
    use std::path::PathBuf;

    #[derive(Debug, Fail)]
    /// Custom errors.
    pub enum DarknetError {
        #[fail(display = "invalid path: {:?}", _0)]
        /// Indicates that path was invalid
        InvalidPath(PathBuf),
    }
}

/// Network
#[derive(Debug)]
pub struct Network {
    net: *mut ffi::network,
    nnp_status: bool,
}

impl Network {
    /// Create a new network.
    pub fn new<P: AsRef<Path>>(config: P, weight: P) -> Result<Self, Error> {
        let config = path_to_cstring(config)?.into_raw();
        let weight = path_to_cstring(weight)?.into_raw();
        let net = unsafe { ffi::load_network(config, weight, 0) };
        Ok(Network {
            net: net,
            nnp_status: false,
        })
    }

    #[cfg(feature = "nnpack")]
    /// Initializes the network with a threadpool.
    pub fn threadpool(&mut self, n: usize) {
        if !self.nnp_status {
            unsafe { ffi::nnp_initialize() };
            self.nnp_status = true;
        }

        unsafe { (*self.net).threadpool = ffi::pthreadpool_create(n) }
    }

    /// Return the width of the network.
    pub fn width(&self) -> usize {
        unsafe { ffi::network_width(self.net) as usize }
    }

    /// Return the height of the network.
    pub fn height(&self) -> usize {
        unsafe { ffi::network_height(self.net) as usize }
    }

    /// Perform prediction.
    pub fn predict(&self, data: *mut f32) -> *mut f32 {
        unsafe { ffi::network_predict(self.net, data) }
    }

    /// Perform prediction.
    pub fn predict_image(&self, image: &Image) -> *mut f32 {
        unsafe { ffi::network_predict_image(self.net, image.0) }
    }

    /// Get the network boxes.
    fn get_network_boxes(&self, w: i32, h: i32, thresh: f32, hier: f32) -> Detections_ {
        let mut num = 0;
        let det = unsafe {
            ffi::get_network_boxes(
                self.net,
                w,
                h,
                thresh,
                hier,
                std::ptr::null_mut(),
                0,
                &mut num,
            )
        };
        Detections_ {
            inner: det,
            num: num,
        }
    }
}

impl Drop for Network {
    #[cfg(not(feature = "nnpack"))]
    fn drop(&mut self) {
        unsafe {
            ffi::free_network(self.net);
        }
    }

    #[cfg(feature = "nnpack")]
    fn drop(&mut self) {
        if self.nnp_status {
            unsafe {
                ffi::pthreadpool_destroy((*self.net).threadpool);
                ffi::nnp_deinitialize();
            }
        }
        unsafe {
            ffi::free_network(self.net);
        }
    }
}

fn path_to_cstring<P: AsRef<Path>>(path: P) -> Result<CString, Error> {
    let path = path.as_ref();
    let x = path.to_str()
        .ok_or(errors::DarknetError::InvalidPath(path.into()))?;
    let result = CString::new(x)?;
    Ok(result)
}

/// Perform simple detection with default threshold.
#[inline]
pub fn simple_detect(network: &Network, meta: &Meta, image: &Image) -> Vec<Detection> {
    let thres = 0.5;
    let hier_thresh = 0.5;
    let nms = 0.45;
    detect(network, meta, image, thres, hier_thresh, nms)
}

/// Perform detection.
pub fn detect(
    network: &Network,
    meta: &Meta,
    image: &Image,
    thresh: f32,
    hier_thresh: f32,
    nms: f32,
) -> Vec<Detection> {
    network.predict_image(image);
    let dets = network.get_network_boxes(image.0.w, image.0.h, thresh, hier_thresh);
    let detections = dets.postprocess(nms, meta);
    detections
}

/// A rectangle type.
pub type Rect = ffi::box_;

/// Detection. Note that the bounding box is centered at (x, y) and have width
/// `w` and height `h`.
#[derive(Debug, Clone)]
pub struct Detection {
    /// The class.
    pub class: i32,
    /// x coordinate.
    pub x: f32,
    /// y coordinate.
    pub y: f32,
    /// width.
    pub w: f32,
    /// height.
    pub h: f32,
    /// probability.
    pub prob: f32,
    /// name.
    pub name: String,
}

/// Internal Detection.
#[derive(Debug)]
struct Detections_ {
    inner: *mut ffi::detection,
    num: i32,
}

impl Drop for Detections_ {
    fn drop(&mut self) {
        unsafe {
            ffi::free_detections(self.inner, self.num);
        }
    }
}

impl Detections_ {
    /// Non-maximum suppression.
    fn nms(&self, total: i32, classes: i32, thresh: f32) {
        unsafe {
            ffi::do_nms_obj(self.inner, total, classes, thresh);
        }
    }

    /// Filter detection.
    pub fn postprocess(&self, nms: f32, meta: &Meta) -> Vec<Detection> {
        if nms > 0.0 {
            self.nms(self.num, meta.num_classes(), nms);
        }

        let mut res = Vec::new();
        for j in 0..(self.num as isize) {
            let d = unsafe { *self.inner.offset(j) };
            let bbox = d.bbox;
            let probs = d.prob;
            for i in 0..(meta.num_classes() as isize) {
                let p = unsafe { *probs.offset(i) };
                if p > 0.0 {
                    let ffi::box_ { x, y, w, h } = bbox;
                    res.push(Detection {
                        class: i as i32,
                        x: x,
                        y: y,
                        w: w,
                        h: h,
                        prob: p,
                        name: meta.class_name(i as usize).to_string(),
                    });
                }
            }
        }

        res.sort_by(|a, b| b.prob.partial_cmp(&a.prob).unwrap());
        res
    }
}

/// Metadata.
#[derive(Debug)]
pub struct Meta {
    names: Vec<String>,
}

impl From<ffi::metadata> for Meta {
    fn from(meta: ffi::metadata) -> Self {
        let names = (0..(meta.classes as isize))
            .map(|i| unsafe {
                CStr::from_ptr(*(meta.names.offset(i)))
                    .to_string_lossy()
                    .into_owned()
            })
            .collect();
        Meta { names: names }
    }
}

impl Meta {
    /// Load a new metadata.
    pub fn new<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let meta = unsafe { ffi::get_metadata(filename) };
        Ok(meta.into())
    }

    /// Return the number of classes.
    pub fn num_classes(&self) -> i32 {
        self.names.len() as i32
    }

    /// Return the class name identified by the classification index.
    pub fn class_name(&self, i: usize) -> &str {
        &self.names[i]
    }
}

/// Image
#[derive(Debug, Clone)]
pub struct Image(pub ffi::image);

unsafe impl Send for Image {}

impl Image {
    /// Create a new image.
    pub fn new(w: i32, h: i32, c: i32) -> Self {
        Image(unsafe { ffi::make_image(w, h, c) })
    }

    /// Load a new image.
    pub fn load<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe { ffi::load_image(filename, 0, 0, 0) };
        Ok(Image(img))
    }

    /// Load a new image with color.
    pub fn load_color<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe { ffi::load_image_color(filename, 0, 0) };
        Ok(Image(img))
    }

    /// Load a new image with multiple threads.
    #[cfg(feature = "nnpack")]
    pub fn load_threaded<P: AsRef<Path>>(filename: P, network: &Network) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe {
            ffi::load_image_thread(filename, 0, 0, (*network.net).c, (*network.net).threadpool)
        };
        Ok(Image(img))
    }

    /// Decode a new image (always color, 3 channels).
    pub fn decode_jpg(buf: &[u8]) -> Self {
        let image = unsafe { ffi::decode_image_jpg(buf.as_ptr(), buf.len() as i32, 3) };
        Image(image)
    }

    /// Draw a box based on the detection.
    pub fn draw_box(&mut self, d: &Detection, w: i32, r: f32, g: f32, b: f32) {
        let x1 = d.x - d.w / 2.;
        let x2 = d.x + d.w / 2.;
        let y1 = d.y - d.h / 2.;
        let y2 = d.y + d.h / 2.;

        unsafe {
            ffi::draw_box_width(
                self.0,
                x1 as i32,
                y1 as i32,
                x2 as i32,
                y2 as i32,
                w,
                r,
                g,
                b,
            )
        }
    }

    /// Save the image.
    pub fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        unsafe { ffi::save_image(self.0, filename) };
        Ok(())
    }

    /// Save the image as jpg.
    pub fn save_jpg<P: AsRef<Path>>(&self, filename: P) -> Result<(), Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        unsafe { ffi::save_image_jpg(self.0, filename) };
        Ok(())
    }

    /// Save the image as jpg.
    pub fn encode_jpg(&self) -> Vec<u8> {
        let cap = (self.0.w * self.0.h * self.0.c) as usize;
        let mut data: Vec<u8> = Vec::with_capacity(cap);
        let size = unsafe { ffi::encode_image_jpg(self.0, data.as_ptr()) };
        unsafe {
            data.set_len(size as usize);
        }

        data
    }

    /// Resize and return a new image.
    pub fn resize(&self, w: i32, h: i32) -> Image {
        Image(unsafe { ffi::resize_image(self.0, w, h) })
    }

    /// Image width.
    pub fn width(&self) -> i32 {
        self.0.w
    }

    /// Image height.
    pub fn height(&self) -> i32 {
        self.0.h
    }

    /// Image channel.
    pub fn channel(&self) -> i32 {
        self.0.c
    }
}

impl Drop for Image {
    fn drop(&mut self) {
        unsafe {
            ffi::free_image(self.0);
        }
    }
}

/// Groundtruth.
#[derive(Debug)]
pub struct Groundtruth {
    boxes: Vec<ffi::box_label>,
}

impl Groundtruth {
    /// Load a new label.
    pub fn load<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let mut num = 0;
        let truth = unsafe { ffi::read_boxes(filename, &mut num) };

        let truth = (0..num)
            .map(|i| unsafe { *(truth.offset(i as isize)) })
            .collect();
        Ok(Groundtruth { boxes: truth })
    }

    /// Return the rectangle box at a particular index.
    pub fn box_at(&self, i: usize) -> Rect {
        Rect {
            x: self.boxes[i].x,
            y: self.boxes[i].y,
            w: self.boxes[i].w,
            h: self.boxes[i].h,
        }
    }
}
<commit_msg>add threadpool object<commit_after>//! Bindings for Darknet

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unused_import_braces)]
#![deny(unused_qualifications)]

#[macro_use]
extern crate failure;

/// FFI bindings.
pub mod ffi {
    #![allow(missing_docs)]
    #![allow(missing_debug_implementations)]
    #![allow(missing_copy_implementations)]
    #![allow(trivial_casts)]
    #![allow(trivial_numeric_casts)]
    #![allow(unused_import_braces)]
    #![allow(unused_qualifications)]
    #![allow(dead_code)]
    #![allow(non_upper_case_globals)]
    #![allow(non_camel_case_types)]
    #![allow(non_snake_case)]

    #[cfg(feature = "gen")]
    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

    #[cfg(not(feature = "gen"))]
    #[cfg(target_os = "macos")]
    include!("ffi_osx.rs");

    #[cfg(not(feature = "gen"))]
    #[cfg(not(feature = "nnpack"))]
    #[cfg(target_os = "linux")]
    include!("ffi_linux.rs");

    #[cfg(not(feature = "gen"))]
    #[cfg(feature = "nnpack")]
    #[cfg(target_os = "linux")]
    include!("ffi_linux_nnpack.rs");
}

use std::ffi::{CStr, CString};
use std::path::Path;
pub use failure::Error;

mod errors {
    use std::path::PathBuf;

    #[derive(Debug, Fail)]
    /// Custom errors.
    pub enum DarknetError {
        #[fail(display = "invalid path: {:?}", _0)]
        /// Indicates that path was invalid
        InvalidPath(PathBuf),
    }
}

/// Network
#[derive(Debug)]
pub struct Network {
    net: *mut ffi::network,
    nnp_status: bool,
}

/// Threadpool.
#[cfg(feature = "nnpack")]
#[derive(Debug)]
pub struct ThreadPool {
    inner: ffi::pthreadpool_t,
}

impl Network {
    /// Create a new network.
    pub fn new<P: AsRef<Path>>(config: P, weight: P) -> Result<Self, Error> {
        let config = path_to_cstring(config)?.into_raw();
        let weight = path_to_cstring(weight)?.into_raw();
        let net = unsafe { ffi::load_network(config, weight, 0) };
        Ok(Network {
            net: net,
            nnp_status: false,
        })
    }

    #[cfg(feature = "nnpack")]
    /// Initializes the network with a threadpool.
    pub fn create_threadpool(&mut self, n: usize) {
        if !self.nnp_status {
            unsafe { ffi::nnp_initialize() };
            self.nnp_status = true;
        }

        unsafe { (*self.net).threadpool = ffi::pthreadpool_create(n) }
    }

    #[cfg(feature = "nnpack")]
    /// Return a reference to the thread pool.
    pub fn threadpool(&mut self) -> ThreadPool {
        ThreadPool {
            inner: self.net.threadpool,
        }
    }

    /// Return the width of the network.
    pub fn width(&self) -> usize {
        unsafe { ffi::network_width(self.net) as usize }
    }

    /// Return the height of the network.
    pub fn height(&self) -> usize {
        unsafe { ffi::network_height(self.net) as usize }
    }

    /// Perform prediction.
    pub fn predict(&self, data: *mut f32) -> *mut f32 {
        unsafe { ffi::network_predict(self.net, data) }
    }

    /// Perform prediction.
    pub fn predict_image(&self, image: &Image) -> *mut f32 {
        unsafe { ffi::network_predict_image(self.net, image.0) }
    }

    /// Get the network boxes.
    fn get_network_boxes(&self, w: i32, h: i32, thresh: f32, hier: f32) -> Detections_ {
        let mut num = 0;
        let det = unsafe {
            ffi::get_network_boxes(
                self.net,
                w,
                h,
                thresh,
                hier,
                std::ptr::null_mut(),
                0,
                &mut num,
            )
        };
        Detections_ {
            inner: det,
            num: num,
        }
    }
}

impl Drop for Network {
    #[cfg(not(feature = "nnpack"))]
    fn drop(&mut self) {
        unsafe {
            ffi::free_network(self.net);
        }
    }

    #[cfg(feature = "nnpack")]
    fn drop(&mut self) {
        if self.nnp_status {
            unsafe {
                ffi::pthreadpool_destroy((*self.net).threadpool);
                ffi::nnp_deinitialize();
            }
        }
        unsafe {
            ffi::free_network(self.net);
        }
    }
}

fn path_to_cstring<P: AsRef<Path>>(path: P) -> Result<CString, Error> {
    let path = path.as_ref();
    let x = path.to_str()
        .ok_or(errors::DarknetError::InvalidPath(path.into()))?;
    let result = CString::new(x)?;
    Ok(result)
}

/// Perform simple detection with default threshold.
#[inline]
pub fn simple_detect(network: &Network, meta: &Meta, image: &Image) -> Vec<Detection> {
    let thres = 0.5;
    let hier_thresh = 0.5;
    let nms = 0.45;
    detect(network, meta, image, thres, hier_thresh, nms)
}

/// Perform detection.
pub fn detect(
    network: &Network,
    meta: &Meta,
    image: &Image,
    thresh: f32,
    hier_thresh: f32,
    nms: f32,
) -> Vec<Detection> {
    network.predict_image(image);
    let dets = network.get_network_boxes(image.0.w, image.0.h, thresh, hier_thresh);
    let detections = dets.postprocess(nms, meta);
    detections
}

/// A rectangle type.
pub type Rect = ffi::box_;

/// Detection. Note that the bounding box is centered at (x, y) and have width
/// `w` and height `h`.
#[derive(Debug, Clone)]
pub struct Detection {
    /// The class.
    pub class: i32,
    /// x coordinate.
    pub x: f32,
    /// y coordinate.
    pub y: f32,
    /// width.
    pub w: f32,
    /// height.
    pub h: f32,
    /// probability.
    pub prob: f32,
    /// name.
    pub name: String,
}

/// Internal Detection.
#[derive(Debug)]
struct Detections_ {
    inner: *mut ffi::detection,
    num: i32,
}

impl Drop for Detections_ {
    fn drop(&mut self) {
        unsafe {
            ffi::free_detections(self.inner, self.num);
        }
    }
}

impl Detections_ {
    /// Non-maximum suppression.
    fn nms(&self, total: i32, classes: i32, thresh: f32) {
        unsafe {
            ffi::do_nms_obj(self.inner, total, classes, thresh);
        }
    }

    /// Filter detection.
    pub fn postprocess(&self, nms: f32, meta: &Meta) -> Vec<Detection> {
        if nms > 0.0 {
            self.nms(self.num, meta.num_classes(), nms);
        }

        let mut res = Vec::new();
        for j in 0..(self.num as isize) {
            let d = unsafe { *self.inner.offset(j) };
            let bbox = d.bbox;
            let probs = d.prob;
            for i in 0..(meta.num_classes() as isize) {
                let p = unsafe { *probs.offset(i) };
                if p > 0.0 {
                    let ffi::box_ { x, y, w, h } = bbox;
                    res.push(Detection {
                        class: i as i32,
                        x: x,
                        y: y,
                        w: w,
                        h: h,
                        prob: p,
                        name: meta.class_name(i as usize).to_string(),
                    });
                }
            }
        }

        res.sort_by(|a, b| b.prob.partial_cmp(&a.prob).unwrap());
        res
    }
}

/// Metadata.
#[derive(Debug)]
pub struct Meta {
    names: Vec<String>,
}

impl From<ffi::metadata> for Meta {
    fn from(meta: ffi::metadata) -> Self {
        let names = (0..(meta.classes as isize))
            .map(|i| unsafe {
                CStr::from_ptr(*(meta.names.offset(i)))
                    .to_string_lossy()
                    .into_owned()
            })
            .collect();
        Meta { names: names }
    }
}

impl Meta {
    /// Load a new metadata.
    pub fn new<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let meta = unsafe { ffi::get_metadata(filename) };
        Ok(meta.into())
    }

    /// Return the number of classes.
    pub fn num_classes(&self) -> i32 {
        self.names.len() as i32
    }

    /// Return the class name identified by the classification index.
    pub fn class_name(&self, i: usize) -> &str {
        &self.names[i]
    }
}

/// Image
#[derive(Debug, Clone)]
pub struct Image(pub ffi::image);

unsafe impl Send for Image {}

impl Image {
    /// Create a new image.
    pub fn new(w: i32, h: i32, c: i32) -> Self {
        Image(unsafe { ffi::make_image(w, h, c) })
    }

    /// Load a new image.
    pub fn load<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe { ffi::load_image(filename, 0, 0, 0) };
        Ok(Image(img))
    }

    /// Load a new image with color.
    pub fn load_color<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe { ffi::load_image_color(filename, 0, 0) };
        Ok(Image(img))
    }

    /// Load a new image with multiple threads.
    #[cfg(feature = "nnpack")]
    pub fn load_threaded<P: AsRef<Path>>(
        filename: P,
        channel: i32,
        pool: &ThreadPool,
    ) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let img = unsafe { ffi::load_image_thread(filename, 0, 0, c, pool.inner) };
        Ok(Image(img))
    }

    /// Decode a new image (always color, 3 channels).
    pub fn decode_jpg(buf: &[u8]) -> Self {
        let image = unsafe { ffi::decode_image_jpg(buf.as_ptr(), buf.len() as i32, 3) };
        Image(image)
    }

    /// Draw a box based on the detection.
    pub fn draw_box(&mut self, d: &Detection, w: i32, r: f32, g: f32, b: f32) {
        let x1 = d.x - d.w / 2.;
        let x2 = d.x + d.w / 2.;
        let y1 = d.y - d.h / 2.;
        let y2 = d.y + d.h / 2.;

        unsafe {
            ffi::draw_box_width(
                self.0,
                x1 as i32,
                y1 as i32,
                x2 as i32,
                y2 as i32,
                w,
                r,
                g,
                b,
            )
        }
    }

    /// Save the image.
    pub fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        unsafe { ffi::save_image(self.0, filename) };
        Ok(())
    }

    /// Save the image as jpg.
    pub fn save_jpg<P: AsRef<Path>>(&self, filename: P) -> Result<(), Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        unsafe { ffi::save_image_jpg(self.0, filename) };
        Ok(())
    }

    /// Save the image as jpg.
    pub fn encode_jpg(&self) -> Vec<u8> {
        let cap = (self.0.w * self.0.h * self.0.c) as usize;
        let mut data: Vec<u8> = Vec::with_capacity(cap);
        let size = unsafe { ffi::encode_image_jpg(self.0, data.as_ptr()) };
        unsafe {
            data.set_len(size as usize);
        }

        data
    }

    /// Resize and return a new image.
    pub fn resize(&self, w: i32, h: i32) -> Image {
        Image(unsafe { ffi::resize_image(self.0, w, h) })
    }

    /// Image width.
    pub fn width(&self) -> i32 {
        self.0.w
    }

    /// Image height.
    pub fn height(&self) -> i32 {
        self.0.h
    }

    /// Image channel.
    pub fn channel(&self) -> i32 {
        self.0.c
    }
}

impl Drop for Image {
    fn drop(&mut self) {
        unsafe {
            ffi::free_image(self.0);
        }
    }
}

/// Groundtruth.
#[derive(Debug)]
pub struct Groundtruth {
    boxes: Vec<ffi::box_label>,
}

impl Groundtruth {
    /// Load a new label.
    pub fn load<P: AsRef<Path>>(filename: P) -> Result<Self, Error> {
        let filename = path_to_cstring(filename)?.into_raw();
        let mut num = 0;
        let truth = unsafe { ffi::read_boxes(filename, &mut num) };

        let truth = (0..num)
            .map(|i| unsafe { *(truth.offset(i as isize)) })
            .collect();
        Ok(Groundtruth { boxes: truth })
    }

    /// Return the rectangle box at a particular index.
    pub fn box_at(&self, i: usize) -> Rect {
        Rect {
            x: self.boxes[i].x,
            y: self.boxes[i].y,
            w: self.boxes[i].w,
            h: self.boxes[i].h,
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core_intrinsics, op_assign_traits, augmented_assignments)]
#![cfg_attr(test, feature(test))]

extern crate typenum;

pub mod array;
pub mod cipher;
pub mod keyed;
pub mod secret;

mod rotate;
mod wrapping;
mod nodrop;
mod truncate;
mod signs;
<commit_msg>Remove unneeded feature flags<commit_after>#![feature(core_intrinsics)]
#![cfg_attr(test, feature(test))]

extern crate typenum;

pub mod array;
pub mod cipher;
pub mod keyed;
pub mod secret;

mod rotate;
mod wrapping;
mod nodrop;
mod truncate;
mod signs;
<|endoftext|>


<commit_before>use std::slice::raw::buf_as_slice;
use std::str::raw::c_str_to_static_slice;
use libc::{c_char, c_uint, c_void, ptrdiff_t, size_t};
use libc;

use {encode, Encode};

pub enum Object { }

pub struct Sel {
	ptr: *const c_void,
}

pub enum Ivar { }

pub enum Method { }

pub enum Class { }

pub type Imp = extern fn(*mut Object, Sel, ...) -> *mut Object;

#[link(name = "Foundation", kind = "framework")]
extern {
	pub fn sel_registerName(name: *const c_char) -> Sel;
	pub fn sel_getName(sel: Sel) -> *const c_char;

	pub fn objc_getClass(name: *const c_char) -> *const Class;
	pub fn class_getName(cls: *const Class) -> *const c_char;
	pub fn class_getInstanceSize(cls: *const Class) -> size_t;
	pub fn class_getInstanceMethod(cls: *const Class, sel: Sel) -> *const Method;
	pub fn class_getInstanceVariable(cls: *const Class, name: *const c_char) -> *const Ivar;
	pub fn class_copyIvarList(cls: *const Class, outCount: *mut c_uint) -> *mut *const Ivar;
	pub fn class_addMethod(cls: *mut Class, name: Sel, imp: Imp, types: *const c_char) -> bool;
	pub fn class_addIvar(cls: *mut Class, name: *const c_char, size: size_t, alignment: u8, types: *const c_char) -> bool;

	pub fn objc_allocateClassPair(superclass: *const Class, name: *const c_char, extraBytes: size_t) -> *mut Class;
	pub fn objc_disposeClassPair(cls: *mut Class);
	pub fn objc_registerClassPair(cls: *mut Class);

	pub fn object_getClass(obj: *const Object) -> *const Class;

	pub fn ivar_getName(ivar: *const Ivar) -> *const c_char;
	pub fn ivar_getOffset(ivar: *const Ivar) -> ptrdiff_t;
	pub fn ivar_getTypeEncoding(ivar: *const Ivar) -> *const c_char;

	pub fn objc_msgSend(obj: *mut Object, op: Sel, ...) -> *mut Object;

	pub fn method_getName(method: *const Method) -> Sel;
	pub fn method_getImplementation(method: *const Method) -> Imp;
	pub fn method_getTypeEncoding(method: *const Method) -> *const c_char;
	pub fn method_getNumberOfArguments(method: *const Method) -> c_uint;
	pub fn method_setImplementation(method: *mut Method, imp: Imp) -> Imp;
	pub fn method_exchangeImplementations(m1: *mut Method, m2: *mut Method);
}

impl Sel {
	pub fn register(name: &str) -> Sel {
		name.with_c_str(|name| unsafe {
			sel_registerName(name)
		})
	}

	pub fn name(&self) -> &str {
		unsafe {
			let name = sel_getName(*self);
			c_str_to_static_slice(name)
		}
	}
}

impl PartialEq for Sel {
	fn eq(&self, other: &Sel) -> bool {
		self.ptr == other.ptr
	}
}

impl Eq for Sel { }

impl Clone for Sel {
	fn clone(&self) -> Sel { *self }
}

impl Ivar {
	pub fn name(&self) -> &str {
		unsafe {
			let name = ivar_getName(self);
			c_str_to_static_slice(name)
		}
	}

	pub fn offset(&self) -> int {
		let offset = unsafe {
			ivar_getOffset(self)
		};
		offset as int
	}

	pub fn type_encoding(&self) -> &str {
		unsafe {
			let encoding = ivar_getTypeEncoding(self);
			c_str_to_static_slice(encoding)
		}
	}
}

impl Method {
	pub fn name(&self) -> Sel {
		unsafe {
			method_getName(self)
		}
	}

	pub fn type_encoding(&self) -> &str {
		unsafe {
			let encoding = method_getTypeEncoding(self);
			c_str_to_static_slice(encoding)
		}
	}

	pub fn arguments(&self) -> uint {
		unsafe {
			method_getNumberOfArguments(self) as uint
		}
	}

	pub fn implementation(&self) -> Imp {
		unsafe {
			method_getImplementation(self)
		}
	}

	pub unsafe fn set_implementation(&mut self, imp: Imp) -> Imp {
		method_setImplementation(self, imp)
	}

	pub unsafe fn exchange_implementation(&mut self, other: &mut Method) {
		method_exchangeImplementations(self, other);
	}
}

impl Object {
	pub fn class(&self) -> &'static Class {
		unsafe {
			&*object_getClass(self)
		}
	}

	pub unsafe fn get_ivar<T: Encode>(&self, name: &str) -> &T {
		let cls = self.class();
		let ptr = match cls.instance_variable(name) {
			Some(ivar) => {
				assert!(ivar.type_encoding() == encode::<T>());
				let offset = ivar.offset();
				let self_ptr = self as *const Object;
				(self_ptr as *const u8).offset(offset) as *const T
			}
			None => fail!("Ivar {} not found on class {}", name, cls.name()),
		};
		&*ptr
	}

	pub unsafe fn get_mut_ivar<T: Encode>(&mut self, name: &str) -> &mut T {
		let cls = self.class();
		let ptr = match cls.instance_variable(name) {
			Some(ivar) => {
				assert!(ivar.type_encoding() == encode::<T>());
				let offset = ivar.offset();
				let self_ptr = self as *mut Object;
				(self_ptr as *mut u8).offset(offset) as *mut T
			}
			None => fail!("Ivar {} not found on class {}", name, cls.name()),
		};
		&mut *ptr
	}

	pub unsafe fn set_ivar<T: Encode>(&mut self, name: &str, value: T) {
		*self.get_mut_ivar::<T>(name) = value;
	}
}

impl Class {
	pub fn get(name: &str) -> Option<&'static Class> {
		let cls = name.with_c_str(|name| unsafe {
			objc_getClass(name)
		});
		if cls.is_null() {
			None
		} else {
			Some(unsafe { &*cls })
		}
	}

	pub fn name(&self) -> &str {
		unsafe {
			let name = class_getName(self);
			c_str_to_static_slice(name)
		}
	}

	pub fn instance_size(&self) -> uint {
		unsafe {
			class_getInstanceSize(self) as uint
		}
	}

	pub fn instance_method(&self, sel: Sel) -> Option<&Method> {
		let method = unsafe {
			class_getInstanceMethod(self, sel)
		};
		if method.is_null() {
			None
		} else {
			Some(unsafe { &*method })
		}
	}

	pub fn instance_variable(&self, name: &str) -> Option<&Ivar> {
		let ivar = name.with_c_str(|name| unsafe {
			class_getInstanceVariable(self, name)
		});
		if ivar.is_null() {
			None
		} else {
			Some(unsafe { &*ivar })
		}
	}

	pub fn instance_variables(&self) -> Vec<&Ivar> {
		unsafe {
			let mut count: c_uint = 0;
			let ivars = class_copyIvarList(self, &mut count);
			let vec = buf_as_slice(ivars as *const _, count as uint, |ivars| {
				ivars.to_vec()
			});
			libc::free(ivars as *mut c_void);
			vec
		}
	}
}

pub trait Message { }

impl Message for Object { }

impl Message for Class { }

pub trait ToMessage {
	fn as_ptr(&self) -> *mut Object;

	fn is_nil(&self) -> bool {
		self.as_ptr().is_null()
	}
}

impl<T: Message> ToMessage for *mut T {
	fn as_ptr(&self) -> *mut Object {
		*self as *mut Object
	}
}

impl<'a, T: Message> ToMessage for &'a T {
	fn as_ptr(&self) -> *mut Object {
		(*self as *const T as *mut T).as_ptr()
	}
}
<commit_msg>Rearranging runtime module for consistency.<commit_after>use std::slice::raw::buf_as_slice;
use std::str::raw::c_str_to_static_slice;
use libc::{c_char, c_uint, c_void, ptrdiff_t, size_t};
use libc;

use {encode, Encode};

pub struct Sel {
	ptr: *const c_void,
}

pub enum Ivar { }

pub enum Method { }

pub enum Class { }

pub enum Object { }

pub type Imp = extern fn(*mut Object, Sel, ...) -> *mut Object;

#[link(name = "Foundation", kind = "framework")]
extern {
	pub fn sel_registerName(name: *const c_char) -> Sel;
	pub fn sel_getName(sel: Sel) -> *const c_char;

	pub fn objc_getClass(name: *const c_char) -> *const Class;
	pub fn class_getName(cls: *const Class) -> *const c_char;
	pub fn class_getInstanceSize(cls: *const Class) -> size_t;
	pub fn class_getInstanceMethod(cls: *const Class, sel: Sel) -> *const Method;
	pub fn class_getInstanceVariable(cls: *const Class, name: *const c_char) -> *const Ivar;
	pub fn class_copyIvarList(cls: *const Class, outCount: *mut c_uint) -> *mut *const Ivar;
	pub fn class_addMethod(cls: *mut Class, name: Sel, imp: Imp, types: *const c_char) -> bool;
	pub fn class_addIvar(cls: *mut Class, name: *const c_char, size: size_t, alignment: u8, types: *const c_char) -> bool;

	pub fn objc_allocateClassPair(superclass: *const Class, name: *const c_char, extraBytes: size_t) -> *mut Class;
	pub fn objc_disposeClassPair(cls: *mut Class);
	pub fn objc_registerClassPair(cls: *mut Class);

	pub fn object_getClass(obj: *const Object) -> *const Class;

	pub fn ivar_getName(ivar: *const Ivar) -> *const c_char;
	pub fn ivar_getOffset(ivar: *const Ivar) -> ptrdiff_t;
	pub fn ivar_getTypeEncoding(ivar: *const Ivar) -> *const c_char;

	pub fn objc_msgSend(obj: *mut Object, op: Sel, ...) -> *mut Object;

	pub fn method_getName(method: *const Method) -> Sel;
	pub fn method_getImplementation(method: *const Method) -> Imp;
	pub fn method_getTypeEncoding(method: *const Method) -> *const c_char;
	pub fn method_getNumberOfArguments(method: *const Method) -> c_uint;
	pub fn method_setImplementation(method: *mut Method, imp: Imp) -> Imp;
	pub fn method_exchangeImplementations(m1: *mut Method, m2: *mut Method);
}

impl Sel {
	pub fn register(name: &str) -> Sel {
		name.with_c_str(|name| unsafe {
			sel_registerName(name)
		})
	}

	pub fn name(&self) -> &str {
		unsafe {
			let name = sel_getName(*self);
			c_str_to_static_slice(name)
		}
	}
}

impl PartialEq for Sel {
	fn eq(&self, other: &Sel) -> bool {
		self.ptr == other.ptr
	}
}

impl Eq for Sel { }

impl Clone for Sel {
	fn clone(&self) -> Sel { *self }
}

impl Ivar {
	pub fn name(&self) -> &str {
		unsafe {
			let name = ivar_getName(self);
			c_str_to_static_slice(name)
		}
	}

	pub fn offset(&self) -> int {
		let offset = unsafe {
			ivar_getOffset(self)
		};
		offset as int
	}

	pub fn type_encoding(&self) -> &str {
		unsafe {
			let encoding = ivar_getTypeEncoding(self);
			c_str_to_static_slice(encoding)
		}
	}
}

impl Method {
	pub fn name(&self) -> Sel {
		unsafe {
			method_getName(self)
		}
	}

	pub fn type_encoding(&self) -> &str {
		unsafe {
			let encoding = method_getTypeEncoding(self);
			c_str_to_static_slice(encoding)
		}
	}

	pub fn arguments(&self) -> uint {
		unsafe {
			method_getNumberOfArguments(self) as uint
		}
	}

	pub fn implementation(&self) -> Imp {
		unsafe {
			method_getImplementation(self)
		}
	}

	pub unsafe fn set_implementation(&mut self, imp: Imp) -> Imp {
		method_setImplementation(self, imp)
	}

	pub unsafe fn exchange_implementation(&mut self, other: &mut Method) {
		method_exchangeImplementations(self, other);
	}
}

impl Class {
	pub fn get(name: &str) -> Option<&'static Class> {
		let cls = name.with_c_str(|name| unsafe {
			objc_getClass(name)
		});
		if cls.is_null() {
			None
		} else {
			Some(unsafe { &*cls })
		}
	}

	pub fn name(&self) -> &str {
		unsafe {
			let name = class_getName(self);
			c_str_to_static_slice(name)
		}
	}

	pub fn instance_size(&self) -> uint {
		unsafe {
			class_getInstanceSize(self) as uint
		}
	}

	pub fn instance_method(&self, sel: Sel) -> Option<&Method> {
		let method = unsafe {
			class_getInstanceMethod(self, sel)
		};
		if method.is_null() {
			None
		} else {
			Some(unsafe { &*method })
		}
	}

	pub fn instance_variable(&self, name: &str) -> Option<&Ivar> {
		let ivar = name.with_c_str(|name| unsafe {
			class_getInstanceVariable(self, name)
		});
		if ivar.is_null() {
			None
		} else {
			Some(unsafe { &*ivar })
		}
	}

	pub fn instance_variables(&self) -> Vec<&Ivar> {
		unsafe {
			let mut count: c_uint = 0;
			let ivars = class_copyIvarList(self, &mut count);
			let vec = buf_as_slice(ivars as *const _, count as uint, |ivars| {
				ivars.to_vec()
			});
			libc::free(ivars as *mut c_void);
			vec
		}
	}
}

impl Object {
	pub fn class(&self) -> &'static Class {
		unsafe {
			&*object_getClass(self)
		}
	}

	pub unsafe fn get_ivar<T: Encode>(&self, name: &str) -> &T {
		let cls = self.class();
		let ptr = match cls.instance_variable(name) {
			Some(ivar) => {
				assert!(ivar.type_encoding() == encode::<T>());
				let offset = ivar.offset();
				let self_ptr = self as *const Object;
				(self_ptr as *const u8).offset(offset) as *const T
			}
			None => fail!("Ivar {} not found on class {}", name, cls.name()),
		};
		&*ptr
	}

	pub unsafe fn get_mut_ivar<T: Encode>(&mut self, name: &str) -> &mut T {
		let cls = self.class();
		let ptr = match cls.instance_variable(name) {
			Some(ivar) => {
				assert!(ivar.type_encoding() == encode::<T>());
				let offset = ivar.offset();
				let self_ptr = self as *mut Object;
				(self_ptr as *mut u8).offset(offset) as *mut T
			}
			None => fail!("Ivar {} not found on class {}", name, cls.name()),
		};
		&mut *ptr
	}

	pub unsafe fn set_ivar<T: Encode>(&mut self, name: &str, value: T) {
		*self.get_mut_ivar::<T>(name) = value;
	}
}

pub trait Message { }

impl Message for Object { }

impl Message for Class { }

pub trait ToMessage {
	fn as_ptr(&self) -> *mut Object;

	fn is_nil(&self) -> bool {
		self.as_ptr().is_null()
	}
}

impl<T: Message> ToMessage for *mut T {
	fn as_ptr(&self) -> *mut Object {
		*self as *mut Object
	}
}

impl<'a, T: Message> ToMessage for &'a T {
	fn as_ptr(&self) -> *mut Object {
		(*self as *const T as *mut T).as_ptr()
	}
}
<|endoftext|>


<commit_before>//! Tracks minimal sets of mutually incomparable elements of a partial order.

use std::default::Default;
use std::cmp::Ordering;

use progress::CountMap;

/// A set of mutually incomparable elements.
#[derive(Default, Clone, Debug)]
pub struct Antichain<T> {
    elements: Vec<T>
}

impl<T: PartialOrd> Antichain<T> {
    /// Updates the `Antichain` if the element is not greater than or equal to some present element.
    ///
    /// Returns true if element is added to the set
    pub fn insert(&mut self, element: T) -> bool {
        // bail if any element exceeds the candidate
        if self.elements.iter().any(|x| element.ge(x)) {
            return false;
        }
        let mut removed = 0;
        for index in 0..self.elements.len() {
            let new_index = index - removed;
            if element.lt(&self.elements[new_index]) {
                self.elements.swap_remove(new_index);
                removed += 1;
            }
        }

        self.elements.push(element);
        true
    }

    /// Creates a new empty `Antichain`.
    pub fn new() -> Antichain<T> { Antichain { elements: Vec::new() } }

    /// Creates a new singleton `Antichain`.
    pub fn from_elem(element: T) -> Antichain<T> { Antichain { elements: vec![element] } }

    /// Reveals the elements in the `Antichain`.
    pub fn elements(&self) -> &[T] { &self.elements[..] }
}

/// An antichain based on a multiset whose elements frequencies can be updated.
///
/// In particular, unlike `Antichain`, element frequencies can be decremented, removing elements in
/// the antichain and revealing other elements that were previously obscured.
/// As part of this, the `MutableAntichain` must maintain the frequences for all elements, not just
/// those in the antichain at the moment.
#[derive(Default, Debug, Clone)]
pub struct MutableAntichain<T:Eq> {
    occurrences:    CountMap<T>,    // occurrence count of each time
    precedents:     Vec<(T, i64)>,  // counts number of distinct times in occurences strictly less than element
    elements:       Vec<T>,         // the set of times with precedent count == 0
}

impl<T: PartialOrd+Eq+Clone+'static> MutableAntichain<T> {
    /// Creates a new empty `MutableAntichain`.
    pub fn new() -> MutableAntichain<T> {
        MutableAntichain {
            occurrences:    Default::default(),
            precedents:     Default::default(),
            elements:       Vec::new(),
        }
    }

    /// Removes all elements from the antichain.
    pub fn clear(&mut self) {
        self.occurrences.clear();
        self.precedents.clear();
        self.elements.clear();
    }

    /// Reveals the element in the `MutableAntichain`.
    pub fn elements(&self) -> &[T] { &self.elements }

    /// Creates a new singleton `MutableAntichain`.
    pub fn new_bottom(bottom: T) -> MutableAntichain<T> {
        let mut result = MutableAntichain::new();
        result.update_weight(&bottom, 1, &mut Default::default());
        result
    }

    /// Returns true if there are no elements in the `MutableAntichain`.
    pub fn empty(&self) -> bool { self.elements.is_empty() }

    /// Returns true if any item in the `MutableAntichain` is strictly less than the argument.
    #[inline]
    pub fn lt(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.lt(time))
    }

    /// Returns true if any item in the `MutableAntichain` is less than or equal to the argument.
    #[inline]
    pub fn le(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.le(time))
    }

    /// Returns the number of times an element exists in the set.
    #[inline]
    pub fn count(&self, time: &T) -> Option<i64> {
        self.occurrences.iter().filter(|x| time.eq(&x.0)).next().map(|i| i.1)
    }

    // TODO : Four different versions of basically the same code. Fix that!
    // TODO : Should this drain updates through to the CM? Check out uses!
    /// Incorporates `updates` into the antichain, pushing frontier changes into `results`.
    pub fn update_into_cm(&mut self, updates: &CountMap<T>, results: &mut CountMap<T>) -> () {
        self.update_iter_and(updates.iter().cloned(), |time, val| { results.update(time, val); });
    }

    /// Performs a single update to the antichain, pushing frontier changes into `results`.
    pub fn update_weight(&mut self, elem: &T, delta: i64, results: &mut CountMap<T>) -> () {
        self.update_and(elem, delta, |time, delta| { results.update(time, delta); });
    }

    /// Applies a single update to the antichain.
    #[inline] pub fn update(&mut self, elem: &T, delta: i64) { self.update_and(elem, delta, |_,_| {}); }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    //#[inline(always)]
    pub fn update_iter_and<I: Iterator<Item = (T, i64)>,
                           A: FnMut(&T, i64) -> ()>(&mut self, updates: I, mut action: A) -> () {
        for (ref elem, delta) in updates {
            self.update_and(elem, delta, |t,d| action(t,d));
        }
    }

    /// Tests the size of the antichain against a threshould.
    ///
    /// This is a diagnostic method in place to observe when antichains become surprisingly large.
    /// If either `self.occurrences` or `self.precedents` exceeds the threshold, they are listed.
    #[inline]
    pub fn test_size(&self, threshold: usize, name: &str) {
        if self.occurrences.len() > threshold {
            println!("{}:\toccurrences:\tlen() = {}", name, self.occurrences.len());
            // for &(ref key, val) in self.occurrences.elements().iter() { println!("{}: \toccurrence: {:?} : {:?}", name, key, val); }
            // panic!();
        }
        if self.precedents.len() > threshold {
            println!("{}: precedents:\tlen() = {}", name, self.precedents.len());
        }
    }

    /// Applies an update to the antichain and takes an action on any frontier changes.
    #[inline]
    pub fn update_and<A: FnMut(&T, i64)->()>(&mut self, elem: &T, delta: i64, mut action: A) -> () {

        if delta != 0 {
            // self.test_size(100, "???");
            let new_value = self.occurrences.update(elem, delta);
            let old_value = new_value - delta;

            // if the value went from non-positive to positive we need to update self.precedents
            if old_value <= 0 && new_value > 0 {
                let mut preceded_by = 0;

                // maintain precedent counts relative to the set
                for &mut (ref key, ref mut val) in &mut self.precedents {
                    if let Some(comparison) = elem.partial_cmp(key) {
                        match comparison {
                            Ordering::Less    => {
                                if *val == 0 {
                                    self.elements.retain(|x| x != key);
                                    action(key, -1);
                                }
                                *val += 1;
                            },
                            Ordering::Equal   => { panic!("surprising!"); },
                            Ordering::Greater => { preceded_by += 1; },
                        }
                    }
                }

                // insert count always; maybe put in elements
                self.precedents.push((elem.clone(), preceded_by));
                if preceded_by == 0 {
                    self.elements.push(elem.clone());
                    action(elem, 1);
                }
            }

            // if the value went from positive to non-positive we need to update self.precedents.
            if old_value > 0 && new_value <= 0 {
                // maintain precedent counts relative to the set
                for &mut (ref key, ref mut val) in &mut self.precedents {
                    if elem < key {
                        *val -= 1;
                        if *val == 0 {
                            self.elements.push(key.clone());
                            action(key, 1);
                        }
                    }
                }

                if let Some(position) = self.elements.iter().position(|x| x == elem) {
                    action(elem, -1);
                    self.elements.swap_remove(position);
                }

                self.precedents.retain(|x| &x.0 != elem);
            }
        }
    }
}
<commit_msg>added a clear method to antichain<commit_after>//! Tracks minimal sets of mutually incomparable elements of a partial order.

use std::default::Default;
use std::cmp::Ordering;

use progress::CountMap;

/// A set of mutually incomparable elements.
#[derive(Default, Clone, Debug)]
pub struct Antichain<T> {
    elements: Vec<T>
}

impl<T: PartialOrd> Antichain<T> {
    /// Updates the `Antichain` if the element is not greater than or equal to some present element.
    ///
    /// Returns true if element is added to the set
    pub fn insert(&mut self, element: T) -> bool {
        // bail if any element exceeds the candidate
        if self.elements.iter().any(|x| element.ge(x)) {
            return false;
        }
        let mut removed = 0;
        for index in 0..self.elements.len() {
            let new_index = index - removed;
            if element.lt(&self.elements[new_index]) {
                self.elements.swap_remove(new_index);
                removed += 1;
            }
        }

        self.elements.push(element);
        true
    }

    /// Creates a new empty `Antichain`.
    pub fn new() -> Antichain<T> { Antichain { elements: Vec::new() } }

    /// Creates a new singleton `Antichain`.
    pub fn from_elem(element: T) -> Antichain<T> { Antichain { elements: vec![element] } }

    /// Clears the contents of the antichain.
    pub fn clear(&mut self) { self.elements.clear() }

    /// Reveals the elements in the antichain.
    pub fn elements(&self) -> &[T] { &self.elements[..] }
}

/// An antichain based on a multiset whose elements frequencies can be updated.
///
/// In particular, unlike `Antichain`, element frequencies can be decremented, removing elements in
/// the antichain and revealing other elements that were previously obscured.
/// As part of this, the `MutableAntichain` must maintain the frequences for all elements, not just
/// those in the antichain at the moment.
#[derive(Default, Debug, Clone)]
pub struct MutableAntichain<T:Eq> {
    occurrences:    CountMap<T>,    // occurrence count of each time
    precedents:     Vec<(T, i64)>,  // counts number of distinct times in occurences strictly less than element
    elements:       Vec<T>,         // the set of times with precedent count == 0
}

impl<T: PartialOrd+Eq+Clone+'static> MutableAntichain<T> {
    /// Creates a new empty `MutableAntichain`.
    pub fn new() -> MutableAntichain<T> {
        MutableAntichain {
            occurrences:    Default::default(),
            precedents:     Default::default(),
            elements:       Vec::new(),
        }
    }

    /// Removes all elements from the antichain.
    pub fn clear(&mut self) {
        self.occurrences.clear();
        self.precedents.clear();
        self.elements.clear();
    }

    /// Reveals the element in the `MutableAntichain`.
    pub fn elements(&self) -> &[T] { &self.elements }

    /// Creates a new singleton `MutableAntichain`.
    pub fn new_bottom(bottom: T) -> MutableAntichain<T> {
        let mut result = MutableAntichain::new();
        result.update_weight(&bottom, 1, &mut Default::default());
        result
    }

    /// Returns true if there are no elements in the `MutableAntichain`.
    pub fn empty(&self) -> bool { self.elements.is_empty() }

    /// Returns true if any item in the `MutableAntichain` is strictly less than the argument.
    #[inline]
    pub fn lt(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.lt(time))
    }

    /// Returns true if any item in the `MutableAntichain` is less than or equal to the argument.
    #[inline]
    pub fn le(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.le(time))
    }

    /// Returns the number of times an element exists in the set.
    #[inline]
    pub fn count(&self, time: &T) -> Option<i64> {
        self.occurrences.iter().filter(|x| time.eq(&x.0)).next().map(|i| i.1)
    }

    // TODO : Four different versions of basically the same code. Fix that!
    // TODO : Should this drain updates through to the CM? Check out uses!
    /// Incorporates `updates` into the antichain, pushing frontier changes into `results`.
    pub fn update_into_cm(&mut self, updates: &CountMap<T>, results: &mut CountMap<T>) -> () {
        self.update_iter_and(updates.iter().cloned(), |time, val| { results.update(time, val); });
    }

    /// Performs a single update to the antichain, pushing frontier changes into `results`.
    pub fn update_weight(&mut self, elem: &T, delta: i64, results: &mut CountMap<T>) -> () {
        self.update_and(elem, delta, |time, delta| { results.update(time, delta); });
    }

    /// Applies a single update to the antichain.
    #[inline] pub fn update(&mut self, elem: &T, delta: i64) { self.update_and(elem, delta, |_,_| {}); }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    //#[inline(always)]
    pub fn update_iter_and<I: Iterator<Item = (T, i64)>,
                           A: FnMut(&T, i64) -> ()>(&mut self, updates: I, mut action: A) -> () {
        for (ref elem, delta) in updates {
            self.update_and(elem, delta, |t,d| action(t,d));
        }
    }

    /// Tests the size of the antichain against a threshould.
    ///
    /// This is a diagnostic method in place to observe when antichains become surprisingly large.
    /// If either `self.occurrences` or `self.precedents` exceeds the threshold, they are listed.
    #[inline]
    pub fn test_size(&self, threshold: usize, name: &str) {
        if self.occurrences.len() > threshold {
            println!("{}:\toccurrences:\tlen() = {}", name, self.occurrences.len());
            // for &(ref key, val) in self.occurrences.elements().iter() { println!("{}: \toccurrence: {:?} : {:?}", name, key, val); }
            // panic!();
        }
        if self.precedents.len() > threshold {
            println!("{}: precedents:\tlen() = {}", name, self.precedents.len());
        }
    }

    /// Applies an update to the antichain and takes an action on any frontier changes.
    #[inline]
    pub fn update_and<A: FnMut(&T, i64)->()>(&mut self, elem: &T, delta: i64, mut action: A) -> () {

        if delta != 0 {
            // self.test_size(100, "???");
            let new_value = self.occurrences.update(elem, delta);
            let old_value = new_value - delta;

            // if the value went from non-positive to positive we need to update self.precedents
            if old_value <= 0 && new_value > 0 {
                let mut preceded_by = 0;

                // maintain precedent counts relative to the set
                for &mut (ref key, ref mut val) in &mut self.precedents {
                    if let Some(comparison) = elem.partial_cmp(key) {
                        match comparison {
                            Ordering::Less    => {
                                if *val == 0 {
                                    self.elements.retain(|x| x != key);
                                    action(key, -1);
                                }
                                *val += 1;
                            },
                            Ordering::Equal   => { panic!("surprising!"); },
                            Ordering::Greater => { preceded_by += 1; },
                        }
                    }
                }

                // insert count always; maybe put in elements
                self.precedents.push((elem.clone(), preceded_by));
                if preceded_by == 0 {
                    self.elements.push(elem.clone());
                    action(elem, 1);
                }
            }

            // if the value went from positive to non-positive we need to update self.precedents.
            if old_value > 0 && new_value <= 0 {
                // maintain precedent counts relative to the set
                for &mut (ref key, ref mut val) in &mut self.precedents {
                    if elem < key {
                        *val -= 1;
                        if *val == 0 {
                            self.elements.push(key.clone());
                            action(key, 1);
                        }
                    }
                }

                if let Some(position) = self.elements.iter().position(|x| x == elem) {
                    action(elem, -1);
                    self.elements.swap_remove(position);
                }

                self.precedents.retain(|x| &x.0 != elem);
            }
        }
    }
}
<|endoftext|>


<commit_before>use mio::Token;

#[derive(Clone,Copy,PartialEq,Eq)]
pub struct StreamId {
  id: u32,
  token: Token
}

impl StreamId {
  pub fn new(id: u32, token: Token) -> StreamId {
    StreamId {
      id: id,
      token: token
    }
  }

  pub fn token(&self) -> Token {
    self.token
  }
}
<commit_msg>Convenience method for StreamId<commit_after>use mio::Token;

#[derive(Clone,Copy,PartialEq,Eq)]
pub struct StreamId {
  id: u32,
  token: Token
}

impl StreamId {
  pub fn new(id: u32, token: Token) -> StreamId {
    StreamId {
      id: id,
      token: token
    }
  }

  pub fn token(&self) -> Token {
    self.token
  }

  pub fn id(&self) -> u32 {
    self.id
  }
}
<|endoftext|>


<commit_before>use vector::*;
use objects::*;

fn get_normal(object: &Object, collision: Vec3) -> Vec3 {
    match *object {
        Object::Sphere { center: c, radius: _ } => {
            (collision - c).normalized()
        }
    }
}

fn get_ambient_color(material: &Material) -> Color {
    (*material).ambient
}

fn get_diffuse_color(light: &Light, material: &Material,
                     n: Vec3, l: Vec3) -> Color {
    ((*material).diffuse * (*light).color *
        n.dot(l).max(0.0) * (*light).intensity)
}

fn get_specular_color(material: &Material,
                      l: Vec3, v: Vec3, normal: Vec3) -> Color {
    let h = (v + l).normalized();
    (*material).specular * (normal.dot(h).max(0.0).powf((*material).specular_exponent))
}

pub fn get_color(scene: &Scene, materialobject: &MaterialObject,
                 ray: &Ray, t: f64) -> (Color, u64) {
    let (ref object, ref material) = *materialobject;
    let collision = ray.origin + (ray.direction * t);
    let normal = get_normal(object, collision);
    let ambient = get_ambient_color(&material);
    (*scene).lights.iter().fold((ambient, 0), |accum, light| {
        let (prev_color, prev_rays) = accum;
        let direction = (*light).position - collision;
        let new_ray = Ray {
            origin: collision - (direction * 0.00001),
            direction: direction
        };
        let l = (light.position - collision).normalized();
        let v = new_ray.origin - new_ray.direction;

        let diffuse = get_diffuse_color(&light, material, normal, l);
        let specular = get_specular_color(material, l, v, normal);
        (prev_color + diffuse + specular, prev_rays + 1)
    })
}
<commit_msg>Get specular working better (hack)<commit_after>use vector::*;
use objects::*;

fn get_normal(object: &Object, collision: Vec3) -> Vec3 {
    match *object {
        Object::Sphere { center: c, radius: _ } => {
            (collision - c).normalized()
        }
    }
}

fn get_ambient_color(material: &Material) -> Color {
    (*material).ambient
}

fn get_diffuse_color(light: &Light, material: &Material,
                     n: Vec3, l: Vec3, distance: f64) -> Color {
    // TODO: why do I need this abs
    ((*material).diffuse * (*light).color *
        n.dot(l).abs() * (*light).intensity / distance)
}

fn get_specular_color(material: &Material,
                      l: Vec3, v: Vec3, normal: Vec3) -> Color {
    let h = (v + l).normalized();
    ((*material).specular *
     (normal.dot(h).max(0.0).powf((*material).specular_exponent)))
}

pub fn get_color(scene: &Scene, materialobject: &MaterialObject,
                 ray: &Ray, t: f64) -> (Color, u64) {
    let (ref object, ref material) = *materialobject;
    let collision = ray.origin + (ray.direction * t);
    let normal = get_normal(object, collision);
    let ambient = get_ambient_color(&material);
    (*scene).lights.iter().fold((ambient, 0), |accum, light| {
        let (prev_color, prev_rays) = accum;
        let direction = (*light).position - collision;
        let new_ray = Ray {
            origin: collision - (direction * 0.00001),
            direction: direction
        };
        let vec_to_light = light.position - collision;
        let distance = vec_to_light.mag_squared().sqrt();
        let l = (light.position - collision).normalized();
        let v = new_ray.origin - new_ray.direction;

        let diffuse = get_diffuse_color(&light, material, normal, l, distance);
        let specular = get_specular_color(material, l, v, normal);
        (prev_color + diffuse + specular, prev_rays + 1)
    })
}
<|endoftext|>


<commit_before>use core::{intrinsics, ptr};

use mem;

// NOTE This function and the ones below are implemented using assembly because they using a custom
// calling convention which can't be implemented using a normal Rust function
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl __udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl __aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}");
    intrinsics::unreachable();
}

// FIXME: The `*4` and `*8` variants should be defined as aliases.

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
    mem::memcpy(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, mut n: usize) {
    let mut dest = dest as *mut u32;
    let mut src = src as *mut u32;

    while n >= 4 {
        ptr::write(dest, ptr::read(src));
        dest = dest.offset(1);
        src = src.offset(1);
        n -= 4;
    }

    __aeabi_memcpy(dest as *mut u8, src as *const u8, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memcpy4(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
    mem::memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
    // Note the different argument order
    mem::memset(dest, c, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, mut n: usize, c: i32) {
    let mut dest = dest as *mut u32;

    let byte = (c as u32) & 0xff;
    let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;

    while n >= 4 {
        ptr::write(dest, c);
        dest = dest.offset(1);
        n -= 4;
    }

    __aeabi_memset(dest as *mut u8, n, byte as i32);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
    __aeabi_memset4(dest, n, c);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
    __aeabi_memset(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}
<commit_msg>Fix unused imports on iOS<commit_after>use core::intrinsics;

// NOTE This function and the ones below are implemented using assembly because they using a custom
// calling convention which can't be implemented using a normal Rust function
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl __udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl __aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}");
    intrinsics::unreachable();
}

#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}");
    intrinsics::unreachable();
}

// FIXME: The `*4` and `*8` variants should be defined as aliases.

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memcpy(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, mut n: usize) {
    use core::ptr;

    let mut dest = dest as *mut u32;
    let mut src = src as *mut u32;

    while n >= 4 {
        ptr::write(dest, ptr::read(src));
        dest = dest.offset(1);
        src = src.offset(1);
        n -= 4;
    }

    __aeabi_memcpy(dest as *mut u8, src as *const u8, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memcpy4(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
    // Note the different argument order
    ::mem::memset(dest, c, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, mut n: usize, c: i32) {
    use core::ptr;

    let mut dest = dest as *mut u32;

    let byte = (c as u32) & 0xff;
    let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;

    while n >= 4 {
        ptr::write(dest, c);
        dest = dest.offset(1);
        n -= 4;
    }

    __aeabi_memset(dest as *mut u8, n, byte as i32);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
    __aeabi_memset4(dest, n, c);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
    __aeabi_memset(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(default_type_params)]
extern crate arena;
extern crate petgraph;

use arena::TypedArena;
use std::cell::Cell;

use petgraph::ograph::{
    OGraph,
    toposort,
};

pub use petgraph::{
    MinScored,
    DiGraph,
    Graph,
    Ptr,
    Incoming, Outgoing,
    Node,
    NodeCell,
    BreadthFirst,
    DepthFirst,
    dijkstra,
};

fn make_graph() {
    let root = TypedArena::new();
    let mut g: DiGraph<_, f32> = DiGraph::new();
    let an = g.add_node(Ptr(root.alloc(Node("A"))));
    let bn = g.add_node(Ptr(root.alloc(Node("B"))));
    let cn = g.add_node(Ptr(root.alloc(Node("C"))));
    g.add_edge(an, bn, 1.);
    g.add_edge(an, cn, 2.);
    /*
    println!("{}", g.nodes);

    {
        for node in g.nodes() {
            println!("Node= {}", node);
        }
    }

    for next in g.edges(an) {
        println!("{} is a successor of {}", next, an);
    }

    g.remove_node(bn);
    println!("Removed B, {}", g.nodes);

    g.add_edge(cn, bn, 2.);
    println!("Added edge C to B, {}", g.nodes);
    g.add_edge(bn, an, 1.);
    println!("Added edge B to A, {}", g.nodes);
    g.add_edge(bn, cn, 3.);
    println!("Added edge B to C, {}", g.nodes);
    g.remove_edge(bn, an);
    println!("Removed edge B to A, {}", g.nodes);
    g.remove_edge(bn, an);
    println!("Removed edge B to A, {}", g.nodes);

    println!("Reversed, {}", g.reverse().nodes);

    */
    // Wikipedia example
    let root = TypedArena::<NodeCell<_>>::new();
    let mut g: DiGraph<_, f32> = DiGraph::new();
    let node = |name: &'static str| Ptr(root.alloc(NodeCell(Cell::new(name))));
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_diedge(a, b, 7.);
    g.add_diedge(a, c, 9.);
    g.add_diedge(a, d, 14.);
    g.add_diedge(b, c, 10.);
    g.add_diedge(c, d, 2.);
    g.add_diedge(d, e, 9.);
    g.add_diedge(b, f, 15.);
    g.add_diedge(c, f, 11.);
    g.add_diedge(e, f, 6.);
    println!("{}", g);

    f.set("F'");

    println!("Scores= {}",
        dijkstra(&g, a, |gr, n| gr.edges(n).map(|(n, &e)| (n, e)))
    );

    //let x =
    let mut it = BreadthFirst::new(&g, a);
    //let mut it = range(0i, 1);
    for node in it {
        println!("Visit {}", node);
    }
    println!("");
    let mut it = DepthFirst::new(&g, a);
    for node in it {
        println!("Visit {}", node);
    }

    let mut g: DiGraph<_, f32> = DiGraph::new();
    let node = |name: &'static str| name;
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_diedge(a, b, 7.);
    g.add_diedge(a, c, 9.);
    g.add_diedge(a, d, 14.);
    g.add_diedge(b, c, 10.);
    g.add_diedge(c, d, 2.);
    g.add_diedge(d, e, 9.);
    g.add_diedge(b, f, 15.);
    g.add_diedge(c, f, 11.);
    g.add_diedge(e, f, 6.);

    println!("{}", g);

    let root = TypedArena::<Node<_>>::new();
    let mut g: Graph<_, f32> = Graph::new();
    let node = |name: &'static str| Ptr(root.alloc(Node(name.to_string())));
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_edge(a, b, 7.);
    g.add_edge(a, c, 9.);
    g.add_edge(a, d, 14.);
    g.add_edge(b, c, 10.);
    g.add_edge(c, d, 2.);
    g.add_edge(d, e, 9.);
    g.add_edge(b, f, 15.);
    g.add_edge(c, f, 11.);
    g.add_edge(e, f, 6.);
    println!("{}", g);
    println!("{}", dijkstra(&g, a, |gr, n| gr.edges(n).map(|(n, &e)| (n, e))));
    for node in DepthFirst::new(&g, a) {
        println!("Visit {}", node);
    }
    println!("");
    for node in BreadthFirst::new(&g, a) {
        println!("Visit {}", node);
    }

    let mut g: Graph<int, int> = Graph::new();
    g.add_node(1);
    g.add_node(2);
    g.add_edge(1, 2, -1);

    println!("{}", g);
    *g.edge_mut(1, 2).unwrap() = 3;
    for elt in g.edges(1) {
        println!("Edge {} => {}", 1i, elt);
    }
    for elt in g.edges(2) {
        println!("Edge {} => {}", 2i, elt);
    }
    for elt in BreadthFirst::new(&g, 2) {
        println!("Visit: {}", elt);
    }
    //g.remove_node(2);
    g.remove_edge(2, 1);
    println!("{}", g);
}

fn main() {
    make_graph();

    let mut og = OGraph::new();
    let a = og.add_node(0i);
    let b = og.add_node(1i);
    let c = og.add_node(2i);
    let d = og.add_node(3i);
    let ed1 = og.add_edge(a, b, 0i);
    let ed2 = og.add_edge(a, c, 1);
    og.add_edge(c, a, 2);
    og.add_edge(a, a, 3);
    og.add_edge(b, c, 4);
    og.add_edge(b, a, 5);
    og.add_edge(a, d, 6);

    for no in og.edges(a, Outgoing) {
        println!("Edges {}", no);
    }

    for no in og.edges_both(a) {
        println!("EdgesBoth {}", no);
    }

    println!("{}", og);
    println!("Remove {}", a);
    for no in BreadthFirst::new(&og, a) {
        println!("Visit {}", no);
    }
    og.remove_node(a);
    //og.remove_edge(ed1);
    println!("{}", og);
    for no in BreadthFirst::new(&og, a) {
        println!("Visit {}", no);
    }

    let mut g = OGraph::<_, f32>::new();
    let a = g.add_node("A");
    let b = g.add_node("B");
    let c = g.add_node("C");
    let d = g.add_node("D");
    let e = g.add_node("E");
    let f = g.add_node("F");
    g.add_edge(a, b, 7.);
    g.add_edge(a, c, 9.);
    g.add_edge(a, d, 14.);
    g.add_edge(b, c, 10.);
    g.add_edge(c, d, 2.);
    g.add_edge(d, e, 9.);
    g.add_edge(b, f, 15.);
    g.add_edge(c, f, 11.);
    g.add_edge(e, f, 6.);
    println!("{}", g);
    for no in BreadthFirst::new(&g, a) {
        println!("Visit {} = {}", no, g.node(no));
    }

    println!("Scores= {}",
        dijkstra(&g, a, |gr, n| gr.edges(n, Outgoing).map(|(n, &e)| (n, e)))
    );

    let x = g.add_node("X");
    let y = g.add_node("Y");
    g.add_edge(x, y, 0.);
    println!("{}", toposort(&g));
}
<commit_msg>Update for closure changes.<commit_after>#![feature(macro_rules)]
#![feature(default_type_params)]
extern crate arena;
extern crate petgraph;

use arena::TypedArena;
use std::cell::Cell;

use petgraph::ograph::{
    OGraph,
    toposort,
};

pub use petgraph::{
    MinScored,
    DiGraph,
    Graph,
    Ptr,
    Incoming, Outgoing,
    Node,
    NodeCell,
    BreadthFirst,
    DepthFirst,
    dijkstra,
};

fn make_graph() {
    let root = TypedArena::new();
    let mut g: DiGraph<_, f32> = DiGraph::new();
    let an = g.add_node(Ptr(root.alloc(Node("A"))));
    let bn = g.add_node(Ptr(root.alloc(Node("B"))));
    let cn = g.add_node(Ptr(root.alloc(Node("C"))));
    g.add_edge(an, bn, 1.);
    g.add_edge(an, cn, 2.);
    /*
    println!("{}", g.nodes);

    {
        for node in g.nodes() {
            println!("Node= {}", node);
        }
    }

    for next in g.edges(an) {
        println!("{} is a successor of {}", next, an);
    }

    g.remove_node(bn);
    println!("Removed B, {}", g.nodes);

    g.add_edge(cn, bn, 2.);
    println!("Added edge C to B, {}", g.nodes);
    g.add_edge(bn, an, 1.);
    println!("Added edge B to A, {}", g.nodes);
    g.add_edge(bn, cn, 3.);
    println!("Added edge B to C, {}", g.nodes);
    g.remove_edge(bn, an);
    println!("Removed edge B to A, {}", g.nodes);
    g.remove_edge(bn, an);
    println!("Removed edge B to A, {}", g.nodes);

    println!("Reversed, {}", g.reverse().nodes);

    */
    // Wikipedia example
    let root = TypedArena::<NodeCell<_>>::new();
    let mut g: DiGraph<_, f32> = DiGraph::new();
    let node = |&: name: &'static str| Ptr(root.alloc(NodeCell(Cell::new(name))));
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_diedge(a, b, 7.);
    g.add_diedge(a, c, 9.);
    g.add_diedge(a, d, 14.);
    g.add_diedge(b, c, 10.);
    g.add_diedge(c, d, 2.);
    g.add_diedge(d, e, 9.);
    g.add_diedge(b, f, 15.);
    g.add_diedge(c, f, 11.);
    g.add_diedge(e, f, 6.);
    println!("{}", g);

    f.set("F'");

    println!("Scores= {}",
        dijkstra(&g, a, |gr, n| gr.edges(n).map(|(n, &e)| (n, e)))
    );

    //let x =
    let mut it = BreadthFirst::new(&g, a);
    //let mut it = range(0i, 1);
    for node in it {
        println!("Visit {}", node);
    }
    println!("");
    let mut it = DepthFirst::new(&g, a);
    for node in it {
        println!("Visit {}", node);
    }

    let mut g: DiGraph<_, f32> = DiGraph::new();
    let node = |&: name: &'static str| name;
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_diedge(a, b, 7.);
    g.add_diedge(a, c, 9.);
    g.add_diedge(a, d, 14.);
    g.add_diedge(b, c, 10.);
    g.add_diedge(c, d, 2.);
    g.add_diedge(d, e, 9.);
    g.add_diedge(b, f, 15.);
    g.add_diedge(c, f, 11.);
    g.add_diedge(e, f, 6.);

    println!("{}", g);

    let root = TypedArena::<Node<_>>::new();
    let mut g: Graph<_, f32> = Graph::new();
    let node = |&: name: &'static str| Ptr(root.alloc(Node(name.to_string())));
    let a = g.add_node(node("A"));
    let b = g.add_node(node("B"));
    let c = g.add_node(node("C"));
    let d = g.add_node(node("D"));
    let e = g.add_node(node("E"));
    let f = g.add_node(node("F"));
    g.add_edge(a, b, 7.);
    g.add_edge(a, c, 9.);
    g.add_edge(a, d, 14.);
    g.add_edge(b, c, 10.);
    g.add_edge(c, d, 2.);
    g.add_edge(d, e, 9.);
    g.add_edge(b, f, 15.);
    g.add_edge(c, f, 11.);
    g.add_edge(e, f, 6.);
    println!("{}", g);
    println!("{}", dijkstra(&g, a, |gr, n| gr.edges(n).map(|(n, &e)| (n, e))));
    for node in DepthFirst::new(&g, a) {
        println!("Visit {}", node);
    }
    println!("");
    for node in BreadthFirst::new(&g, a) {
        println!("Visit {}", node);
    }

    let mut g: Graph<int, int> = Graph::new();
    g.add_node(1);
    g.add_node(2);
    g.add_edge(1, 2, -1);

    println!("{}", g);
    *g.edge_mut(1, 2).unwrap() = 3;
    for elt in g.edges(1) {
        println!("Edge {} => {}", 1i, elt);
    }
    for elt in g.edges(2) {
        println!("Edge {} => {}", 2i, elt);
    }
    for elt in BreadthFirst::new(&g, 2) {
        println!("Visit: {}", elt);
    }
    //g.remove_node(2);
    g.remove_edge(2, 1);
    println!("{}", g);
}

fn main() {
    make_graph();

    let mut og = OGraph::new();
    let a = og.add_node(0i);
    let b = og.add_node(1i);
    let c = og.add_node(2i);
    let d = og.add_node(3i);
    let ed1 = og.add_edge(a, b, 0i);
    let ed2 = og.add_edge(a, c, 1);
    og.add_edge(c, a, 2);
    og.add_edge(a, a, 3);
    og.add_edge(b, c, 4);
    og.add_edge(b, a, 5);
    og.add_edge(a, d, 6);

    for no in og.edges(a, Outgoing) {
        println!("Edges {}", no);
    }

    for no in og.edges_both(a) {
        println!("EdgesBoth {}", no);
    }

    println!("{}", og);
    println!("Remove {}", a);
    for no in BreadthFirst::new(&og, a) {
        println!("Visit {}", no);
    }
    og.remove_node(a);
    //og.remove_edge(ed1);
    println!("{}", og);
    for no in BreadthFirst::new(&og, a) {
        println!("Visit {}", no);
    }

    let mut g = OGraph::<_, f32>::new();
    let a = g.add_node("A");
    let b = g.add_node("B");
    let c = g.add_node("C");
    let d = g.add_node("D");
    let e = g.add_node("E");
    let f = g.add_node("F");
    g.add_edge(a, b, 7.);
    g.add_edge(a, c, 9.);
    g.add_edge(a, d, 14.);
    g.add_edge(b, c, 10.);
    g.add_edge(c, d, 2.);
    g.add_edge(d, e, 9.);
    g.add_edge(b, f, 15.);
    g.add_edge(c, f, 11.);
    g.add_edge(e, f, 6.);
    println!("{}", g);
    for no in BreadthFirst::new(&g, a) {
        println!("Visit {} = {}", no, g.node(no));
    }

    println!("Scores= {}",
        dijkstra(&g, a, |gr, n| gr.edges(n, Outgoing).map(|(n, &e)| (n, e)))
    );

    let x = g.add_node("X");
    let y = g.add_node("Y");
    g.add_edge(x, y, 0.);
    println!("{}", toposort(&g));
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
use std::rc::Rc;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );

#[derive(Debug)]
struct EString( String ) ;
impl EString{
    fn new(val: &str) -> Self { EString(val.to_string()) }
}

struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
impl Integer{
    fn new(val: isize) -> Self { Integer(val) }
}

struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

//For simplicity while experimenting, I'm not using Rc<T>
//Can't derive Debug automatically for Term
//#[derive(Debug)]
struct Lambda{
    parameter: Box<Term>,
    guard    : Box<Term>,
    body     : Box<Term>,
    //type,
    index    : usize,
    stuff     : (),
}
impl Lambda{
    fn new(p: Box<Term>, g: Box<Term>, b: Box<Term>) -> Self{
        Lambda{parameter: p, guard: g, body: b, index: 0, stuff: ()}
    }
}

trait RootType<T>{
    fn native(&self) -> &T;
}
impl RootType<String> for EString{
    fn native(&self) -> &String { &self.0 }
}
impl RootType<isize> for Integer{
    fn native(&self) -> &isize { &self.0 }
}

trait Term{
    fn to_string(&self) -> String { "This is a Term.".to_string() }
}

impl Term for EString{
    fn to_string(&self) -> String { "This is an EString".to_string() }
}

impl Term for Integer{
    fn to_string(&self) -> String {"This is an Integer".to_string() }
}

impl Term for Lambda{
    fn to_string(&self) -> String {"This is a Lambda.".to_string() }
}

#[test]
fn term_type_check_test() -> (){
    let estring = EString("Test".to_string());
    let integer = Integer::new(3);
    let i2 = Integer::new(5);
    let lambda = Lambda::new(Box::new(estring), Box::new(integer),
                 Box::new(i2));
    // Uncomment the following line to see the term type checker assist in action
    // stringterm = integerterm;
    // The following line shoudl fail to compile because i32 does not have the Termable trait.
    //estring = integer;

    panic!("Intentionial panic. {:?}", lambda.to_string() );
}

<commit_msg>Removed outdated lines.<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
use std::rc::Rc;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );

#[derive(Debug)]
struct EString( String ) ;
impl EString{
    fn new(val: &str) -> Self { EString(val.to_string()) }
}

struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
impl Integer{
    fn new(val: isize) -> Self { Integer(val) }
}

struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

//For simplicity while experimenting, I'm not using Rc<T>
//Can't derive Debug automatically for Term
//#[derive(Debug)]
struct Lambda{
    parameter: Box<Term>,
    guard    : Box<Term>,
    body     : Box<Term>,
    //type,
    index    : usize,
    stuff     : (),
}
impl Lambda{
    fn new(p: Box<Term>, g: Box<Term>, b: Box<Term>) -> Self{
        Lambda{parameter: p, guard: g, body: b, index: 0, stuff: ()}
    }
}

trait RootType<T>{
    fn native(&self) -> &T;
}
impl RootType<String> for EString{
    fn native(&self) -> &String { &self.0 }
}
impl RootType<isize> for Integer{
    fn native(&self) -> &isize { &self.0 }
}

trait Term{
    fn to_string(&self) -> String { "This is a Term.".to_string() }
}

impl Term for EString{
    fn to_string(&self) -> String { "This is an EString".to_string() }
}

impl Term for Integer{
    fn to_string(&self) -> String {"This is an Integer".to_string() }
}

impl Term for Lambda{
    fn to_string(&self) -> String {"This is a Lambda.".to_string() }
}

#[test]
fn term_type_check_test() -> (){
    let estring = EString("Test".to_string());
    let integer = Integer::new(3);
    let i2 = Integer::new(5);
    let lambda = Lambda::new(Box::new(estring), Box::new(integer),
                 Box::new(i2));
    // Uncomment the following line to see the term type checker assist in action
    // stringterm = integerterm;

    panic!("Intentionial panic. {:?}", lambda.to_string() );
}

<|endoftext|>


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

use clap::Parser;
use num_format::{Locale, ToFormattedString};
use serde::Serialize;
use std::path::PathBuf;
use std::str::FromStr;
use std::string::ToString;
use tabled::{
    object::{Columns, Rows},
    style::Border,
    Alignment, Modify, Style, Table, Tabled,
};

use crate::lang;

#[derive(Debug)]
pub enum Format {
    Json,
    Table,
}

impl FromStr for Format {
    type Err = String;
    fn from_str(format: &str) -> Result<Self, Self::Err> {
        match format {
            "json" => Ok(Format::Json),
            "table" => Ok(Format::Table),
            _ => Err(format.to_string()),
        }
    }
}

/// Count lines of code.
#[derive(Debug, Parser)]
#[clap(version, about)]
pub struct Args {
    /// Output format ("table" or "json").
    #[clap(short = 'o', long = "output", default_value = "table")]
    pub format: Format,

    /// Show timing information.
    #[clap(short, long)]
    pub timing: bool,

    /// Directory or file to scan.
    #[clap(default_value = ".")]
    pub path: PathBuf,
}

#[derive(Debug, Serialize)]
pub struct Output {
    pub languages: Vec<LangOut>,
    pub total_num_files: u64,
    pub total_num_lines: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub elapsed_ms: Option<u64>,
}

#[derive(Debug, Serialize)]
pub struct LangOut {
    pub language: lang::Language,
    pub num_files: u64,
    pub num_lines: u64,
}

pub fn get_options() -> Args {
    Args::parse()
}

pub fn write_output(out: &Output, format: Format) {
    match format {
        Format::Json => write_json_pretty(out),
        Format::Table => write_table(out),
    }
}

fn write_json_pretty(out: &Output) {
    println!("{}", serde_json::to_string_pretty(&out).unwrap());
}

#[derive(Tabled)]
struct Row {
    #[tabled(rename = "Language")]
    language: String,
    #[tabled(rename = "Files")]
    files: String,
    #[tabled(rename = "Lines")]
    lines: String,
}

fn write_table(out: &Output) {
    let mut data = Vec::new();
    for lang in &out.languages {
        data.push(Row {
            language: lang.language.as_str().to_string(),
            files: lang.num_files.to_formatted_string(&Locale::en),
            lines: lang.num_lines.to_formatted_string(&Locale::en),
        });
    }

    if out.languages.len() != 1 {
        data.push(Row {
            language: "Total".to_string(),
            files: out.total_num_files.to_formatted_string(&Locale::en),
            lines: out.total_num_lines.to_formatted_string(&Locale::en),
        });
    }

    let mut table = Table::new(&data);
    table
        .with(Style::psql())
        .with(Modify::new(Columns::first()).with(Alignment::left()))
        .with(Modify::new(Columns::new(1..=2)).with(Alignment::right()))
        .with(Modify::new(Rows::first()).with(Alignment::left()));

    if out.languages.len() != 1 {
        table.with(Modify::new(Rows::last()).with(Border::default().top('-')));
    }

    println!("{}", table);

    if let Some(elapsed_ms) = out.elapsed_ms {
        println!("\nTook: {}ms", elapsed_ms);
    }
}
<commit_msg>Fix for clap v4.0.10<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2022 Ryan Fowler
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// copies of the Software, and to permit persons to whom the Software is
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use clap::Parser;
use num_format::{Locale, ToFormattedString};
use serde::Serialize;
use std::path::PathBuf;
use std::str::FromStr;
use std::string::ToString;
use tabled::{
    object::{Columns, Rows},
    style::Border,
    Alignment, Modify, Style, Table, Tabled,
};

use crate::lang;

#[derive(Clone, Debug)]
pub enum Format {
    Json,
    Table,
}

impl FromStr for Format {
    type Err = String;
    fn from_str(format: &str) -> Result<Self, Self::Err> {
        match format {
            "json" => Ok(Format::Json),
            "table" => Ok(Format::Table),
            _ => Err(format.to_string()),
        }
    }
}

/// Count lines of code.
#[derive(Debug, Parser)]
#[clap(version, about)]
pub struct Args {
    /// Output format ("table" or "json").
    #[clap(short = 'o', long = "output", default_value = "table")]
    pub format: Format,

    /// Show timing information.
    #[clap(short, long)]
    pub timing: bool,

    /// Directory or file to scan.
    #[clap(default_value = ".")]
    pub path: PathBuf,
}

#[derive(Debug, Serialize)]
pub struct Output {
    pub languages: Vec<LangOut>,
    pub total_num_files: u64,
    pub total_num_lines: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub elapsed_ms: Option<u64>,
}

#[derive(Debug, Serialize)]
pub struct LangOut {
    pub language: lang::Language,
    pub num_files: u64,
    pub num_lines: u64,
}

pub fn get_options() -> Args {
    Args::parse()
}

pub fn write_output(out: &Output, format: Format) {
    match format {
        Format::Json => write_json_pretty(out),
        Format::Table => write_table(out),
    }
}

fn write_json_pretty(out: &Output) {
    println!("{}", serde_json::to_string_pretty(&out).unwrap());
}

#[derive(Tabled)]
struct Row {
    #[tabled(rename = "Language")]
    language: String,
    #[tabled(rename = "Files")]
    files: String,
    #[tabled(rename = "Lines")]
    lines: String,
}

fn write_table(out: &Output) {
    let mut data = Vec::new();
    for lang in &out.languages {
        data.push(Row {
            language: lang.language.as_str().to_string(),
            files: lang.num_files.to_formatted_string(&Locale::en),
            lines: lang.num_lines.to_formatted_string(&Locale::en),
        });
    }

    if out.languages.len() != 1 {
        data.push(Row {
            language: "Total".to_string(),
            files: out.total_num_files.to_formatted_string(&Locale::en),
            lines: out.total_num_lines.to_formatted_string(&Locale::en),
        });
    }

    let mut table = Table::new(&data);
    table
        .with(Style::psql())
        .with(Modify::new(Columns::first()).with(Alignment::left()))
        .with(Modify::new(Columns::new(1..=2)).with(Alignment::right()))
        .with(Modify::new(Rows::first()).with(Alignment::left()));

    if out.languages.len() != 1 {
        table.with(Modify::new(Rows::last()).with(Border::default().top('-')));
    }

    println!("{}", table);

    if let Some(elapsed_ms) = out.elapsed_ms {
        println!("\nTook: {}ms", elapsed_ms);
    }
}
<|endoftext|>