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

#![allow(non_upper_case_globals)]

use base::{ObjCMethodCall, id, SEL, nil, NSInteger, NSUInteger};
use libc;

#[cfg(target_word_size = "32")]
pub type CGFloat = f32;
#[cfg(target_word_size = "64")]
pub type CGFloat = f64;

#[repr(C)]
pub struct NSPoint {
    pub x: f64,
    pub y: f64,
}

impl NSPoint {
    #[inline]
    pub fn new(x: f64, y: f64) -> NSPoint {
        NSPoint {
            x: x,
            y: y,
        }
    }
}

#[repr(C)]
pub struct NSSize {
    pub width: f64,
    pub height: f64,
}

impl NSSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> NSSize {
        NSSize {
            width: width,
            height: height,
        }
    }
}

#[repr(C)]
pub struct NSRect {
    pub origin: NSPoint,
    pub size: NSSize,
}

impl NSRect {
    #[inline]
    pub fn new(origin: NSPoint, size: NSSize) -> NSRect {
        NSRect {
            origin: origin,
            size: size
        }
    }
}

#[link(name = "AppKit", kind = "framework")]
extern {}

pub unsafe fn NSApp() -> id {
    "NSApplication".send("sharedApplication", ())
}

#[repr(i64)]
pub enum NSApplicationActivationPolicy {
    NSApplicationActivationPolicyRegular = 0,
    NSApplicationActivationPolicyERROR = -1
}

#[repr(u64)]
pub enum NSWindowMask {
    NSBorderlessWindowMask      = 0,
    NSTitledWindowMask          = 1 << 0,
    NSClosableWindowMask        = 1 << 1,
    NSMiniaturizableWindowMask  = 1 << 2,
    NSResizableWindowMask       = 1 << 3,

    NSTexturedBackgroundWindowMask  = 1 << 8,

    NSUnifiedTitleAndToolbarWindowMask  = 1 << 12,

    NSFullScreenWindowMask      = 1 << 14
}

#[repr(u64)]
pub enum NSBackingStoreType {
    NSBackingStoreRetained      = 0,
    NSBackingStoreNonretained   = 1,
    NSBackingStoreBuffered      = 2
}

bitflags! {
    flags NSWindowOrderingMode: NSInteger {
        const NSWindowAbove =  1,
        const NSWindowBelow = -1,
        const NSWindowOut   =  0,
    }
}

bitflags! {
    flags NSAlignmentOptions: libc::c_ulonglong {
        const NSAlignMinXInward         = 1 << 0,
        const NSAlignMinYInward         = 1 << 1,
        const NSAlignMaxXInward         = 1 << 2,
        const NSAlignMaxYInward         = 1 << 3,
        const NSAlignWidthInward        = 1 << 4,
        const NSAlignHeightInward       = 1 << 5,
        const NSAlignMinXOutward        = 1 << 8,
        const NSAlignMinYOutward        = 1 << 9,
        const NSAlignMaxXOutward        = 1 << 10,
        const NSAlignMaxYOutward        = 1 << 11,
        const NSAlignWidthOutward       = 1 << 12,
        const NSAlignHeightOutward      = 1 << 13,
        const NSAlignMinXNearest        = 1 << 16,
        const NSAlignMinYNearest        = 1 << 17,
        const NSAlignMaxXNearest        = 1 << 18,
        const NSAlignMaxYNearest        = 1 << 19,
        const NSAlignWidthNearest       = 1 << 20,
        const NSAlignHeightNearest      = 1 << 21,
        const NSAlignRectFlipped        = 1 << 63,
        const NSAlignAllEdgesInward     = NSAlignMinXInward.bits
                                        | NSAlignMaxXInward.bits
                                        | NSAlignMinYInward.bits
                                        | NSAlignMaxYInward.bits,
        const NSAlignAllEdgesOutward    = NSAlignMinXOutward.bits
                                        | NSAlignMaxXOutward.bits
                                        | NSAlignMinYOutward.bits
                                        | NSAlignMaxYOutward.bits,
        const NSAlignAllEdgesNearest    = NSAlignMinXNearest.bits
                                        | NSAlignMaxXNearest.bits
                                        | NSAlignMinYNearest.bits
                                        | NSAlignMaxYNearest.bits,
    }
}

pub trait NSAutoreleasePool {
    unsafe fn new(_: Self) -> id {
        "NSAutoreleasePool".send("new", ())
    }

    unsafe fn autorelease(self) -> Self;
}

impl NSAutoreleasePool for id {
    unsafe fn autorelease(self) -> id {
        self.send("autorelease", ())
    }
}

pub trait NSProcessInfo {
    unsafe fn processInfo(_: Self) -> id {
        "NSProcessInfo".send("processInfo", ())
    }

    unsafe fn processName(self) -> id;
}

impl NSProcessInfo for id {
    unsafe fn processName(self) -> id {
        self.send("processName", ())
    }
}

pub trait NSApplication {
    unsafe fn sharedApplication(_: Self) -> id {
        "NSApplication".send("sharedApplication", ())
    }

    unsafe fn setActivationPolicy_(self, policy: NSApplicationActivationPolicy) -> bool;
    unsafe fn setMainMenu_(self, menu: id);
    unsafe fn activateIgnoringOtherApps_(self, ignore: bool);
    unsafe fn run(self);
}

impl NSApplication for id {
    unsafe fn setActivationPolicy_(self, policy: NSApplicationActivationPolicy) -> bool {
        self.send_bool("setActivationPolicy:", policy as NSInteger)
    }

    unsafe fn setMainMenu_(self, menu: id) {
        self.send_void("setMainMenu:", menu)
    }

    unsafe fn activateIgnoringOtherApps_(self, ignore: bool) {
        self.send_void("activateIgnoringOtherApps:", ignore);
    }

    unsafe fn run(self) {
        self.send_void("run", ());
    }
}

pub trait NSMenu {
    unsafe fn new(_: Self) -> id {
        "NSMenu".send("new", ())
    }

    unsafe fn addItem_(self, menu_item: id);
}

impl NSMenu for id {
    unsafe fn addItem_(self, menu_item: id) {
        self.send_void("addItem:", menu_item)
    }
}

pub trait NSMenuItem {
    unsafe fn alloc(_: Self) -> id {
        "NSMenuItem".send("alloc", ())
    }

    unsafe fn new(_: Self) -> id {
        "NSMenuItem".send("new", ())
    }

    unsafe fn initWithTitle_action_keyEquivalent_(self, title: id, action: SEL, key: id) -> id;
    unsafe fn setSubmenu_(self, submenu: id);
}

impl NSMenuItem for id {
    unsafe fn initWithTitle_action_keyEquivalent_(self, title: id, action: SEL, key: id) -> id {
        self.send("initWithTitle:action:keyEquivalent:", (title, action, key))
    }

    unsafe fn setSubmenu_(self, submenu: id) {
        self.send_void("setSubmenu:", submenu)
    }
}

pub trait NSWindow {
    unsafe fn alloc(_: Self) -> id {
        "NSWindow".send("alloc", ())
    }

    unsafe fn initWithContentRect_styleMask_backing_defer_(self,
                                                           rect: NSRect,
                                                           style: NSUInteger,
                                                           backing: NSBackingStoreType,
                                                           defer: bool) -> id;
    unsafe fn setTitle_(self, title: id);
    unsafe fn makeKeyAndOrderFront_(self, sender: id);
    unsafe fn center(self);

    // Sizing Windows
    unsafe fn frame(self) -> NSRect;
    unsafe fn setFrameOrigin_(self, point: NSPoint);
    unsafe fn setFrameTopLeftPoint_(self, point: NSPoint);
    // skipped: constrainFrameRect_toScreen_
    unsafe fn cascadeTopLeftFromPoint_(self, topLeft: NSPoint) -> NSPoint;
    unsafe fn setFrame_displayViews_(self, windowFrame: NSRect, display: bool);
    unsafe fn aspectRatio(self) -> NSSize;
    unsafe fn setAspectRatio_(self, aspectRatio: NSSize);
    unsafe fn minSize(self) -> NSSize;
    unsafe fn setMinSize_(self, minSize: NSSize);
    unsafe fn maxSize(self) -> NSSize;
    unsafe fn setMaxSize_(self, maxSize: NSSize);
    unsafe fn performZoom_(self, sender: id);
    unsafe fn zoom_(self, sender: id);
    // skipped: resizeFlags
    unsafe fn showsResizeIndicator(self) -> bool;
    unsafe fn setShowsResizeIndicator_(self, showsResizeIndicator: bool);
    unsafe fn resizeIncrements(self) -> NSSize;
    unsafe fn setResizeIncrements_(self, resizeIncrements: NSSize);
    unsafe fn preservesContentDuringLiveResize(self) -> bool;
    unsafe fn setPreservesContentDuringLiveResize_(self, preservesContentDuringLiveResize: bool);
    unsafe fn inLiveResize(self) -> bool;

    // Managing Window Layers
    unsafe fn orderOut_(self, sender: id);
    unsafe fn orderBack_(self, sender: id);
    unsafe fn orderFront_(self, sender: id);
    unsafe fn orderFrontRegardless(self);
    unsafe fn orderFrontWindow_relativeTo_(self, orderingMode: NSWindowOrderingMode, otherWindowNumber: NSInteger);
    unsafe fn level(self) -> NSInteger;
    unsafe fn setLevel_(self, level: NSInteger);

    // Converting Coordinates
    unsafe fn backingScaleFactor(self) -> CGFloat;
    unsafe fn backingAlignedRect_options_(self, rect: NSRect, options: NSAlignmentOptions) -> NSRect;
    unsafe fn convertRectFromBacking_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectToBacking_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectToScreen_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectFromScreen_(self, rect: NSRect) -> NSRect;
}

impl NSWindow for id {
    unsafe fn initWithContentRect_styleMask_backing_defer_(self,
                                                           rect: NSRect,
                                                           style: NSUInteger,
                                                           backing: NSBackingStoreType,
                                                           defer: bool) -> id {
        self.send("initWithContentRect:styleMask:backing:defer:",
                  (rect, style, backing as NSUInteger, defer))
    }

    unsafe fn setTitle_(self, title: id) {
        self.send_void("setTitle:", title);
    }

    unsafe fn makeKeyAndOrderFront_(self, sender: id) {
        self.send_void("makeKeyAndOrderFront:", sender)
    }

    unsafe fn center(self) {
        self.send_void("center", ())
    }

    // Sizing Windows

    unsafe fn frame(self) -> NSRect {
        self.send_rect("frame", ())
    }

    unsafe fn setFrameOrigin_(self, point: NSPoint) {
        self.send_void("setFrameOrigin:", point);
    }

    unsafe fn setFrameTopLeftPoint_(self, point: NSPoint) {
        self.send_void("setFrameTopLeftPoint:", point);
    }

    unsafe fn cascadeTopLeftFromPoint_(self, topLeft: NSPoint) -> NSPoint {
        self.send_point("cascadeTopLeftFromPoint:", topLeft)
    }

    unsafe fn setFrame_displayViews_(self, windowFrame: NSRect, display: bool) {
        self.send_void("setFrame:displayViews:", (windowFrame, display));
    }

    unsafe fn aspectRatio(self) -> NSSize {
        self.send_size("aspectRatio", ())
    }

    unsafe fn setAspectRatio_(self, aspectRatio: NSSize) {
        self.send_void("setAspectRatio:", aspectRatio);
    }

    unsafe fn minSize(self) -> NSSize {
        self.send_size("minSize", ())
    }

    unsafe fn setMinSize_(self, minSize: NSSize) {
        self.send_void("setMinSize:", minSize);
    }

    unsafe fn maxSize(self) -> NSSize {
        self.send_size("maxSize", ())
    }

    unsafe fn setMaxSize_(self, maxSize: NSSize) {
        self.send_void("setMaxSize:", maxSize);
    }

    unsafe fn performZoom_(self, sender: id) {
        self.send_void("performZoom:", sender);
    }

    unsafe fn zoom_(self, sender: id) {
        self.send_void("zoom:", sender);
    }

    unsafe fn showsResizeIndicator(self) -> bool {
        self.send_bool("showsResizeIndicator", ())
    }

    unsafe fn setShowsResizeIndicator_(self, showsResizeIndicator: bool) {
        self.send_void("setShowsResizeIndicator:", showsResizeIndicator)
    }

    unsafe fn resizeIncrements(self) -> NSSize {
        self.send_size("resizeIncrements", ())
    }

    unsafe fn setResizeIncrements_(self, resizeIncrements: NSSize) {
        self.send_void("setResizeIncrements:", resizeIncrements);
    }

    unsafe fn preservesContentDuringLiveResize(self) -> bool {
        self.send_bool("preservesContentDuringLiveResize", ())
    }

    unsafe fn setPreservesContentDuringLiveResize_(self, preservesContentDuringLiveResize: bool) {
        self.send_void("setPreservesContentDuringLiveResize:", preservesContentDuringLiveResize)
    }

    unsafe fn inLiveResize(self) -> bool {
        self.send_bool("inLiveResize", ())
    }

    // Managing Window Layers

    unsafe fn orderOut_(self, sender: id) {
        self.send_void("orderOut:", sender);
    }

    unsafe fn orderBack_(self, sender: id) {
        self.send_void("orderBack:", sender);
    }

    unsafe fn orderFront_(self, sender: id) {
        self.send_void("orderFront:", sender);
    }

    unsafe fn orderFrontRegardless(self) {
        self.send_void("orderFrontRegardless", ());
    }

    unsafe fn orderFrontWindow_relativeTo_(self, ordering_mode: NSWindowOrderingMode, other_window_number: NSInteger) {
        self.send_void("orderWindow:relativeTo:", (ordering_mode, other_window_number));
    }

    unsafe fn level(self) -> NSInteger {
        self.send_integer("level", ())
    }

    unsafe fn setLevel_(self, level: NSInteger) {
        self.send_void("setLevel:", level);
    }

    // Converting Coordinates

    unsafe fn backingScaleFactor(self) -> CGFloat {
        self.send_float("backingScaleFactor", ())
    }

    unsafe fn backingAlignedRect_options_(self, rect: NSRect, options: NSAlignmentOptions) -> NSRect {
        self.send_rect("backingAlignedRect:options:", (rect, options))
    }

    unsafe fn convertRectFromBacking_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectFromBacking:", rect)
    }

    unsafe fn convertRectToBacking_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectToBacking:", rect)
    }

    unsafe fn convertRectToScreen_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectToScreen:", rect)
    }

    unsafe fn convertRectFromScreen_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectFromScreen:", rect)
    }
}

pub trait NSString {
    unsafe fn alloc(_: Self) -> id {
        "NSString".send("alloc", ())
    }

    unsafe fn initWithUTF8String_(self, c_string: *const u8) -> id;
    unsafe fn stringByAppendingString_(self, other: id) -> id;
    unsafe fn init_str(self, string: &str) -> Self;
}

impl NSString for id {
    unsafe fn initWithUTF8String_(self, c_string: *const u8) -> id {
        self.send("initWithUTF8String:", c_string as id)
    }

    unsafe fn stringByAppendingString_(self, other: id) -> id {
        self.send("stringByAppendingString:", other)
    }

    unsafe fn init_str(self, string: &str) -> id {
        self.initWithUTF8String_(string.as_ptr())
    }
}

<commit_msg>Add title management methods<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_upper_case_globals)]

use base::{ObjCMethodCall, id, SEL, nil, NSInteger, NSUInteger};
use libc;

#[cfg(target_word_size = "32")]
pub type CGFloat = f32;
#[cfg(target_word_size = "64")]
pub type CGFloat = f64;

#[repr(C)]
pub struct NSPoint {
    pub x: f64,
    pub y: f64,
}

impl NSPoint {
    #[inline]
    pub fn new(x: f64, y: f64) -> NSPoint {
        NSPoint {
            x: x,
            y: y,
        }
    }
}

#[repr(C)]
pub struct NSSize {
    pub width: f64,
    pub height: f64,
}

impl NSSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> NSSize {
        NSSize {
            width: width,
            height: height,
        }
    }
}

#[repr(C)]
pub struct NSRect {
    pub origin: NSPoint,
    pub size: NSSize,
}

impl NSRect {
    #[inline]
    pub fn new(origin: NSPoint, size: NSSize) -> NSRect {
        NSRect {
            origin: origin,
            size: size
        }
    }
}

#[link(name = "AppKit", kind = "framework")]
extern {}

pub unsafe fn NSApp() -> id {
    "NSApplication".send("sharedApplication", ())
}

#[repr(i64)]
pub enum NSApplicationActivationPolicy {
    NSApplicationActivationPolicyRegular = 0,
    NSApplicationActivationPolicyERROR = -1
}

#[repr(u64)]
pub enum NSWindowMask {
    NSBorderlessWindowMask      = 0,
    NSTitledWindowMask          = 1 << 0,
    NSClosableWindowMask        = 1 << 1,
    NSMiniaturizableWindowMask  = 1 << 2,
    NSResizableWindowMask       = 1 << 3,

    NSTexturedBackgroundWindowMask  = 1 << 8,

    NSUnifiedTitleAndToolbarWindowMask  = 1 << 12,

    NSFullScreenWindowMask      = 1 << 14
}

#[repr(u64)]
pub enum NSBackingStoreType {
    NSBackingStoreRetained      = 0,
    NSBackingStoreNonretained   = 1,
    NSBackingStoreBuffered      = 2
}

bitflags! {
    flags NSWindowOrderingMode: NSInteger {
        const NSWindowAbove =  1,
        const NSWindowBelow = -1,
        const NSWindowOut   =  0,
    }
}

bitflags! {
    flags NSAlignmentOptions: libc::c_ulonglong {
        const NSAlignMinXInward         = 1 << 0,
        const NSAlignMinYInward         = 1 << 1,
        const NSAlignMaxXInward         = 1 << 2,
        const NSAlignMaxYInward         = 1 << 3,
        const NSAlignWidthInward        = 1 << 4,
        const NSAlignHeightInward       = 1 << 5,
        const NSAlignMinXOutward        = 1 << 8,
        const NSAlignMinYOutward        = 1 << 9,
        const NSAlignMaxXOutward        = 1 << 10,
        const NSAlignMaxYOutward        = 1 << 11,
        const NSAlignWidthOutward       = 1 << 12,
        const NSAlignHeightOutward      = 1 << 13,
        const NSAlignMinXNearest        = 1 << 16,
        const NSAlignMinYNearest        = 1 << 17,
        const NSAlignMaxXNearest        = 1 << 18,
        const NSAlignMaxYNearest        = 1 << 19,
        const NSAlignWidthNearest       = 1 << 20,
        const NSAlignHeightNearest      = 1 << 21,
        const NSAlignRectFlipped        = 1 << 63,
        const NSAlignAllEdgesInward     = NSAlignMinXInward.bits
                                        | NSAlignMaxXInward.bits
                                        | NSAlignMinYInward.bits
                                        | NSAlignMaxYInward.bits,
        const NSAlignAllEdgesOutward    = NSAlignMinXOutward.bits
                                        | NSAlignMaxXOutward.bits
                                        | NSAlignMinYOutward.bits
                                        | NSAlignMaxYOutward.bits,
        const NSAlignAllEdgesNearest    = NSAlignMinXNearest.bits
                                        | NSAlignMaxXNearest.bits
                                        | NSAlignMinYNearest.bits
                                        | NSAlignMaxYNearest.bits,
    }
}

pub trait NSAutoreleasePool {
    unsafe fn new(_: Self) -> id {
        "NSAutoreleasePool".send("new", ())
    }

    unsafe fn autorelease(self) -> Self;
}

impl NSAutoreleasePool for id {
    unsafe fn autorelease(self) -> id {
        self.send("autorelease", ())
    }
}

pub trait NSProcessInfo {
    unsafe fn processInfo(_: Self) -> id {
        "NSProcessInfo".send("processInfo", ())
    }

    unsafe fn processName(self) -> id;
}

impl NSProcessInfo for id {
    unsafe fn processName(self) -> id {
        self.send("processName", ())
    }
}

pub trait NSApplication {
    unsafe fn sharedApplication(_: Self) -> id {
        "NSApplication".send("sharedApplication", ())
    }

    unsafe fn setActivationPolicy_(self, policy: NSApplicationActivationPolicy) -> bool;
    unsafe fn setMainMenu_(self, menu: id);
    unsafe fn activateIgnoringOtherApps_(self, ignore: bool);
    unsafe fn run(self);
}

impl NSApplication for id {
    unsafe fn setActivationPolicy_(self, policy: NSApplicationActivationPolicy) -> bool {
        self.send_bool("setActivationPolicy:", policy as NSInteger)
    }

    unsafe fn setMainMenu_(self, menu: id) {
        self.send_void("setMainMenu:", menu)
    }

    unsafe fn activateIgnoringOtherApps_(self, ignore: bool) {
        self.send_void("activateIgnoringOtherApps:", ignore);
    }

    unsafe fn run(self) {
        self.send_void("run", ());
    }
}

pub trait NSMenu {
    unsafe fn new(_: Self) -> id {
        "NSMenu".send("new", ())
    }

    unsafe fn addItem_(self, menu_item: id);
}

impl NSMenu for id {
    unsafe fn addItem_(self, menu_item: id) {
        self.send_void("addItem:", menu_item)
    }
}

pub trait NSMenuItem {
    unsafe fn alloc(_: Self) -> id {
        "NSMenuItem".send("alloc", ())
    }

    unsafe fn new(_: Self) -> id {
        "NSMenuItem".send("new", ())
    }

    unsafe fn initWithTitle_action_keyEquivalent_(self, title: id, action: SEL, key: id) -> id;
    unsafe fn setSubmenu_(self, submenu: id);
}

impl NSMenuItem for id {
    unsafe fn initWithTitle_action_keyEquivalent_(self, title: id, action: SEL, key: id) -> id {
        self.send("initWithTitle:action:keyEquivalent:", (title, action, key))
    }

    unsafe fn setSubmenu_(self, submenu: id) {
        self.send_void("setSubmenu:", submenu)
    }
}

pub trait NSWindow {
    unsafe fn alloc(_: Self) -> id {
        "NSWindow".send("alloc", ())
    }

    unsafe fn initWithContentRect_styleMask_backing_defer_(self,
                                                           rect: NSRect,
                                                           style: NSUInteger,
                                                           backing: NSBackingStoreType,
                                                           defer: bool) -> id;
    unsafe fn makeKeyAndOrderFront_(self, sender: id);
    unsafe fn center(self);

    // Sizing Windows
    unsafe fn frame(self) -> NSRect;
    unsafe fn setFrameOrigin_(self, point: NSPoint);
    unsafe fn setFrameTopLeftPoint_(self, point: NSPoint);
    // skipped: constrainFrameRect_toScreen_
    unsafe fn cascadeTopLeftFromPoint_(self, topLeft: NSPoint) -> NSPoint;
    unsafe fn setFrame_displayViews_(self, windowFrame: NSRect, display: bool);
    unsafe fn aspectRatio(self) -> NSSize;
    unsafe fn setAspectRatio_(self, aspectRatio: NSSize);
    unsafe fn minSize(self) -> NSSize;
    unsafe fn setMinSize_(self, minSize: NSSize);
    unsafe fn maxSize(self) -> NSSize;
    unsafe fn setMaxSize_(self, maxSize: NSSize);
    unsafe fn performZoom_(self, sender: id);
    unsafe fn zoom_(self, sender: id);
    // skipped: resizeFlags
    unsafe fn showsResizeIndicator(self) -> bool;
    unsafe fn setShowsResizeIndicator_(self, showsResizeIndicator: bool);
    unsafe fn resizeIncrements(self) -> NSSize;
    unsafe fn setResizeIncrements_(self, resizeIncrements: NSSize);
    unsafe fn preservesContentDuringLiveResize(self) -> bool;
    unsafe fn setPreservesContentDuringLiveResize_(self, preservesContentDuringLiveResize: bool);
    unsafe fn inLiveResize(self) -> bool;

    // Managing Window Layers
    unsafe fn orderOut_(self, sender: id);
    unsafe fn orderBack_(self, sender: id);
    unsafe fn orderFront_(self, sender: id);
    unsafe fn orderFrontRegardless(self);
    unsafe fn orderFrontWindow_relativeTo_(self, orderingMode: NSWindowOrderingMode, otherWindowNumber: NSInteger);
    unsafe fn level(self) -> NSInteger;
    unsafe fn setLevel_(self, level: NSInteger);

    // Converting Coordinates
    unsafe fn backingScaleFactor(self) -> CGFloat;
    unsafe fn backingAlignedRect_options_(self, rect: NSRect, options: NSAlignmentOptions) -> NSRect;
    unsafe fn convertRectFromBacking_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectToBacking_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectToScreen_(self, rect: NSRect) -> NSRect;
    unsafe fn convertRectFromScreen_(self, rect: NSRect) -> NSRect;

    // Managing Titles
    unsafe fn title(self) -> id;
    unsafe fn setTitle_(self, title: id);
    unsafe fn setTitleWithRepresentedFilename_(self, filePath: id);
    unsafe fn representedFilename(self) -> id;
    unsafe fn setRepresentedFilename_(self, filePath: id);
    // skipped: representedURL
    // skipped: setRepresentedURL_
}

impl NSWindow for id {
    unsafe fn initWithContentRect_styleMask_backing_defer_(self,
                                                           rect: NSRect,
                                                           style: NSUInteger,
                                                           backing: NSBackingStoreType,
                                                           defer: bool) -> id {
        self.send("initWithContentRect:styleMask:backing:defer:",
                  (rect, style, backing as NSUInteger, defer))
    }

    unsafe fn makeKeyAndOrderFront_(self, sender: id) {
        self.send_void("makeKeyAndOrderFront:", sender)
    }

    unsafe fn center(self) {
        self.send_void("center", ())
    }

    // Sizing Windows

    unsafe fn frame(self) -> NSRect {
        self.send_rect("frame", ())
    }

    unsafe fn setFrameOrigin_(self, point: NSPoint) {
        self.send_void("setFrameOrigin:", point);
    }

    unsafe fn setFrameTopLeftPoint_(self, point: NSPoint) {
        self.send_void("setFrameTopLeftPoint:", point);
    }

    unsafe fn cascadeTopLeftFromPoint_(self, topLeft: NSPoint) -> NSPoint {
        self.send_point("cascadeTopLeftFromPoint:", topLeft)
    }

    unsafe fn setFrame_displayViews_(self, windowFrame: NSRect, display: bool) {
        self.send_void("setFrame:displayViews:", (windowFrame, display));
    }

    unsafe fn aspectRatio(self) -> NSSize {
        self.send_size("aspectRatio", ())
    }

    unsafe fn setAspectRatio_(self, aspectRatio: NSSize) {
        self.send_void("setAspectRatio:", aspectRatio);
    }

    unsafe fn minSize(self) -> NSSize {
        self.send_size("minSize", ())
    }

    unsafe fn setMinSize_(self, minSize: NSSize) {
        self.send_void("setMinSize:", minSize);
    }

    unsafe fn maxSize(self) -> NSSize {
        self.send_size("maxSize", ())
    }

    unsafe fn setMaxSize_(self, maxSize: NSSize) {
        self.send_void("setMaxSize:", maxSize);
    }

    unsafe fn performZoom_(self, sender: id) {
        self.send_void("performZoom:", sender);
    }

    unsafe fn zoom_(self, sender: id) {
        self.send_void("zoom:", sender);
    }

    unsafe fn showsResizeIndicator(self) -> bool {
        self.send_bool("showsResizeIndicator", ())
    }

    unsafe fn setShowsResizeIndicator_(self, showsResizeIndicator: bool) {
        self.send_void("setShowsResizeIndicator:", showsResizeIndicator)
    }

    unsafe fn resizeIncrements(self) -> NSSize {
        self.send_size("resizeIncrements", ())
    }

    unsafe fn setResizeIncrements_(self, resizeIncrements: NSSize) {
        self.send_void("setResizeIncrements:", resizeIncrements);
    }

    unsafe fn preservesContentDuringLiveResize(self) -> bool {
        self.send_bool("preservesContentDuringLiveResize", ())
    }

    unsafe fn setPreservesContentDuringLiveResize_(self, preservesContentDuringLiveResize: bool) {
        self.send_void("setPreservesContentDuringLiveResize:", preservesContentDuringLiveResize)
    }

    unsafe fn inLiveResize(self) -> bool {
        self.send_bool("inLiveResize", ())
    }

    // Managing Window Layers

    unsafe fn orderOut_(self, sender: id) {
        self.send_void("orderOut:", sender);
    }

    unsafe fn orderBack_(self, sender: id) {
        self.send_void("orderBack:", sender);
    }

    unsafe fn orderFront_(self, sender: id) {
        self.send_void("orderFront:", sender);
    }

    unsafe fn orderFrontRegardless(self) {
        self.send_void("orderFrontRegardless", ());
    }

    unsafe fn orderFrontWindow_relativeTo_(self, ordering_mode: NSWindowOrderingMode, other_window_number: NSInteger) {
        self.send_void("orderWindow:relativeTo:", (ordering_mode, other_window_number));
    }

    unsafe fn level(self) -> NSInteger {
        self.send_integer("level", ())
    }

    unsafe fn setLevel_(self, level: NSInteger) {
        self.send_void("setLevel:", level);
    }

    // Converting Coordinates

    unsafe fn backingScaleFactor(self) -> CGFloat {
        self.send_float("backingScaleFactor", ())
    }

    unsafe fn backingAlignedRect_options_(self, rect: NSRect, options: NSAlignmentOptions) -> NSRect {
        self.send_rect("backingAlignedRect:options:", (rect, options))
    }

    unsafe fn convertRectFromBacking_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectFromBacking:", rect)
    }

    unsafe fn convertRectToBacking_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectToBacking:", rect)
    }

    unsafe fn convertRectToScreen_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectToScreen:", rect)
    }

    unsafe fn convertRectFromScreen_(self, rect: NSRect) -> NSRect {
        self.send_rect("convertRectFromScreen:", rect)
    }

    // Managing Titles

    unsafe fn title(self) -> id {
        self.send("title", ())
    }

    unsafe fn setTitle_(self, title: id) {
        self.send_void("setTitle:", title);
    }

    unsafe fn setTitleWithRepresentedFilename_(self, filePath: id) {
        self.send_void("setTitleWithRepresentedFilename:", filePath);
    }

    unsafe fn representedFilename(self) -> id {
        self.send("representedFilename", ())
    }

    unsafe fn setRepresentedFilename_(self, filePath: id) {
        self.send_void("setRepresentedFilename:", filePath);
    }
}

pub trait NSString {
    unsafe fn alloc(_: Self) -> id {
        "NSString".send("alloc", ())
    }

    unsafe fn initWithUTF8String_(self, c_string: *const u8) -> id;
    unsafe fn stringByAppendingString_(self, other: id) -> id;
    unsafe fn init_str(self, string: &str) -> Self;
}

impl NSString for id {
    unsafe fn initWithUTF8String_(self, c_string: *const u8) -> id {
        self.send("initWithUTF8String:", c_string as id)
    }

    unsafe fn stringByAppendingString_(self, other: id) -> id {
        self.send("stringByAppendingString:", other)
    }

    unsafe fn init_str(self, string: &str) -> id {
        self.initWithUTF8String_(string.as_ptr())
    }
}

<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &coreutils::ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found(&'h') || parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use coreutils::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "human-readable")
        .add_flag("", "help");
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<commit_msg>df adheres to new ArgParser interface<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &coreutils::ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use coreutils::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "human-readable"])
        .add_flag(&["help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<|endoftext|>


<commit_before>use std::hash;
use std::iter::FromIterator;
use std::collections::HashMap;
use num::{BigUint, FromPrimitive, Zero, One};
use nock::{self, Noun, FromNoun};

pub struct Jet {
    pub name: String,
    pub jet: Option<fn(&Noun) -> Noun>,
    pub battery: Noun,
    // TODO: What do we do with these?
    pub axis: u32,
    pub hooks: HashMap<String, Noun>,
    pub calls: u64,
}

impl Jet {
    pub fn new(name: String, battery: Noun, axis: u32, hooks: Vec<(String, Noun)>) -> Jet {
        let jet = match &name[..] {
            "dec" => Some(dec as fn(&Noun) -> Noun),
            "bex" => Some(bex as fn(&Noun) -> Noun),
            "add" => Some(add as fn(&Noun) -> Noun),
            "mul" => Some(mul as fn(&Noun) -> Noun),
            "sub" => Some(sub as fn(&Noun) -> Noun),
            "div" => Some(div as fn(&Noun) -> Noun),
            "lth" => Some(lth as fn(&Noun) -> Noun),
            "rsh" => Some(rsh as fn(&Noun) -> Noun),
            "lsh" => Some(lsh as fn(&Noun) -> Noun),
            "mod" => Some(mod_ as fn(&Noun) -> Noun),
            "end" => Some(end as fn(&Noun) -> Noun),
            "mix" => Some(mix as fn(&Noun) -> Noun),
            "met" => Some(met as fn(&Noun) -> Noun),
            "cut" => Some(cut as fn(&Noun) -> Noun),
            _ => None,
        };

        Jet {
            name: name,
            jet: jet,
            battery: battery,
            axis: axis,
            hooks: HashMap::from_iter(hooks.into_iter()),
            calls: 0,
        }
    }
}

impl hash::Hash for Jet {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.battery.hash(state);
    }
}

// FIXME: Needing to do the get_axis on subject.
// TODO: Error handling that isn't panicing.

pub fn dec(subject: &Noun) -> Noun {
    // XXX: How do we know the axis here?
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let n = BigUint::from_noun(&arg).unwrap();
    Noun::from(n - BigUint::one())
}

pub fn bex(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    // XXX: Will fail if arg is above machine word size.
    let n: usize = FromNoun::from_noun(&arg).unwrap();
    Noun::from(BigUint::one() << n)
}

pub fn add(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x + y)
}

pub fn mul(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x * y)
}

pub fn sub(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x - y)
}

pub fn div(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x / y)
}

pub fn lth(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x < y)
}

pub fn rsh(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(c >> ((1 << a) * b))
}

pub fn lsh(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(c << ((1 << a) * b))
}

pub fn mod_(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x % y)
}

pub fn end(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();

    Noun::from(c % BigUint::from_usize(1 << ((1 << a) * b)).unwrap())
}

pub fn mix(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();

    Noun::from(a ^ b)
}

pub fn met(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (bloq, mut atom): (usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    let mut ret: usize = 0;
    while atom != Zero::zero() {
        atom = atom >> (1 << bloq);
        ret += 1;
    }
    Noun::from(ret)
}

pub fn cut(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, (mut b, mut c), mut d): (usize, (usize, usize), BigUint) = FromNoun::from_noun(&arg).unwrap();
    b = b << a;
    c = c << (1 << a);
    d = d >> b;
    d = d % BigUint::from_usize(c).unwrap();

    Noun::from(d)
}
<commit_msg>WIP mug jet<commit_after>use std::hash;
use std::iter::FromIterator;
use std::collections::HashMap;
use num::{BigUint, FromPrimitive, Zero, One};
use nock::{self, Noun, FromNoun};

pub struct Jet {
    pub name: String,
    pub jet: Option<fn(&Noun) -> Noun>,
    pub battery: Noun,
    // TODO: What do we do with these?
    pub axis: u32,
    pub hooks: HashMap<String, Noun>,
    pub calls: u64,
}

impl Jet {
    pub fn new(name: String, battery: Noun, axis: u32, hooks: Vec<(String, Noun)>) -> Jet {
        let jet = match &name[..] {
            "dec" => Some(dec as fn(&Noun) -> Noun),
            "bex" => Some(bex as fn(&Noun) -> Noun),
            "add" => Some(add as fn(&Noun) -> Noun),
            "mul" => Some(mul as fn(&Noun) -> Noun),
            "sub" => Some(sub as fn(&Noun) -> Noun),
            "div" => Some(div as fn(&Noun) -> Noun),
            "lth" => Some(lth as fn(&Noun) -> Noun),
            "rsh" => Some(rsh as fn(&Noun) -> Noun),
            "lsh" => Some(lsh as fn(&Noun) -> Noun),
            "mod" => Some(mod_ as fn(&Noun) -> Noun),
            "end" => Some(end as fn(&Noun) -> Noun),
            "mix" => Some(mix as fn(&Noun) -> Noun),
            "met" => Some(met as fn(&Noun) -> Noun),
            "cut" => Some(cut as fn(&Noun) -> Noun),
            "mug" => Some(mug as fn(&Noun) -> Noun),
            _ => None,
        };

        Jet {
            name: name,
            jet: jet,
            battery: battery,
            axis: axis,
            hooks: HashMap::from_iter(hooks.into_iter()),
            calls: 0,
        }
    }
}

impl hash::Hash for Jet {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.battery.hash(state);
    }
}

// FIXME: Needing to do the get_axis on subject.
// TODO: Error handling that isn't panicing.

pub fn dec(subject: &Noun) -> Noun {
    // XXX: How do we know the axis here?
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let n = BigUint::from_noun(&arg).unwrap();
    Noun::from(n - BigUint::one())
}

pub fn bex(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    // XXX: Will fail if arg is above machine word size.
    let n: usize = FromNoun::from_noun(&arg).unwrap();
    Noun::from(BigUint::one() << n)
}

pub fn add(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x + y)
}

pub fn mul(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x * y)
}

pub fn sub(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x - y)
}

pub fn div(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x / y)
}

pub fn lth(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x < y)
}

pub fn rsh(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(c >> ((1 << a) * b))
}

pub fn lsh(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(c << ((1 << a) * b))
}

pub fn mod_(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (x, y): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();
    Noun::from(x % y)
}

pub fn end(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b, c): (usize, usize, BigUint) = FromNoun::from_noun(&arg).unwrap();

    Noun::from(c % BigUint::from_usize(1 << ((1 << a) * b)).unwrap())
}

pub fn mix(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, b): (BigUint, BigUint) = FromNoun::from_noun(&arg).unwrap();

    Noun::from(a ^ b)
}

pub fn met(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (bloq, mut atom): (usize, BigUint) = FromNoun::from_noun(&arg).unwrap();
    let mut ret: usize = 0;
    while atom != Zero::zero() {
        atom = atom >> (1 << bloq);
        ret += 1;
    }
    Noun::from(ret)
}

pub fn cut(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();

    let (a, (mut b, mut c), mut d): (usize, (usize, usize), BigUint) = FromNoun::from_noun(&arg).unwrap();
    b = b << a;
    c = c << (1 << a);
    d = d >> b;
    d = d % BigUint::from_usize(c).unwrap();

    Noun::from(d)
}

pub fn mug(subject: &Noun) -> Noun {
    let arg = nock::get_axis(&Noun::from(6u32), subject).unwrap();
    Noun::from(arg.mug())
}
<|endoftext|>


<commit_before>//! Voxel bounds

use cgmath::{Point, Point3, Vector3};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
/// The input coordinates should be divided by (2^lg_size) relative to world coords.
pub struct T {
  pub x: i32,
  pub y: i32,
  pub z: i32,
  /// The log_2 of the voxel's size.
  pub lg_size: i16,
}

#[allow(missing_docs)]
pub fn new(x: i32, y: i32, z: i32, lg_size: i16) -> T {
  let ret =
    T {
      x: x,
      y: y,
      z: z,
      lg_size: lg_size,
    };
  ret
}

impl T {
  /// The width of this voxel.
  pub fn size(&self) -> f32 {
    if self.lg_size >= 0 {
      (1 << self.lg_size) as f32
    } else {
      1.0 / (1 << -self.lg_size) as f32
    }
  }

  /// The bottom of this voxel.
  pub fn low_corner(&self) -> Point3<f32> {
    let size = self.size();
    Point3::new(self.x as f32, self.y as f32, self.z as f32).mul_s(size)
  }

  /// The corners of this voxel.
  pub fn corners(&self) -> (Point3<f32>, Point3<f32>) {
    let size = self.size();
    let low = Point3::new(self.x as f32, self.y as f32, self.z as f32).mul_s(size);
    (low, low.add_v(&Vector3::new(size, size, size)))
  }

  /// The center of this voxel.
  pub fn center(&self) -> Point3<f32> {
    let size = self.size();
    let half = Vector3::new(0.5, 0.5, 0.5);
    Point3::new(self.x as f32, self.y as f32, self.z as f32).add_v(&half).mul_s(size)
  }

  /// Check whether this voxel contains a given point.
  pub fn contains(&self, p: &Point3<f32>) -> bool {
    let (low, high) = self.corners();
    p.x >= low.x &&
    p.y >= low.y &&
    p.z >= low.z &&
    p.x < high.x &&
    p.y < high.y &&
    p.z < high.z &&
    true
  }
}
<commit_msg>add a containment function for voxel::bounds<commit_after>//! Voxel bounds

use cgmath::{Point, Point3, Vector3};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
/// The input coordinates should be divided by (2^lg_size) relative to world coords.
pub struct T {
  pub x: i32,
  pub y: i32,
  pub z: i32,
  /// The log_2 of the voxel's size.
  pub lg_size: i16,
}

#[allow(missing_docs)]
pub fn new(x: i32, y: i32, z: i32, lg_size: i16) -> T {
  let ret =
    T {
      x: x,
      y: y,
      z: z,
      lg_size: lg_size,
    };
  ret
}

impl T {
  /// The width of this voxel.
  pub fn size(&self) -> f32 {
    if self.lg_size >= 0 {
      (1 << self.lg_size) as f32
    } else {
      1.0 / (1 << -self.lg_size) as f32
    }
  }

  /// The bottom of this voxel.
  pub fn low_corner(&self) -> Point3<f32> {
    let size = self.size();
    Point3::new(self.x as f32, self.y as f32, self.z as f32).mul_s(size)
  }

  /// The corners of this voxel.
  pub fn corners(&self) -> (Point3<f32>, Point3<f32>) {
    let size = self.size();
    let low = Point3::new(self.x as f32, self.y as f32, self.z as f32).mul_s(size);
    (low, low.add_v(&Vector3::new(size, size, size)))
  }

  /// The center of this voxel.
  pub fn center(&self) -> Point3<f32> {
    let size = self.size();
    let half = Vector3::new(0.5, 0.5, 0.5);
    Point3::new(self.x as f32, self.y as f32, self.z as f32).add_v(&half).mul_s(size)
  }

  /// Check whether this voxel contains a given point.
  pub fn contains_point(&self, p: &Point3<f32>) -> bool {
    let (low, high) = self.corners();
    p.x >= low.x &&
    p.y >= low.y &&
    p.z >= low.z &&
    p.x < high.x &&
    p.y < high.y &&
    p.z < high.z &&
    true
  }

  /// Check whether this voxel contains another one
  pub fn contains(&self, other: &T) -> bool {
    if other.lg_size > self.lg_size {
      return false
    }

    // Convert `other`'s coordinates to be in terms of `self`'s lg_size.
    // This rounds down, so any voxels inside `self` will end up equal to self.
    let lg_ratio = self.lg_size - other.lg_size;
    (other.x >> lg_ratio) == self.x &&
    (other.y >> lg_ratio) == self.y &&
    (other.z >> lg_ratio) == self.z &&
    true
  }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Combinatorial phantom types for discrete mathematics.
//!
//! All discrete spaces have the following functions:
//!
//! ~~~ignore
//! fn count(dim) -> usize;
//! fn to_index(dim, pos) -> usize;
//! fn to_pos(dim, index, &mut pos);
//! ~~~
//!
//! A discrete space is countable and has a one-to-one map
//! with the natural numbers.
//!
//! For example, a pair of natural numbers is a discrete space.
//! There exists an algorithm that converts each pair of numbers
//! into a number. Likewise there exists an algorithm that
//! takes a number and converts it into a pair.
//!
//! To construct a pair, you write:
//!
//! ~~~ignore
//! let x: Pair<Data> = Construct::new();
//! ~~~
//!
//! The `x` above is a phantom variable, it does not use memory
//! in the compiled program. It represents the discrete space
//! that we have constructed. Now we can call methods on the space
//! to examine its discrete structure.
//!
//! A pair can be visualized as edges between points.
//! If we have 4 points then we can create 6 edges:
//!
//! ```text
//!   o---o
//!   |\ /|
//!   | X |
//!   |/ \|
//!   o---o
//! ```
//!
//! To check this we can write:
//!
//! ~~~ignore
//! let dim = 4; // number of points
//! assert_eq!(x.count(dim), 6); // count edges
//! ~~~
//!
//! Phantom types makes it possible to construct advanced discrete spaces.
//! By using generic program, the algorithms to examine the structure
//! follows from the construction of the space.
//!
//! This makes it possible to solve tasks as:
//!
//! - Compute upper bounds for certain problems
//! - Store data with a non-trivial structure
//! - Convert from and to natural numbers
//! - Iterate through the space
//! - Pick a random object of the space
//!
//! Iterating through the space can be done simply
//! by counting from zero up to the size of the space.
//! For each number, we convert to a position within the space.
//!
//! Pick a random object of the space can be done by generating
//! a random number between 0 and the size of the space.
//!
//! ### Advanced spaces
//!
//! Phantom types are used because they represents the general spaces.
//! For example, we can represent a general two-dimensional space,
//! instead of binding the type to the size.
//!
//! For any constructed space, there is a dimension and position type.
//! The dimension and position types are compositions,
//! given by the type of the constructed space.

use std::marker::PhantomData;

pub use construct::Construct;
pub use count::Count;
pub use to_index::ToIndex;
pub use to_pos::ToPos;
pub use zero::Zero;
pub use power_set::PowerSet;
pub use dimension_n::DimensionN;
pub use dimension::Dimension;
pub use pair::Pair;
pub use eq_pair::EqPair;
pub use neq_pair::NeqPair;
pub use permutation::Permutation;
pub use context::Context;
pub use directed_context::DirectedContext;
pub use either::{Either, Select};
pub use homotopy::{Homotopy, HPoint};

mod construct;
mod count;
mod to_index;
mod to_pos;
mod zero;
mod power_set;
mod dimension_n;
mod dimension;
mod pair;
mod eq_pair;
mod neq_pair;
mod permutation;
mod context;
mod directed_context;
mod subspace;
mod either;
mod homotopy;

/// Used by the final subspace.
#[derive(Copy, Clone)]
pub struct Data;
/// Used to combine the dimensional and position types.
pub struct Of<T>(PhantomData<T>);

#[cfg(test)]
pub fn does_count<T, U>()
    where
        T: Count<U>
{}

#[cfg(test)]
pub fn does_zero<T, U, V>()
    where
        T: Zero<U, V>
{}

#[cfg(test)]
pub fn does_to_index<T, U, V>()
    where
        T: ToIndex<U, V>
{}

#[cfg(test)]
pub fn does_to_pos<T, U, V>()
    where
        T: ToPos<U, V>
{}

// T - discrete space
// U - dimension
// V - Position
#[cfg(test)]
pub fn is_complete<T, U, V>()
    where
        T: Count<U> + Zero<U, V> + ToIndex<U, V> + ToPos<U, V>
{
    does_count::<T, U>();
    does_zero::<T, U, V>();
    does_to_index::<T, U, V>();
    does_to_pos::<T, U, V>();
}
<commit_msg>Fixed typos in docs<commit_after>#![deny(missing_docs)]

//! Combinatorial phantom types for discrete mathematics.
//!
//! All discrete spaces have the following functions:
//!
//! ~~~ignore
//! fn count(dim) -> usize;
//! fn to_index(dim, pos) -> usize;
//! fn to_pos(dim, index, &mut pos);
//! ~~~
//!
//! A discrete space is countable and has a one-to-one map
//! with the natural numbers.
//!
//! For example, a pair of natural numbers is a discrete space.
//! There exists an algorithm that converts each pair of numbers
//! into a number. Likewise there exists an algorithm that
//! takes a number and converts it into a pair.
//!
//! To construct a pair, you write:
//!
//! ~~~ignore
//! let x: Pair<Data> = Construct::new();
//! ~~~
//!
//! The `x` above is a phantom variable, which means it does not use memory
//! in the compiled program. The phantom variable represents the discrete space
//! that we have constructed. Now we can call methods on the space
//! to examine its discrete structure.
//!
//! A pair can be visualized as edges between points.
//! If we have 4 points then we can create 6 edges:
//!
//! ```text
//!   o---o
//!   |\ /|
//!   | X |
//!   |/ \|
//!   o---o
//! ```
//!
//! To check this we can write:
//!
//! ~~~ignore
//! let dim = 4; // number of points
//! assert_eq!(x.count(dim), 6); // count edges
//! ~~~
//!
//! Phantom types makes it possible to construct advanced discrete spaces.
//! By using a generic program, the algorithms to examine the structure
//! follows from the construction of the space.
//!
//! This makes it possible to solve tasks such as:
//!
//! - Compute upper bounds for many problems
//! - Store data with a non-trivial structure
//! - Convert from and to natural numbers
//! - Iterate through all elements of a space
//! - Pick a random object of the space
//!
//! Iterating through all elements of a space can be done simply
//! by counting from zero up to the size of the space.
//! For each number, we convert to a position within the space.
//!
//! Picking a random object of the space can be done by generating
//! a random number between 0 and the size of the space.
//!
//! ### Advanced spaces
//!
//! Phantom types are used because they represent the general spaces.
//! For example, we can represent a general two-dimensional space,
//! instead of binding the type to the size.
//!
//! For any constructed space, there is a dimension and position type.
//! The dimension and position types are compositions,
//! given by the type of the constructed space.

use std::marker::PhantomData;

pub use construct::Construct;
pub use count::Count;
pub use to_index::ToIndex;
pub use to_pos::ToPos;
pub use zero::Zero;
pub use power_set::PowerSet;
pub use dimension_n::DimensionN;
pub use dimension::Dimension;
pub use pair::Pair;
pub use eq_pair::EqPair;
pub use neq_pair::NeqPair;
pub use permutation::Permutation;
pub use context::Context;
pub use directed_context::DirectedContext;
pub use either::{Either, Select};
pub use homotopy::{Homotopy, HPoint};

mod construct;
mod count;
mod to_index;
mod to_pos;
mod zero;
mod power_set;
mod dimension_n;
mod dimension;
mod pair;
mod eq_pair;
mod neq_pair;
mod permutation;
mod context;
mod directed_context;
mod subspace;
mod either;
mod homotopy;

/// Used by the final subspace.
#[derive(Copy, Clone)]
pub struct Data;
/// Used to combine the dimensional and position types.
pub struct Of<T>(PhantomData<T>);

#[cfg(test)]
pub fn does_count<T, U>()
    where
        T: Count<U>
{}

#[cfg(test)]
pub fn does_zero<T, U, V>()
    where
        T: Zero<U, V>
{}

#[cfg(test)]
pub fn does_to_index<T, U, V>()
    where
        T: ToIndex<U, V>
{}

#[cfg(test)]
pub fn does_to_pos<T, U, V>()
    where
        T: ToPos<U, V>
{}

// T - discrete space
// U - dimension
// V - Position
#[cfg(test)]
pub fn is_complete<T, U, V>()
    where
        T: Count<U> + Zero<U, V> + ToIndex<U, V> + ToPos<U, V>
{
    does_count::<T, U>();
    does_zero::<T, U, V>();
    does_to_index::<T, U, V>();
    does_to_pos::<T, U, V>();
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<commit_msg>added display trait for matrix<commit_after>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T: Display> Display for Matrix<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut res = write!(f, "");
        let (row, col) = self.size();

        for i in 0..row {
            // write matrix content
            for j in 0..col {
                res = res.and(write!(f, "{} ", self[(i, j)]));
            }
            res = res.and(write!(f, "\n"));
        }

        res
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<|endoftext|>


<commit_before>// ZSnapMgr :: ZFS snapshot and backup manager
//
// Copyright (c) 2016 by William R. Fraser
//

use std::collections::btree_map::*;
use std::io::Write;

extern crate chrono;
use chrono::*;

#[macro_use]
mod zfs_error;
use zfs_error::ZfsError;

mod zfs;
use zfs::ZFS;

mod inheritable_pipe;
use inheritable_pipe::InheritablePipe;

pub struct ZSnapMgr {
    zfs: ZFS,
}

fn date_from_snapshot(snap: &str) -> Option<Date<Local>> {
    let datepart = match snap.splitn(2, '@').last() {
        Some(s) => s,
        None => return None,
    };

    let dateparts: Vec<i32> = datepart.splitn(3, '-')
                                      .filter_map(|part| {
                                          part.parse::<i32>()
                                              .ok()
                                      })
                                      .collect();

    if dateparts.len() != 3 {
        return None;
    }

    Some(Local.ymd(dateparts[0], dateparts[1] as u32, dateparts[2] as u32))
}

fn today() -> Date<Local> {
    // see chrono issue "Local::today() is not today."
    // https://github.com/lifthrasiir/rust-chrono/issues/61
    let now = Local::now();
    Local.ymd(now.year(), now.month(), now.day())
}

trait WeekOfYear {
    fn week_of_year(&self) -> u32;
}

impl<T: Datelike> WeekOfYear for T {
    fn week_of_year(&self) -> u32 {
        // The original C# version of this program used System.Globalization.Calendar.GetWeekOfYear
        // for this, using System.Globalization.DateTimeFormatInfo.InvariantInfo for the
        // parameters.
        //
        // "The first week of the year starts on the first day of the year and ends before the
        // following designated first day of the week."
        // The first day of the week is designated as Sunday.
        //
        // This is similar to the ISO week date, except that ISO week date has:
        //  week starting on Monday
        //  the first week of the year can be 53
        //
        // This isn't going to replicate the C# method exactly - the value can be +/- 1 depending
        // on which year it is for.
        // Figuring out whether to add 1 or not depending on the year is hard, and this method is
        // only used for finding the first snapshot in a week, so the difference isn't important.

        let weekdate = self.isoweekdate();
        let mut week_number = weekdate.1;

        // Week starts on Sunday.
        if weekdate.2 == Weekday::Sun {
            if week_number == 53 {
                week_number = 1;
            } else {
                week_number += 1;
            }
        }

        week_number
    }
}

impl ZSnapMgr {
    pub fn new(use_sudo: bool) -> ZSnapMgr {
        ZSnapMgr { zfs: ZFS { use_sudo: use_sudo } }
    }

    pub fn get_volumes(&self) -> Result<Vec<String>, ZfsError> {
        self.zfs.volumes(None)
    }

    pub fn get_snapshots(&self, dataset: Option<&str>) -> Result<Vec<String>, ZfsError> {
        self.zfs.snapshots(dataset)
    }

    pub fn backup(&self,
                  path: &str,
                  snapshot: &str,
                  passphrase: &str,
                  incremental_start: Option<&str>)
                  -> Result<(), ZfsError> {
        let mut passphrase_pipe =
            zfstry!(InheritablePipe::new(), or "failed to create passphrase pipe");

        zfstry!(write!(passphrase_pipe, "{}\n", passphrase), or "failed to write passphrase to pipe");

        self.zfs.send(snapshot,
                      &format!("{}/{}.zfs.bz2.gpg", path, snapshot.replace("/", "_")),
                      incremental_start,
                      Some(&format!("pbzip2 | gpg --batch --symmetric --passphrase-fd {} \
                                     --output -",
                                    passphrase_pipe.child_fd())))
    }

    pub fn snapshot_automanage(&self) -> Result<(), ZfsError> {
        let today = today().succ();
        let today_str = format!("{:04}-{:02}-{:02}",
                                today.year(),
                                today.month(),
                                today.day());

        let mut all_snaps = try!(self.get_snapshots(None));
        let mut snaps_map: BTreeMap<String, BTreeMap<Date<Local>, String>> = BTreeMap::new();
        for snap in all_snaps.drain(..) {
            let snap_date = match date_from_snapshot(&snap) {
                Some(date) => date,
                None => continue,
            };

            let volume = snap.splitn(2, '@').next().unwrap().to_string();
            let entry = snaps_map.entry(volume).or_insert(BTreeMap::new());
            entry.insert(snap_date, snap);
        }

        let mut to_delete = Vec::<String>::new();
        let mut to_create = Vec::<String>::new();

        for volume_pair in snaps_map {
            let volume = volume_pair.0;
            let snaps = volume_pair.1;
            let mut count = 0;

            for snap_pair in snaps.iter().rev() {
                let snap_date = snap_pair.0;
                let snap = snap_pair.1;

                count += 1;

                let days_old = (today - *snap_date).num_days();

                if (count == 1) && (days_old != 0) {
                    println!("{}\t{}\t0 days old\t#1\t[NEW]", volume, today_str);
                    to_create.push(format!("{}@{}", volume, today_str));
                    count += 1;
                }

                print!("{}\t{}\t{} days old\t#{}",
                       volume,
                       snap.splitn(2, '@').last().unwrap(),
                       days_old,
                       count);

                let mut delete = false;

                let first_of_month = snaps.iter()
                                          .rev()
                                          .find(|pair| {
                                              pair.0.year() == snap_date.year() &&
                                              pair.0.month() == snap_date.month()
                                          });

                if count > 60 {
                    // Keep only the first snapshot of the month.
                    if first_of_month.map_or(false, |pair| pair.1 != snap) {
                        delete = true;
                    }
                } else if count > 30 {
                    // Keep only the first snapshot of the week or month.
                    let first_of_week = snaps.iter()
                                             .rev()
                                             .find(|pair| {
                                                 pair.0.year() == snap_date.year() &&
                                                 pair.0.week_of_year() == snap_date.week_of_year()
                                             });

                    if first_of_week.map_or(false, |pair| pair.1 != snap) &&
                       first_of_month.map_or(false, |pair| pair.1 != snap) {
                        delete = true;
                    }
                }

                if delete {
                    print!("\t[DELETE]");
                    to_delete.push(snap.to_string());
                }

                println!("");
            }
        }

        for snap in to_delete {
            // TODO
            println!("ZFS DELETE {}", snap);
        }

        for snap in to_create {
            // TODO
            println!("ZFS SNAPSHOT {}", snap);
        }

        Err(ZfsError::from("snapshot automanage is not yet implemented."))
    }
}
<commit_msg>oops, remove debugging edit<commit_after>// ZSnapMgr :: ZFS snapshot and backup manager
//
// Copyright (c) 2016 by William R. Fraser
//

use std::collections::btree_map::*;
use std::io::Write;

extern crate chrono;
use chrono::*;

#[macro_use]
mod zfs_error;
use zfs_error::ZfsError;

mod zfs;
use zfs::ZFS;

mod inheritable_pipe;
use inheritable_pipe::InheritablePipe;

pub struct ZSnapMgr {
    zfs: ZFS,
}

fn date_from_snapshot(snap: &str) -> Option<Date<Local>> {
    let datepart = match snap.splitn(2, '@').last() {
        Some(s) => s,
        None => return None,
    };

    let dateparts: Vec<i32> = datepart.splitn(3, '-')
                                      .filter_map(|part| {
                                          part.parse::<i32>()
                                              .ok()
                                      })
                                      .collect();

    if dateparts.len() != 3 {
        return None;
    }

    Some(Local.ymd(dateparts[0], dateparts[1] as u32, dateparts[2] as u32))
}

fn today() -> Date<Local> {
    // see chrono issue "Local::today() is not today."
    // https://github.com/lifthrasiir/rust-chrono/issues/61
    let now = Local::now();
    Local.ymd(now.year(), now.month(), now.day())
}

trait WeekOfYear {
    fn week_of_year(&self) -> u32;
}

impl<T: Datelike> WeekOfYear for T {
    fn week_of_year(&self) -> u32 {
        // The original C# version of this program used System.Globalization.Calendar.GetWeekOfYear
        // for this, using System.Globalization.DateTimeFormatInfo.InvariantInfo for the
        // parameters.
        //
        // "The first week of the year starts on the first day of the year and ends before the
        // following designated first day of the week."
        // The first day of the week is designated as Sunday.
        //
        // This is similar to the ISO week date, except that ISO week date has:
        //  week starting on Monday
        //  the first week of the year can be 53
        //
        // This isn't going to replicate the C# method exactly - the value can be +/- 1 depending
        // on which year it is for.
        // Figuring out whether to add 1 or not depending on the year is hard, and this method is
        // only used for finding the first snapshot in a week, so the difference isn't important.

        let weekdate = self.isoweekdate();
        let mut week_number = weekdate.1;

        // Week starts on Sunday.
        if weekdate.2 == Weekday::Sun {
            if week_number == 53 {
                week_number = 1;
            } else {
                week_number += 1;
            }
        }

        week_number
    }
}

impl ZSnapMgr {
    pub fn new(use_sudo: bool) -> ZSnapMgr {
        ZSnapMgr { zfs: ZFS { use_sudo: use_sudo } }
    }

    pub fn get_volumes(&self) -> Result<Vec<String>, ZfsError> {
        self.zfs.volumes(None)
    }

    pub fn get_snapshots(&self, dataset: Option<&str>) -> Result<Vec<String>, ZfsError> {
        self.zfs.snapshots(dataset)
    }

    pub fn backup(&self,
                  path: &str,
                  snapshot: &str,
                  passphrase: &str,
                  incremental_start: Option<&str>)
                  -> Result<(), ZfsError> {
        let mut passphrase_pipe =
            zfstry!(InheritablePipe::new(), or "failed to create passphrase pipe");

        zfstry!(write!(passphrase_pipe, "{}\n", passphrase), or "failed to write passphrase to pipe");

        self.zfs.send(snapshot,
                      &format!("{}/{}.zfs.bz2.gpg", path, snapshot.replace("/", "_")),
                      incremental_start,
                      Some(&format!("pbzip2 | gpg --batch --symmetric --passphrase-fd {} \
                                     --output -",
                                    passphrase_pipe.child_fd())))
    }

    pub fn snapshot_automanage(&self) -> Result<(), ZfsError> {
        let today = today();
        let today_str = format!("{:04}-{:02}-{:02}",
                                today.year(),
                                today.month(),
                                today.day());

        let mut all_snaps = try!(self.get_snapshots(None));
        let mut snaps_map: BTreeMap<String, BTreeMap<Date<Local>, String>> = BTreeMap::new();
        for snap in all_snaps.drain(..) {
            let snap_date = match date_from_snapshot(&snap) {
                Some(date) => date,
                None => continue,
            };

            let volume = snap.splitn(2, '@').next().unwrap().to_string();
            let entry = snaps_map.entry(volume).or_insert(BTreeMap::new());
            entry.insert(snap_date, snap);
        }

        let mut to_delete = Vec::<String>::new();
        let mut to_create = Vec::<String>::new();

        for volume_pair in snaps_map {
            let volume = volume_pair.0;
            let snaps = volume_pair.1;
            let mut count = 0;

            for snap_pair in snaps.iter().rev() {
                let snap_date = snap_pair.0;
                let snap = snap_pair.1;

                count += 1;

                let days_old = (today - *snap_date).num_days();

                if (count == 1) && (days_old != 0) {
                    println!("{}\t{}\t0 days old\t#1\t[NEW]", volume, today_str);
                    to_create.push(format!("{}@{}", volume, today_str));
                    count += 1;
                }

                print!("{}\t{}\t{} days old\t#{}",
                       volume,
                       snap.splitn(2, '@').last().unwrap(),
                       days_old,
                       count);

                let mut delete = false;

                let first_of_month = snaps.iter()
                                          .rev()
                                          .find(|pair| {
                                              pair.0.year() == snap_date.year() &&
                                              pair.0.month() == snap_date.month()
                                          });

                if count > 60 {
                    // Keep only the first snapshot of the month.
                    if first_of_month.map_or(false, |pair| pair.1 != snap) {
                        delete = true;
                    }
                } else if count > 30 {
                    // Keep only the first snapshot of the week or month.
                    let first_of_week = snaps.iter()
                                             .rev()
                                             .find(|pair| {
                                                 pair.0.year() == snap_date.year() &&
                                                 pair.0.week_of_year() == snap_date.week_of_year()
                                             });

                    if first_of_week.map_or(false, |pair| pair.1 != snap) &&
                       first_of_month.map_or(false, |pair| pair.1 != snap) {
                        delete = true;
                    }
                }

                if delete {
                    print!("\t[DELETE]");
                    to_delete.push(snap.to_string());
                }

                println!("");
            }
        }

        for snap in to_delete {
            // TODO
            println!("ZFS DELETE {}", snap);
        }

        for snap in to_create {
            // TODO
            println!("ZFS SNAPSHOT {}", snap);
        }

        Err(ZfsError::from("snapshot automanage is not yet implemented."))
    }
}
<|endoftext|>