<commit_before>use jsapi::*;

pub enum Action { }
unsafe impl Sync for ProxyTraps { }
/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Copy, Clone)]
pub struct ProxyTraps {
    pub enter: ::std::option::Option<unsafe extern "C" fn
                                         (cx: *mut JSContext,
                                          proxy: HandleObject, id: HandleId,
                                          action: Action, bp: *mut bool) -> bool>,
    pub getOwnPropertyDescriptor: ::std::option::Option<unsafe extern "C" fn
                                                            (cx:
                                                                 *mut JSContext,
                                                             proxy:
                                                                 HandleObject,
                                                             id: HandleId,
                                                             desc:
                                                                 MutableHandle<PropertyDescriptor>)
                                                            -> bool>,
    pub defineProperty: ::std::option::Option<unsafe extern "C" fn
                                                  (cx: *mut JSContext,
                                                   proxy: HandleObject,
                                                   id: HandleId,
                                                   desc:
                                                       Handle<PropertyDescriptor>,
                                                   result:
                                                       *mut ObjectOpResult)
                                                  -> bool>,
    pub ownPropertyKeys: ::std::option::Option<unsafe extern "C" fn
                                                   (cx: *mut JSContext,
                                                    proxy: HandleObject,
                                                    props: *mut AutoIdVector)
                                                   -> bool>,
    pub delete_: ::std::option::Option<unsafe extern "C" fn
                                           (cx: *mut JSContext,
                                            proxy: HandleObject, id: HandleId,
                                            result: *mut ObjectOpResult)
                                           -> bool>,
    pub enumerate: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject,
                                              objp: MutableHandleObject)
                                             -> bool>,
    pub getPrototypeIfOrdinary: ::std::option::Option<unsafe extern "C" fn
                                                          (cx: *mut JSContext,
                                                           proxy: HandleObject,
                                                           isOrdinary: *mut bool,
                                                           protop: MutableHandleObject)
                                                          -> bool>,
    pub preventExtensions: ::std::option::Option<unsafe extern "C" fn
                                                     (cx: *mut JSContext,
                                                      proxy: HandleObject,
                                                      result:
                                                          *mut ObjectOpResult)
                                                     -> bool>,
    pub isExtensible: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 succeeded: *mut bool) -> bool>,
    pub has: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject, id: HandleId,
                                        bp: *mut bool) -> bool>,
    pub get: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject,
                                        receiver: HandleValue, id: HandleId,
                                        vp: MutableHandleValue) -> bool>,
    pub set: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject,
                                        id: HandleId, v: HandleValue,
                                        receiver: HandleValue,
                                        result: *mut ObjectOpResult) -> bool>,
    pub call: ::std::option::Option<unsafe extern "C" fn
                                        (cx: *mut JSContext,
                                         proxy: HandleObject,
                                         args: *const CallArgs) -> bool>,
    pub construct: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject,
                                              args: *const CallArgs) -> bool>,
    pub getPropertyDescriptor: ::std::option::Option<unsafe extern "C" fn
                                                         (cx: *mut JSContext,
                                                          proxy: HandleObject,
                                                          id: HandleId,
                                                          desc:
                                                              MutableHandle<PropertyDescriptor>)
                                                         -> bool>,
    pub hasOwn: ::std::option::Option<unsafe extern "C" fn
                                          (cx: *mut JSContext,
                                           proxy: HandleObject, id: HandleId,
                                           bp: *mut bool) -> bool>,
    pub getOwnEnumerablePropertyKeys: ::std::option::Option<unsafe extern "C" fn
                                                                (cx:
                                                                     *mut JSContext,
                                                                 proxy:
                                                                     HandleObject,
                                                                 props:
                                                                     *mut AutoIdVector)
                                                                -> bool>,
    pub nativeCall: ::std::option::Option<unsafe extern "C" fn
                                              (cx: *mut JSContext,
                                               test: IsAcceptableThis,
                                               _impl: NativeImpl,
                                               args: CallArgs) -> bool>,
    pub hasInstance: ::std::option::Option<unsafe extern "C" fn
                                               (cx: *mut JSContext,
                                                proxy: HandleObject,
                                                v: MutableHandleValue,
                                                bp: *mut bool) -> bool>,
    pub objectClassIs: ::std::option::Option<unsafe extern "C" fn
                                                 (obj: HandleObject,
                                                  classValue: ESClass,
                                                  cx: *mut JSContext) -> bool>,
    pub className: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject)
                                             -> *const i8>,
    pub fun_toString: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 indent: u32)
                                                -> *mut JSString>,
    pub boxedValue_unbox: ::std::option::Option<unsafe extern "C" fn
                                                    (cx: *mut JSContext,
                                                     proxy: HandleObject,
                                                     vp: MutableHandleValue)
                                                    -> bool>,
    pub defaultValue: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 obj: HandleObject,
                                                 hint: JSType,
                                                 vp: MutableHandleValue)
                                                -> bool>,
    pub trace: ::std::option::Option<unsafe extern "C" fn
                                         (trc: *mut JSTracer,
                                          proxy: *mut JSObject)>,
    pub finalize: ::std::option::Option<unsafe extern "C" fn
                                            (fop: *mut FreeOp,
                                             proxy: *mut JSObject)>,
    pub objectMoved: ::std::option::Option<unsafe extern "C" fn
                                               (proxy: *mut JSObject,
                                                old: *const JSObject)>,
    pub isCallable: ::std::option::Option<unsafe extern "C" fn
                                              (obj: *mut JSObject) -> bool>,
    pub isConstructor: ::std::option::Option<unsafe extern "C" fn
                                                 (obj: *mut JSObject) -> bool>,
}
impl ::std::default::Default for ProxyTraps {
    fn default() -> ProxyTraps { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrapperProxyHandler {
    pub mTraps: ProxyTraps,
}
impl ::std::default::Default for WrapperProxyHandler {
    fn default() -> WrapperProxyHandler { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ForwardingProxyHandler {
    pub mTraps: ProxyTraps,
    pub mExtra: *const ::libc::c_void,
}
impl ::std::default::Default for ForwardingProxyHandler {
    fn default() -> ForwardingProxyHandler { unsafe { ::std::mem::zeroed() } }
}
extern "C" {
    pub fn InvokeGetOwnPropertyDescriptor(handler: *const ::libc::c_void,
                                          cx: *mut JSContext,
                                          proxy: HandleObject, id: HandleId,
                                          desc:
                                              MutableHandle<PropertyDescriptor>)
     -> bool;
    pub fn InvokeHasOwn(handler: *const ::libc::c_void,
                        cx: *mut JSContext, proxy: HandleObject,
                        id: HandleId, bp: *mut bool) -> bool;
    pub fn RUST_JS_NumberValue(d: f64) -> Value;
    pub fn RUST_FUNCTION_VALUE_TO_JITINFO(v: Value) -> *const JSJitInfo;
    pub fn CreateCallArgsFromVp(argc: u32, v: *mut Value) -> CallArgs;
    pub fn CallJitGetterOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CallJitSetterOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CallJitMethodOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CreateProxyHandler(aTraps: *const ProxyTraps,
                              aExtra: *const ::libc::c_void)
     -> *const ::libc::c_void;
    pub fn CreateWrapperProxyHandler(aTraps: *const ProxyTraps)
     -> *const ::libc::c_void;
    pub fn GetCrossCompartmentWrapper() -> *const ::libc::c_void;
    pub fn NewCompileOptions(aCx: *mut JSContext, aFile: *const ::libc::c_char,
                             aLine: u32) -> *mut ReadOnlyCompileOptions;
    pub fn DeleteCompileOptions(aOpts: *mut ReadOnlyCompileOptions);
    pub fn NewProxyObject(aCx: *mut JSContext,
                          aHandler: *const ::libc::c_void, aPriv: HandleValue,
                          proto: *mut JSObject, parent: *mut JSObject,
                          call: *mut JSObject, construct: *mut JSObject)
     -> *mut JSObject;
    pub fn WrapperNew(aCx: *mut JSContext, aObj: HandleObject,
                      aHandler: *const ::libc::c_void, aClass: *const JSClass,
                      aSingleton: bool)
     -> *mut JSObject;
    pub fn NewWindowProxy(aCx: *mut JSContext, aObj: HandleObject,
                          aHandler: *const ::libc::c_void)
     -> *mut JSObject;
    pub fn GetWindowProxyClass() -> *const Class;
    pub fn GetProxyExtra(obj: *mut JSObject, slot: u32) -> Value;
    pub fn GetProxyPrivate(obj: *mut JSObject) -> Value;
    pub fn SetProxyExtra(obj: *mut JSObject, slot: u32, val: *const Value);
    pub fn RUST_JSID_IS_INT(id: HandleId) -> bool;
    pub fn RUST_JSID_TO_INT(id: HandleId) -> i32;
    pub fn int_to_jsid(i: i32) -> jsid;
    pub fn RUST_JSID_IS_STRING(id: HandleId) -> bool;
    pub fn RUST_JSID_TO_STRING(id: HandleId) -> *mut JSString;
    pub fn RUST_SYMBOL_TO_JSID(sym: *mut Symbol) -> jsid;
    pub fn RUST_SET_JITINFO(func: *mut JSFunction, info: *const JSJitInfo);
    pub fn RUST_INTERNED_STRING_TO_JSID(cx: *mut JSContext,
                                        str: *mut JSString) -> jsid;
    pub fn RUST_js_GetErrorMessage(userRef: *mut ::libc::c_void,
                                   errorNumber: u32)
     -> *const JSErrorFormatString;
    pub fn IsProxyHandlerFamily(obj: *mut JSObject) -> u8;
    pub fn GetProxyHandlerExtra(obj: *mut JSObject) -> *const ::libc::c_void;
    pub fn GetProxyHandler(obj: *mut JSObject) -> *const ::libc::c_void;
    pub fn ReportError(aCx: *mut JSContext, aError: *const i8);
    pub fn IsWrapper(obj: *mut JSObject) -> bool;
    pub fn UnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
    pub fn UncheckedUnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
    pub fn AppendToAutoIdVector(v: *mut AutoIdVector, id: jsid) -> bool;
    pub fn CreateAutoObjectVector(aCx: *mut JSContext)
     -> *mut AutoObjectVector;
    pub fn AppendToAutoObjectVector(v: *mut AutoObjectVector,
                                    obj: *mut JSObject) -> bool;
    pub fn DeleteAutoObjectVector(v: *mut AutoObjectVector);
    pub fn CollectServoSizes(rt: *mut JSRuntime, sizes: *mut ServoSizes) -> bool;
    pub fn CallIdTracer(trc: *mut JSTracer, idp: *mut Heap<jsid>,
                        name: *const ::libc::c_char);
    pub fn CallValueTracer(trc: *mut JSTracer, valuep: *mut Heap<Value>,
                           name: *const ::libc::c_char);
    pub fn CallObjectTracer(trc: *mut JSTracer,
                            objp: *mut Heap<*mut JSObject>,
                            name: *const ::libc::c_char);
    pub fn CallStringTracer(trc: *mut JSTracer,
                            strp: *mut Heap<*mut JSString>,
                            name: *const ::libc::c_char);
    pub fn CallScriptTracer(trc: *mut JSTracer,
                            scriptp: *mut Heap<*mut JSScript>,
                            name: *const ::libc::c_char);
    pub fn CallFunctionTracer(trc: *mut JSTracer,
                              funp: *mut Heap<*mut JSFunction>,
                              name: *const ::libc::c_char);
    pub fn CallUnbarrieredObjectTracer(trc: *mut JSTracer,
                                       objp: *mut *mut JSObject,
                                       name: *const ::libc::c_char);
}
<commit_msg>Fix the wrapper finalize method arguments<commit_after>use jsapi::*;

pub enum Action { }
unsafe impl Sync for ProxyTraps { }
/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Copy, Clone)]
pub struct ProxyTraps {
    pub enter: ::std::option::Option<unsafe extern "C" fn
                                         (cx: *mut JSContext,
                                          proxy: HandleObject, id: HandleId,
                                          action: Action, bp: *mut bool) -> bool>,
    pub getOwnPropertyDescriptor: ::std::option::Option<unsafe extern "C" fn
                                                            (cx:
                                                                 *mut JSContext,
                                                             proxy:
                                                                 HandleObject,
                                                             id: HandleId,
                                                             desc:
                                                                 MutableHandle<PropertyDescriptor>)
                                                            -> bool>,
    pub defineProperty: ::std::option::Option<unsafe extern "C" fn
                                                  (cx: *mut JSContext,
                                                   proxy: HandleObject,
                                                   id: HandleId,
                                                   desc:
                                                       Handle<PropertyDescriptor>,
                                                   result:
                                                       *mut ObjectOpResult)
                                                  -> bool>,
    pub ownPropertyKeys: ::std::option::Option<unsafe extern "C" fn
                                                   (cx: *mut JSContext,
                                                    proxy: HandleObject,
                                                    props: *mut AutoIdVector)
                                                   -> bool>,
    pub delete_: ::std::option::Option<unsafe extern "C" fn
                                           (cx: *mut JSContext,
                                            proxy: HandleObject, id: HandleId,
                                            result: *mut ObjectOpResult)
                                           -> bool>,
    pub enumerate: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject,
                                              objp: MutableHandleObject)
                                             -> bool>,
    pub getPrototypeIfOrdinary: ::std::option::Option<unsafe extern "C" fn
                                                          (cx: *mut JSContext,
                                                           proxy: HandleObject,
                                                           isOrdinary: *mut bool,
                                                           protop: MutableHandleObject)
                                                          -> bool>,
    pub preventExtensions: ::std::option::Option<unsafe extern "C" fn
                                                     (cx: *mut JSContext,
                                                      proxy: HandleObject,
                                                      result:
                                                          *mut ObjectOpResult)
                                                     -> bool>,
    pub isExtensible: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 succeeded: *mut bool) -> bool>,
    pub has: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject, id: HandleId,
                                        bp: *mut bool) -> bool>,
    pub get: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject,
                                        receiver: HandleValue, id: HandleId,
                                        vp: MutableHandleValue) -> bool>,
    pub set: ::std::option::Option<unsafe extern "C" fn
                                       (cx: *mut JSContext,
                                        proxy: HandleObject,
                                        id: HandleId, v: HandleValue,
                                        receiver: HandleValue,
                                        result: *mut ObjectOpResult) -> bool>,
    pub call: ::std::option::Option<unsafe extern "C" fn
                                        (cx: *mut JSContext,
                                         proxy: HandleObject,
                                         args: *const CallArgs) -> bool>,
    pub construct: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject,
                                              args: *const CallArgs) -> bool>,
    pub getPropertyDescriptor: ::std::option::Option<unsafe extern "C" fn
                                                         (cx: *mut JSContext,
                                                          proxy: HandleObject,
                                                          id: HandleId,
                                                          desc:
                                                              MutableHandle<PropertyDescriptor>)
                                                         -> bool>,
    pub hasOwn: ::std::option::Option<unsafe extern "C" fn
                                          (cx: *mut JSContext,
                                           proxy: HandleObject, id: HandleId,
                                           bp: *mut bool) -> bool>,
    pub getOwnEnumerablePropertyKeys: ::std::option::Option<unsafe extern "C" fn
                                                                (cx:
                                                                     *mut JSContext,
                                                                 proxy:
                                                                     HandleObject,
                                                                 props:
                                                                     *mut AutoIdVector)
                                                                -> bool>,
    pub nativeCall: ::std::option::Option<unsafe extern "C" fn
                                              (cx: *mut JSContext,
                                               test: IsAcceptableThis,
                                               _impl: NativeImpl,
                                               args: CallArgs) -> bool>,
    pub hasInstance: ::std::option::Option<unsafe extern "C" fn
                                               (cx: *mut JSContext,
                                                proxy: HandleObject,
                                                v: MutableHandleValue,
                                                bp: *mut bool) -> bool>,
    pub objectClassIs: ::std::option::Option<unsafe extern "C" fn
                                                 (obj: HandleObject,
                                                  classValue: ESClass,
                                                  cx: *mut JSContext) -> bool>,
    pub className: ::std::option::Option<unsafe extern "C" fn
                                             (cx: *mut JSContext,
                                              proxy: HandleObject)
                                             -> *const i8>,
    pub fun_toString: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 indent: u32)
                                                -> *mut JSString>,
    pub boxedValue_unbox: ::std::option::Option<unsafe extern "C" fn
                                                    (cx: *mut JSContext,
                                                     proxy: HandleObject,
                                                     vp: MutableHandleValue)
                                                    -> bool>,
    pub defaultValue: ::std::option::Option<unsafe extern "C" fn
                                                (cx: *mut JSContext,
                                                 obj: HandleObject,
                                                 hint: JSType,
                                                 vp: MutableHandleValue)
                                                -> bool>,
    pub trace: ::std::option::Option<unsafe extern "C" fn
                                         (trc: *mut JSTracer,
                                          proxy: *mut JSObject)>,
    pub finalize: ::std::option::Option<unsafe extern "C" fn
                                            (fop: *mut JSFreeOp,
                                             proxy: *mut JSObject)>,
    pub objectMoved: ::std::option::Option<unsafe extern "C" fn
                                               (proxy: *mut JSObject,
                                                old: *const JSObject)>,
    pub isCallable: ::std::option::Option<unsafe extern "C" fn
                                              (obj: *mut JSObject) -> bool>,
    pub isConstructor: ::std::option::Option<unsafe extern "C" fn
                                                 (obj: *mut JSObject) -> bool>,
}
impl ::std::default::Default for ProxyTraps {
    fn default() -> ProxyTraps { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrapperProxyHandler {
    pub mTraps: ProxyTraps,
}
impl ::std::default::Default for WrapperProxyHandler {
    fn default() -> WrapperProxyHandler { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ForwardingProxyHandler {
    pub mTraps: ProxyTraps,
    pub mExtra: *const ::libc::c_void,
}
impl ::std::default::Default for ForwardingProxyHandler {
    fn default() -> ForwardingProxyHandler { unsafe { ::std::mem::zeroed() } }
}
extern "C" {
    pub fn InvokeGetOwnPropertyDescriptor(handler: *const ::libc::c_void,
                                          cx: *mut JSContext,
                                          proxy: HandleObject, id: HandleId,
                                          desc:
                                              MutableHandle<PropertyDescriptor>)
     -> bool;
    pub fn InvokeHasOwn(handler: *const ::libc::c_void,
                        cx: *mut JSContext, proxy: HandleObject,
                        id: HandleId, bp: *mut bool) -> bool;
    pub fn RUST_JS_NumberValue(d: f64) -> Value;
    pub fn RUST_FUNCTION_VALUE_TO_JITINFO(v: Value) -> *const JSJitInfo;
    pub fn CreateCallArgsFromVp(argc: u32, v: *mut Value) -> CallArgs;
    pub fn CallJitGetterOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CallJitSetterOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CallJitMethodOp(info: *const JSJitInfo, cx: *mut JSContext,
                           thisObj: HandleObject,
                           specializedThis: *mut ::libc::c_void, argc: u32,
                           vp: *mut Value) -> bool;
    pub fn CreateProxyHandler(aTraps: *const ProxyTraps,
                              aExtra: *const ::libc::c_void)
     -> *const ::libc::c_void;
    pub fn CreateWrapperProxyHandler(aTraps: *const ProxyTraps)
     -> *const ::libc::c_void;
    pub fn GetCrossCompartmentWrapper() -> *const ::libc::c_void;
    pub fn NewCompileOptions(aCx: *mut JSContext, aFile: *const ::libc::c_char,
                             aLine: u32) -> *mut ReadOnlyCompileOptions;
    pub fn DeleteCompileOptions(aOpts: *mut ReadOnlyCompileOptions);
    pub fn NewProxyObject(aCx: *mut JSContext,
                          aHandler: *const ::libc::c_void, aPriv: HandleValue,
                          proto: *mut JSObject, parent: *mut JSObject,
                          call: *mut JSObject, construct: *mut JSObject)
     -> *mut JSObject;
    pub fn WrapperNew(aCx: *mut JSContext, aObj: HandleObject,
                      aHandler: *const ::libc::c_void, aClass: *const JSClass,
                      aSingleton: bool)
     -> *mut JSObject;
    pub fn NewWindowProxy(aCx: *mut JSContext, aObj: HandleObject,
                          aHandler: *const ::libc::c_void)
     -> *mut JSObject;
    pub fn GetWindowProxyClass() -> *const Class;
    pub fn GetProxyExtra(obj: *mut JSObject, slot: u32) -> Value;
    pub fn GetProxyPrivate(obj: *mut JSObject) -> Value;
    pub fn SetProxyExtra(obj: *mut JSObject, slot: u32, val: *const Value);
    pub fn RUST_JSID_IS_INT(id: HandleId) -> bool;
    pub fn RUST_JSID_TO_INT(id: HandleId) -> i32;
    pub fn int_to_jsid(i: i32) -> jsid;
    pub fn RUST_JSID_IS_STRING(id: HandleId) -> bool;
    pub fn RUST_JSID_TO_STRING(id: HandleId) -> *mut JSString;
    pub fn RUST_SYMBOL_TO_JSID(sym: *mut Symbol) -> jsid;
    pub fn RUST_SET_JITINFO(func: *mut JSFunction, info: *const JSJitInfo);
    pub fn RUST_INTERNED_STRING_TO_JSID(cx: *mut JSContext,
                                        str: *mut JSString) -> jsid;
    pub fn RUST_js_GetErrorMessage(userRef: *mut ::libc::c_void,
                                   errorNumber: u32)
     -> *const JSErrorFormatString;
    pub fn IsProxyHandlerFamily(obj: *mut JSObject) -> u8;
    pub fn GetProxyHandlerExtra(obj: *mut JSObject) -> *const ::libc::c_void;
    pub fn GetProxyHandler(obj: *mut JSObject) -> *const ::libc::c_void;
    pub fn ReportError(aCx: *mut JSContext, aError: *const i8);
    pub fn IsWrapper(obj: *mut JSObject) -> bool;
    pub fn UnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
    pub fn UncheckedUnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
    pub fn AppendToAutoIdVector(v: *mut AutoIdVector, id: jsid) -> bool;
    pub fn CreateAutoObjectVector(aCx: *mut JSContext)
     -> *mut AutoObjectVector;
    pub fn AppendToAutoObjectVector(v: *mut AutoObjectVector,
                                    obj: *mut JSObject) -> bool;
    pub fn DeleteAutoObjectVector(v: *mut AutoObjectVector);
    pub fn CollectServoSizes(rt: *mut JSRuntime, sizes: *mut ServoSizes) -> bool;
    pub fn CallIdTracer(trc: *mut JSTracer, idp: *mut Heap<jsid>,
                        name: *const ::libc::c_char);
    pub fn CallValueTracer(trc: *mut JSTracer, valuep: *mut Heap<Value>,
                           name: *const ::libc::c_char);
    pub fn CallObjectTracer(trc: *mut JSTracer,
                            objp: *mut Heap<*mut JSObject>,
                            name: *const ::libc::c_char);
    pub fn CallStringTracer(trc: *mut JSTracer,
                            strp: *mut Heap<*mut JSString>,
                            name: *const ::libc::c_char);
    pub fn CallScriptTracer(trc: *mut JSTracer,
                            scriptp: *mut Heap<*mut JSScript>,
                            name: *const ::libc::c_char);
    pub fn CallFunctionTracer(trc: *mut JSTracer,
                              funp: *mut Heap<*mut JSFunction>,
                              name: *const ::libc::c_char);
    pub fn CallUnbarrieredObjectTracer(trc: *mut JSTracer,
                                       objp: *mut *mut JSObject,
                                       name: *const ::libc::c_char);
}
<|endoftext|>


<commit_before>//! Rendering highlighted code as HTML+CSS
use std::fmt::Write;
use parsing::{ScopeStackOp, BasicScopeStackOp, Scope, ScopeStack, SyntaxReference, SyntaxSet, SCOPE_REPO};
use easy::{HighlightLines, HighlightFile};
use highlighting::{Color, FontStyle, Style, Theme};
use util::LinesWithEndings;
use escape::Escape;
use std::io::{self, BufRead};
use std::path::Path;

/// Only one style for now, I may add more class styles later.
/// Just here so I don't have to change the API
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ClassStyle {
    /// The classes are the atoms of the scope separated by spaces
    /// (e.g `source.php` becomes `source php`).
    /// This isn't that fast since it has to use the scope repository
    /// to look up scope names.
    Spaced,
}

fn scope_to_classes(s: &mut String, scope: Scope, style: ClassStyle) {
    assert!(style == ClassStyle::Spaced); // TODO more styles
    let repo = SCOPE_REPO.lock().unwrap();
    for i in 0..(scope.len()) {
        let atom = scope.atom_at(i as usize);
        let atom_s = repo.atom_str(atom);
        if i != 0 {
            s.push_str(" ")
        }
        s.push_str(atom_s);
    }
}

/// Convenience method that combines `start_coloured_html_snippet`, `styles_to_coloured_html`
/// and `HighlightLines` from `syntect::easy` to create a full highlighted HTML snippet for
/// a string (which can contain many lines).
///
/// Note that the `syntax` passed in must be from a `SyntaxSet` compiled for newline characters.
/// This is easy to get with `SyntaxSet::load_defaults_newlines()`. (Note: this was different before v3.0)
pub fn highlighted_html_for_string(s: &str, ss: &SyntaxSet, syntax: &SyntaxReference, theme: &Theme) -> String {
    let mut highlighter = HighlightLines::new(syntax, theme);
    let (mut output, bg) = start_coloured_html_snippet(theme);

    for line in LinesWithEndings::from(s) {
        let regions = highlighter.highlight(line, ss);
        append_coloured_html_for_styles(&regions[..], IncludeBackground::IfDifferent(bg), &mut output);
    }
    output.push_str("
\n");
    output
}

/// Convenience method that combines `start_coloured_html_snippet`, `styles_to_coloured_html`
/// and `HighlightFile` from `syntect::easy` to create a full highlighted HTML snippet for
/// a file.
///
/// Note that the `syntax` passed in must be from a `SyntaxSet` compiled for newline characters.
/// This is easy to get with `SyntaxSet::load_defaults_newlines()`. (Note: this was different before v3.0)
pub fn highlighted_html_for_file<P: AsRef<Path>>(path: P,
                                                 ss: &SyntaxSet,
                                                 theme: &Theme)
                                                 -> io::Result<String> {
    let mut highlighter = HighlightFile::new(path, ss, theme)?;
    let (mut output, bg) = start_coloured_html_snippet(theme);

    let mut line = String::new();
    while highlighter.reader.read_line(&mut line)? > 0 {
        {
            let regions = highlighter.highlight_lines.highlight(&line, ss);
            append_coloured_html_for_styles(&regions[..], IncludeBackground::IfDifferent(bg), &mut output);
        }
        line.clear();
    }
    output.push_str("
\n");
    Ok(output)
}

/// Output HTML for a line of code with `<span>` elements
/// specifying classes for each token. The span elements are nested
/// like the scope stack and the scopes are mapped to classes based
/// on the `ClassStyle` (see it's docs).
///
/// For this to work correctly you must concatenate all the lines in a `<pre>`
/// tag since some span tags opened on a line may not be closed on that line
/// and later lines may close tags from previous lines.
pub fn tokens_to_classed_html(line: &str,
                              ops: &[(usize, ScopeStackOp)],
                              style: ClassStyle)
                              -> String {
    let mut s = String::with_capacity(line.len() + ops.len() * 8); // a guess
    let mut cur_index = 0;
    let mut stack = ScopeStack::new();
    for &(i, ref op) in ops {
        if i > cur_index {
            write!(s, "{}", Escape(&line[cur_index..i])).unwrap();
            cur_index = i
        }
        stack.apply_with_hook(op, |basic_op, _| {
            match basic_op {
                BasicScopeStackOp::Push(scope) => {
                    s.push_str("");
                }
                BasicScopeStackOp::Pop => {
                    s.push_str("");
                }
            }
        });
    }
    s
}

/// Determines how background colour attributes are generated
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum IncludeBackground {
    /// Don't include `background-color`, for performance or so that you can use your own background.
    No,
    /// Set background colour attributes on every node
    Yes,
    /// Only set the `background-color` if it is different than the default (presumably set on a parent element)
    IfDifferent(Color),
}

fn write_css_color(s: &mut String, c: Color) {
    if c.a != 0xFF {
        write!(s,"#{:02x}{:02x}{:02x}{:02x}",c.r,c.g,c.b,c.a).unwrap();
    } else {
        write!(s,"#{:02x}{:02x}{:02x}",c.r,c.g,c.b).unwrap();
    }
}

/// Output HTML for a line of code with `<span>` elements using inline
/// `style` attributes to set the correct font attributes.
/// The `bg` attribute determines if the spans will have the `background-color`
/// attribute set. See the `IncludeBackground` enum's docs.
///
/// The lines returned don't include a newline at the end.
/// # Examples
///
/// ```
/// use syntect::easy::HighlightLines;
/// use syntect::parsing::SyntaxSet;
/// use syntect::highlighting::{ThemeSet, Style};
/// use syntect::html::{styles_to_coloured_html, IncludeBackground};
///
/// // Load these once at the start of your program
/// let ps = SyntaxSet::load_defaults_newlines();
/// let ts = ThemeSet::load_defaults();
///
/// let syntax = ps.find_syntax_by_name("Ruby").unwrap();
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let regions = h.highlight("5", &ps);
/// let html = styles_to_coloured_html(&regions[..], IncludeBackground::No);
/// assert_eq!(html, "<span style=\"color:#d08770;\">5</span>");
/// ```
pub fn styles_to_coloured_html(v: &[(Style, &str)], bg: IncludeBackground) -> String {
    let mut s: String = String::new();
    append_coloured_html_for_styles(v, bg, &mut s);
    s
}

/// Like `styles_to_coloured_html` but appends to a `String` for increased efficiency.
/// In fact `styles_to_coloured_html` is just a wrapper around this function.
pub fn append_coloured_html_for_styles(v: &[(Style, &str)], bg: IncludeBackground, mut s: &mut String) {
    let mut prev_style: Option<&Style> = None;
    for &(ref style, text) in v.iter() {
        let unify_style = if let Some(ps) = prev_style {
            style == ps ||
                (style.background == ps.background && text.trim().is_empty())
        } else {
            false
        };
        if unify_style {
            write!(s, "{}", Escape(text)).unwrap();
        } else {
            if prev_style.is_some() {
                write!(s, "").unwrap();
            }
            prev_style = Some(style);
            write!(s, " true,
                IncludeBackground::No => false,
                IncludeBackground::IfDifferent(c) => (style.background != c),
            };
            if include_bg {
                write!(s, "background-color:").unwrap();
                write_css_color(&mut s, style.background);
                write!(s, ";").unwrap();
            }
            if style.font_style.contains(FontStyle::UNDERLINE) {
                write!(s, "text-decoration:underline;").unwrap();
            }
            if style.font_style.contains(FontStyle::BOLD) {
                write!(s, "font-weight:bold;").unwrap();
            }
            if style.font_style.contains(FontStyle::ITALIC) {
                write!(s, "font-style:italic;").unwrap();
            }
            write!(s, "color:").unwrap();
            write_css_color(&mut s, style.foreground);
            write!(s, ";\">{}", Escape(text)).unwrap();
        }
    }
    if prev_style.is_some() {
        write!(s, "").unwrap();
    }
}

/// Returns a `<pre style="...">\n` tag with the correct background color for the given theme.
/// This is for if you want to roll your own HTML output, you probably just want to use
/// `highlighted_html_for_string`.
///
/// If you don't care about the background color you can just prefix the lines from
/// `styles_to_coloured_html` with a `<pre>`. This is meant to be used with `IncludeBackground::IfDifferent`.
/// As of `v3.0` this method also returns the background color to be passed to `IfDifferent`.
///
/// You're responsible for creating the string `</pre>` to close this, I'm not gonna provide a
/// helper for that :-)
pub fn start_coloured_html_snippet(t: &Theme) -> (String, Color) {
    let c = t.settings.background.unwrap_or(Color::WHITE);
    (format!("
\n",
            c.r,
            c.g,
            c.b), c)
}

#[cfg(test)]
mod tests {
    use super::*;
    use parsing::{SyntaxSet, ParseState, ScopeStack, SyntaxSetBuilder};
    use highlighting::{ThemeSet, Style, Highlighter, HighlightIterator, HighlightState};
    #[test]
    fn tokens() {
        let ss = SyntaxSet::load_defaults_newlines();
        let syntax = ss.find_syntax_by_name("Markdown").unwrap();
        let mut state = ParseState::new(syntax);
        let line = "[w](t.co) *hi* **five**";
        let ops = state.parse_line(line, &ss);

        // use util::debug_print_ops;
        // debug_print_ops(line, &ops);

        let html = tokens_to_classed_html(line, &ops[..], ClassStyle::Spaced);
        println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test2.html").trim_right());

        let ts = ThemeSet::load_defaults();
        let highlighter = Highlighter::new(&ts.themes["InspiredGitHub"]);
        let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
        let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
        let regions: Vec<(Style, &str)> = iter.collect();

        let html2 = styles_to_coloured_html(&regions[..], IncludeBackground::Yes);
        println!("{}", html2);
        assert_eq!(html2, include_str!("../testdata/test1.html").trim_right());
    }

    #[test]
    fn strings() {
        let ss = SyntaxSet::load_defaults_newlines();
        let ts = ThemeSet::load_defaults();
        let s = include_str!("../testdata/highlight_test.erb");
        let syntax = ss.find_syntax_by_extension("erb").unwrap();
        let html = highlighted_html_for_string(s, &ss, syntax, &ts.themes["base16-ocean.dark"]);
        // println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test3.html"));
        let html2 = highlighted_html_for_file("testdata/highlight_test.erb",
                                                 &ss,
                                                 &ts.themes["base16-ocean.dark"])
            .unwrap();
        assert_eq!(html2, html);

        // YAML is a tricky syntax and InspiredGitHub is a fancy theme, this is basically an integration test
        let html3 = highlighted_html_for_file("testdata/Packages/Rust/Cargo.sublime-syntax",
                                                 &ss,
                                                 &ts.themes["InspiredGitHub"])
            .unwrap();
        println!("{}", html3);
        assert_eq!(html3, include_str!("../testdata/test4.html"));
    }

    #[test]
    fn tricky_test_syntax() {
        // This syntax I wrote tests edge cases of prototypes
        // I verified the output HTML against what ST3 does with the same syntax and file
        let mut builder = SyntaxSetBuilder::new();
        builder.add_from_folder("testdata", true).unwrap();
        let ss = builder.build();
        let ts = ThemeSet::load_defaults();
        let html = highlighted_html_for_file("testdata/testing-syntax.testsyntax",
                                                &ss,
                                                &ts.themes["base16-ocean.dark"])
            .unwrap();
        println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test5.html"));
    }
}
<commit_msg>Better names for small HTML helpers<commit_after>//! Rendering highlighted code as HTML+CSS
use std::fmt::Write;
use parsing::{ScopeStackOp, BasicScopeStackOp, Scope, ScopeStack, SyntaxReference, SyntaxSet, SCOPE_REPO};
use easy::{HighlightLines, HighlightFile};
use highlighting::{Color, FontStyle, Style, Theme};
use util::LinesWithEndings;
use escape::Escape;
use std::io::{self, BufRead};
use std::path::Path;

/// Only one style for now, I may add more class styles later.
/// Just here so I don't have to change the API
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ClassStyle {
    /// The classes are the atoms of the scope separated by spaces
    /// (e.g `source.php` becomes `source php`).
    /// This isn't that fast since it has to use the scope repository
    /// to look up scope names.
    Spaced,
}

fn scope_to_classes(s: &mut String, scope: Scope, style: ClassStyle) {
    assert!(style == ClassStyle::Spaced); // TODO more styles
    let repo = SCOPE_REPO.lock().unwrap();
    for i in 0..(scope.len()) {
        let atom = scope.atom_at(i as usize);
        let atom_s = repo.atom_str(atom);
        if i != 0 {
            s.push_str(" ")
        }
        s.push_str(atom_s);
    }
}

/// Convenience method that combines `start_highlighted_html_snippet`, `styled_line_to_highlighted_html`
/// and `HighlightLines` from `syntect::easy` to create a full highlighted HTML snippet for
/// a string (which can contain many lines).
///
/// Note that the `syntax` passed in must be from a `SyntaxSet` compiled for newline characters.
/// This is easy to get with `SyntaxSet::load_defaults_newlines()`. (Note: this was different before v3.0)
pub fn highlighted_html_for_string(s: &str, ss: &SyntaxSet, syntax: &SyntaxReference, theme: &Theme) -> String {
    let mut highlighter = HighlightLines::new(syntax, theme);
    let (mut output, bg) = start_highlighted_html_snippet(theme);

    for line in LinesWithEndings::from(s) {
        let regions = highlighter.highlight(line, ss);
        append_highlighted_html_for_styled_line(&regions[..], IncludeBackground::IfDifferent(bg), &mut output);
    }
    output.push_str("
\n");
    output
}

/// Convenience method that combines `start_highlighted_html_snippet`, `styled_line_to_highlighted_html`
/// and `HighlightFile` from `syntect::easy` to create a full highlighted HTML snippet for
/// a file.
///
/// Note that the `syntax` passed in must be from a `SyntaxSet` compiled for newline characters.
/// This is easy to get with `SyntaxSet::load_defaults_newlines()`. (Note: this was different before v3.0)
pub fn highlighted_html_for_file<P: AsRef<Path>>(path: P,
                                                 ss: &SyntaxSet,
                                                 theme: &Theme)
                                                 -> io::Result<String> {
    let mut highlighter = HighlightFile::new(path, ss, theme)?;
    let (mut output, bg) = start_highlighted_html_snippet(theme);

    let mut line = String::new();
    while highlighter.reader.read_line(&mut line)? > 0 {
        {
            let regions = highlighter.highlight_lines.highlight(&line, ss);
            append_highlighted_html_for_styled_line(&regions[..], IncludeBackground::IfDifferent(bg), &mut output);
        }
        line.clear();
    }
    output.push_str("
\n");
    Ok(output)
}

/// Output HTML for a line of code with `<span>` elements
/// specifying classes for each token. The span elements are nested
/// like the scope stack and the scopes are mapped to classes based
/// on the `ClassStyle` (see it's docs).
///
/// For this to work correctly you must concatenate all the lines in a `<pre>`
/// tag since some span tags opened on a line may not be closed on that line
/// and later lines may close tags from previous lines.
pub fn tokens_to_classed_html(line: &str,
                              ops: &[(usize, ScopeStackOp)],
                              style: ClassStyle)
                              -> String {
    let mut s = String::with_capacity(line.len() + ops.len() * 8); // a guess
    let mut cur_index = 0;
    let mut stack = ScopeStack::new();
    for &(i, ref op) in ops {
        if i > cur_index {
            write!(s, "{}", Escape(&line[cur_index..i])).unwrap();
            cur_index = i
        }
        stack.apply_with_hook(op, |basic_op, _| {
            match basic_op {
                BasicScopeStackOp::Push(scope) => {
                    s.push_str("");
                }
                BasicScopeStackOp::Pop => {
                    s.push_str("");
                }
            }
        });
    }
    s
}

/// Determines how background color attributes are generated
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum IncludeBackground {
    /// Don't include `background-color`, for performance or so that you can use your own background.
    No,
    /// Set background color attributes on every node
    Yes,
    /// Only set the `background-color` if it is different than the default (presumably set on a parent element)
    IfDifferent(Color),
}

fn write_css_color(s: &mut String, c: Color) {
    if c.a != 0xFF {
        write!(s,"#{:02x}{:02x}{:02x}{:02x}",c.r,c.g,c.b,c.a).unwrap();
    } else {
        write!(s,"#{:02x}{:02x}{:02x}",c.r,c.g,c.b).unwrap();
    }
}

/// Output HTML for a line of code with `<span>` elements using inline
/// `style` attributes to set the correct font attributes.
/// The `bg` attribute determines if the spans will have the `background-color`
/// attribute set. See the `IncludeBackground` enum's docs.
///
/// The lines returned don't include a newline at the end.
/// # Examples
///
/// ```
/// use syntect::easy::HighlightLines;
/// use syntect::parsing::SyntaxSet;
/// use syntect::highlighting::{ThemeSet, Style};
/// use syntect::html::{styled_line_to_highlighted_html, IncludeBackground};
///
/// // Load these once at the start of your program
/// let ps = SyntaxSet::load_defaults_newlines();
/// let ts = ThemeSet::load_defaults();
///
/// let syntax = ps.find_syntax_by_name("Ruby").unwrap();
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let regions = h.highlight("5", &ps);
/// let html = styled_line_to_highlighted_html(&regions[..], IncludeBackground::No);
/// assert_eq!(html, "<span style=\"color:#d08770;\">5</span>");
/// ```
pub fn styled_line_to_highlighted_html(v: &[(Style, &str)], bg: IncludeBackground) -> String {
    let mut s: String = String::new();
    append_highlighted_html_for_styled_line(v, bg, &mut s);
    s
}

/// Like `styled_line_to_highlighted_html` but appends to a `String` for increased efficiency.
/// In fact `styled_line_to_highlighted_html` is just a wrapper around this function.
pub fn append_highlighted_html_for_styled_line(v: &[(Style, &str)], bg: IncludeBackground, mut s: &mut String) {
    let mut prev_style: Option<&Style> = None;
    for &(ref style, text) in v.iter() {
        let unify_style = if let Some(ps) = prev_style {
            style == ps ||
                (style.background == ps.background && text.trim().is_empty())
        } else {
            false
        };
        if unify_style {
            write!(s, "{}", Escape(text)).unwrap();
        } else {
            if prev_style.is_some() {
                write!(s, "").unwrap();
            }
            prev_style = Some(style);
            write!(s, " true,
                IncludeBackground::No => false,
                IncludeBackground::IfDifferent(c) => (style.background != c),
            };
            if include_bg {
                write!(s, "background-color:").unwrap();
                write_css_color(&mut s, style.background);
                write!(s, ";").unwrap();
            }
            if style.font_style.contains(FontStyle::UNDERLINE) {
                write!(s, "text-decoration:underline;").unwrap();
            }
            if style.font_style.contains(FontStyle::BOLD) {
                write!(s, "font-weight:bold;").unwrap();
            }
            if style.font_style.contains(FontStyle::ITALIC) {
                write!(s, "font-style:italic;").unwrap();
            }
            write!(s, "color:").unwrap();
            write_css_color(&mut s, style.foreground);
            write!(s, ";\">{}", Escape(text)).unwrap();
        }
    }
    if prev_style.is_some() {
        write!(s, "").unwrap();
    }
}

/// Returns a `<pre style="...">\n` tag with the correct background color for the given theme.
/// This is for if you want to roll your own HTML output, you probably just want to use
/// `highlighted_html_for_string`.
///
/// If you don't care about the background color you can just prefix the lines from
/// `styled_line_to_highlighted_html` with a `<pre>`. This is meant to be used with `IncludeBackground::IfDifferent`.
/// As of `v3.0` this method also returns the background color to be passed to `IfDifferent`.
///
/// You're responsible for creating the string `</pre>` to close this, I'm not gonna provide a
/// helper for that :-)
pub fn start_highlighted_html_snippet(t: &Theme) -> (String, Color) {
    let c = t.settings.background.unwrap_or(Color::WHITE);
    (format!("
\n",
            c.r,
            c.g,
            c.b), c)
}

#[cfg(test)]
mod tests {
    use super::*;
    use parsing::{SyntaxSet, ParseState, ScopeStack, SyntaxSetBuilder};
    use highlighting::{ThemeSet, Style, Highlighter, HighlightIterator, HighlightState};
    #[test]
    fn tokens() {
        let ss = SyntaxSet::load_defaults_newlines();
        let syntax = ss.find_syntax_by_name("Markdown").unwrap();
        let mut state = ParseState::new(syntax);
        let line = "[w](t.co) *hi* **five**";
        let ops = state.parse_line(line, &ss);

        // use util::debug_print_ops;
        // debug_print_ops(line, &ops);

        let html = tokens_to_classed_html(line, &ops[..], ClassStyle::Spaced);
        println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test2.html").trim_right());

        let ts = ThemeSet::load_defaults();
        let highlighter = Highlighter::new(&ts.themes["InspiredGitHub"]);
        let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
        let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
        let regions: Vec<(Style, &str)> = iter.collect();

        let html2 = styled_line_to_highlighted_html(&regions[..], IncludeBackground::Yes);
        println!("{}", html2);
        assert_eq!(html2, include_str!("../testdata/test1.html").trim_right());
    }

    #[test]
    fn strings() {
        let ss = SyntaxSet::load_defaults_newlines();
        let ts = ThemeSet::load_defaults();
        let s = include_str!("../testdata/highlight_test.erb");
        let syntax = ss.find_syntax_by_extension("erb").unwrap();
        let html = highlighted_html_for_string(s, &ss, syntax, &ts.themes["base16-ocean.dark"]);
        // println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test3.html"));
        let html2 = highlighted_html_for_file("testdata/highlight_test.erb",
                                                 &ss,
                                                 &ts.themes["base16-ocean.dark"])
            .unwrap();
        assert_eq!(html2, html);

        // YAML is a tricky syntax and InspiredGitHub is a fancy theme, this is basically an integration test
        let html3 = highlighted_html_for_file("testdata/Packages/Rust/Cargo.sublime-syntax",
                                                 &ss,
                                                 &ts.themes["InspiredGitHub"])
            .unwrap();
        println!("{}", html3);
        assert_eq!(html3, include_str!("../testdata/test4.html"));
    }

    #[test]
    fn tricky_test_syntax() {
        // This syntax I wrote tests edge cases of prototypes
        // I verified the output HTML against what ST3 does with the same syntax and file
        let mut builder = SyntaxSetBuilder::new();
        builder.add_from_folder("testdata", true).unwrap();
        let ss = builder.build();
        let ts = ThemeSet::load_defaults();
        let html = highlighted_html_for_file("testdata/testing-syntax.testsyntax",
                                                &ss,
                                                &ts.themes["base16-ocean.dark"])
            .unwrap();
        println!("{}", html);
        assert_eq!(html, include_str!("../testdata/test5.html"));
    }
}
<|endoftext|>


<commit_before>///! An item is line of text that read from `find` command or stdin together with
///! the internal states, such as selected or not
use std::cmp::min;
use std::default::Default;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

use crate::spinlock::{SpinLock, SpinLockGuard};
use crate::{MatchRange, Rank, SkimItem};

//------------------------------------------------------------------------------

#[derive(Debug)]
pub struct RankBuilder {
    criterion: Vec<RankCriteria>,
}

impl Default for RankBuilder {
    fn default() -> Self {
        Self {
            criterion: vec![RankCriteria::Score, RankCriteria::Begin, RankCriteria::End],
        }
    }
}

impl RankBuilder {
    pub fn new(mut criterion: Vec<RankCriteria>) -> Self {
        criterion.dedup();
        Self { criterion }
    }

    /// score: the greater the better
    pub fn build_rank(&self, score: i32, begin: usize, end: usize, length: usize) -> Rank {
        let mut rank = [0; 4];
        let begin = begin as i32;
        let end = end as i32;
        let length = length as i32;

        for (index, criteria) in self.criterion.iter().take(4).enumerate() {
            let value = match criteria {
                RankCriteria::Score => -score,
                RankCriteria::Begin => begin,
                RankCriteria::End => end,
                RankCriteria::NegScore => score,
                RankCriteria::NegBegin => -begin,
                RankCriteria::NegEnd => -end,
                RankCriteria::Length => length,
                RankCriteria::NegLength => -length,
            };

            rank[index] = value;
        }

        rank
    }
}

//------------------------------------------------------------------------------
#[derive(Clone)]
pub struct MatchedItem {
    pub item: Arc<dyn SkimItem>,
    pub rank: Rank,
    pub matched_range: Option<MatchRange>, // range of chars that matched the pattern
    pub item_idx: u32,
}

impl MatchedItem {}

use std::cmp::Ordering as CmpOrd;

impl PartialEq for MatchedItem {
    fn eq(&self, other: &Self) -> bool {
        self.rank.eq(&other.rank)
    }
}

impl std::cmp::Eq for MatchedItem {}

impl PartialOrd for MatchedItem {
    fn partial_cmp(&self, other: &Self) -> Option<CmpOrd> {
        self.rank.partial_cmp(&other.rank)
    }
}

impl Ord for MatchedItem {
    fn cmp(&self, other: &Self) -> CmpOrd {
        self.rank.cmp(&other.rank)
    }
}

//------------------------------------------------------------------------------
const ITEM_POOL_CAPACITY: usize = 1024;

pub struct ItemPool {
    length: AtomicUsize,
    pool: SpinLock<Vec<Arc<dyn SkimItem>>>,
    /// number of items that was `take`n
    taken: AtomicUsize,

    /// reverse first N lines as header
    reserved_items: SpinLock<Vec<Arc<dyn SkimItem>>>,
    lines_to_reserve: usize,
}

impl ItemPool {
    pub fn new() -> Self {
        Self {
            length: AtomicUsize::new(0),
            pool: SpinLock::new(Vec::with_capacity(ITEM_POOL_CAPACITY)),
            taken: AtomicUsize::new(0),
            reserved_items: SpinLock::new(Vec::new()),
            lines_to_reserve: 0,
        }
    }

    pub fn lines_to_reserve(mut self, lines_to_reserve: usize) -> Self {
        self.lines_to_reserve = lines_to_reserve;
        self
    }

    pub fn len(&self) -> usize {
        self.length.load(Ordering::SeqCst)
    }

    pub fn num_not_taken(&self) -> usize {
        self.length.load(Ordering::SeqCst) - self.taken.load(Ordering::SeqCst)
    }

    pub fn num_taken(&self) -> usize {
        self.taken.load(Ordering::SeqCst)
    }

    pub fn clear(&self) {
        let mut items = self.pool.lock();
        items.clear();
        let mut header_items = self.reserved_items.lock();
        header_items.clear();
        self.taken.store(0, Ordering::SeqCst);
        self.length.store(0, Ordering::SeqCst);
    }

    pub fn reset(&self) {
        // lock to ensure consistency
        let _items = self.pool.lock();
        self.taken.store(0, Ordering::SeqCst);
    }

    /// append the items and return the new_size of the pool
    pub fn append(&self, mut items: Vec<Arc<dyn SkimItem>>) -> usize {
        let len = items.len();
        trace!("item pool, append {} items", len);
        let mut pool = self.pool.lock();
        let mut header_items = self.reserved_items.lock();

        let to_reserve = self.lines_to_reserve - header_items.len();
        if to_reserve > 0 {
            let to_reserve = min(to_reserve, items.len());
            header_items.extend_from_slice(&items[..to_reserve]);
            pool.extend_from_slice(&items[to_reserve..]);
        } else {
            pool.append(&mut items);
        }
        self.length.store(pool.len(), Ordering::SeqCst);
        trace!("item pool, done append {} items", len);
        pool.len()
    }

    pub fn take(&self) -> ItemPoolGuard<Arc<dyn SkimItem>> {
        let guard = self.pool.lock();
        let taken = self.taken.swap(guard.len(), Ordering::SeqCst);
        ItemPoolGuard { guard, start: taken }
    }

    pub fn reserved(&self) -> ItemPoolGuard<Arc<dyn SkimItem>> {
        let guard = self.reserved_items.lock();
        ItemPoolGuard { guard, start: 0 }
    }
}

pub struct ItemPoolGuard<'a, T: Sized + 'a> {
    guard: SpinLockGuard<'a, Vec<T>>,
    start: usize,
}

impl<'mutex, T: Sized> Deref for ItemPoolGuard<'mutex, T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        &self.guard[self.start..]
    }
}

//------------------------------------------------------------------------------
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum RankCriteria {
    Score,
    Begin,
    End,
    NegScore,
    NegBegin,
    NegEnd,
    Length,
    NegLength,
}

pub fn parse_criteria(text: &str) -> Option<RankCriteria> {
    match text.to_lowercase().as_ref() {
        "score" => Some(RankCriteria::Score),
        "begin" => Some(RankCriteria::Begin),
        "end" => Some(RankCriteria::End),
        "-score" => Some(RankCriteria::NegScore),
        "-begin" => Some(RankCriteria::NegBegin),
        "-end" => Some(RankCriteria::NegEnd),
        "length" => Some(RankCriteria::Length),
        "-length" => Some(RankCriteria::NegLength),
        _ => None,
    }
}
<commit_msg>fix: tiebreak should contains score by default<commit_after>///! An item is line of text that read from `find` command or stdin together with
///! the internal states, such as selected or not
use std::cmp::min;
use std::default::Default;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

use crate::spinlock::{SpinLock, SpinLockGuard};
use crate::{MatchRange, Rank, SkimItem};

//------------------------------------------------------------------------------

#[derive(Debug)]
pub struct RankBuilder {
    criterion: Vec<RankCriteria>,
}

impl Default for RankBuilder {
    fn default() -> Self {
        Self {
            criterion: vec![RankCriteria::Score, RankCriteria::Begin, RankCriteria::End],
        }
    }
}

impl RankBuilder {
    pub fn new(mut criterion: Vec<RankCriteria>) -> Self {
        if !criterion.contains(&RankCriteria::Score) && !criterion.contains(&RankCriteria::NegScore) {
            criterion.insert(0, RankCriteria::Score);
        }

        criterion.dedup();
        Self { criterion }
    }

    /// score: the greater the better
    pub fn build_rank(&self, score: i32, begin: usize, end: usize, length: usize) -> Rank {
        let mut rank = [0; 4];
        let begin = begin as i32;
        let end = end as i32;
        let length = length as i32;

        for (index, criteria) in self.criterion.iter().take(4).enumerate() {
            let value = match criteria {
                RankCriteria::Score => -score,
                RankCriteria::Begin => begin,
                RankCriteria::End => end,
                RankCriteria::NegScore => score,
                RankCriteria::NegBegin => -begin,
                RankCriteria::NegEnd => -end,
                RankCriteria::Length => length,
                RankCriteria::NegLength => -length,
            };

            rank[index] = value;
        }

        rank
    }
}

//------------------------------------------------------------------------------
#[derive(Clone)]
pub struct MatchedItem {
    pub item: Arc<dyn SkimItem>,
    pub rank: Rank,
    pub matched_range: Option<MatchRange>, // range of chars that matched the pattern
    pub item_idx: u32,
}

impl MatchedItem {}

use std::cmp::Ordering as CmpOrd;

impl PartialEq for MatchedItem {
    fn eq(&self, other: &Self) -> bool {
        self.rank.eq(&other.rank)
    }
}

impl std::cmp::Eq for MatchedItem {}

impl PartialOrd for MatchedItem {
    fn partial_cmp(&self, other: &Self) -> Option<CmpOrd> {
        self.rank.partial_cmp(&other.rank)
    }
}

impl Ord for MatchedItem {
    fn cmp(&self, other: &Self) -> CmpOrd {
        self.rank.cmp(&other.rank)
    }
}

//------------------------------------------------------------------------------
const ITEM_POOL_CAPACITY: usize = 1024;

pub struct ItemPool {
    length: AtomicUsize,
    pool: SpinLock<Vec<Arc<dyn SkimItem>>>,
    /// number of items that was `take`n
    taken: AtomicUsize,

    /// reverse first N lines as header
    reserved_items: SpinLock<Vec<Arc<dyn SkimItem>>>,
    lines_to_reserve: usize,
}

impl ItemPool {
    pub fn new() -> Self {
        Self {
            length: AtomicUsize::new(0),
            pool: SpinLock::new(Vec::with_capacity(ITEM_POOL_CAPACITY)),
            taken: AtomicUsize::new(0),
            reserved_items: SpinLock::new(Vec::new()),
            lines_to_reserve: 0,
        }
    }

    pub fn lines_to_reserve(mut self, lines_to_reserve: usize) -> Self {
        self.lines_to_reserve = lines_to_reserve;
        self
    }

    pub fn len(&self) -> usize {
        self.length.load(Ordering::SeqCst)
    }

    pub fn num_not_taken(&self) -> usize {
        self.length.load(Ordering::SeqCst) - self.taken.load(Ordering::SeqCst)
    }

    pub fn num_taken(&self) -> usize {
        self.taken.load(Ordering::SeqCst)
    }

    pub fn clear(&self) {
        let mut items = self.pool.lock();
        items.clear();
        let mut header_items = self.reserved_items.lock();
        header_items.clear();
        self.taken.store(0, Ordering::SeqCst);
        self.length.store(0, Ordering::SeqCst);
    }

    pub fn reset(&self) {
        // lock to ensure consistency
        let _items = self.pool.lock();
        self.taken.store(0, Ordering::SeqCst);
    }

    /// append the items and return the new_size of the pool
    pub fn append(&self, mut items: Vec<Arc<dyn SkimItem>>) -> usize {
        let len = items.len();
        trace!("item pool, append {} items", len);
        let mut pool = self.pool.lock();
        let mut header_items = self.reserved_items.lock();

        let to_reserve = self.lines_to_reserve - header_items.len();
        if to_reserve > 0 {
            let to_reserve = min(to_reserve, items.len());
            header_items.extend_from_slice(&items[..to_reserve]);
            pool.extend_from_slice(&items[to_reserve..]);
        } else {
            pool.append(&mut items);
        }
        self.length.store(pool.len(), Ordering::SeqCst);
        trace!("item pool, done append {} items", len);
        pool.len()
    }

    pub fn take(&self) -> ItemPoolGuard<Arc<dyn SkimItem>> {
        let guard = self.pool.lock();
        let taken = self.taken.swap(guard.len(), Ordering::SeqCst);
        ItemPoolGuard { guard, start: taken }
    }

    pub fn reserved(&self) -> ItemPoolGuard<Arc<dyn SkimItem>> {
        let guard = self.reserved_items.lock();
        ItemPoolGuard { guard, start: 0 }
    }
}

pub struct ItemPoolGuard<'a, T: Sized + 'a> {
    guard: SpinLockGuard<'a, Vec<T>>,
    start: usize,
}

impl<'mutex, T: Sized> Deref for ItemPoolGuard<'mutex, T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        &self.guard[self.start..]
    }
}

//------------------------------------------------------------------------------
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum RankCriteria {
    Score,
    Begin,
    End,
    NegScore,
    NegBegin,
    NegEnd,
    Length,
    NegLength,
}

pub fn parse_criteria(text: &str) -> Option<RankCriteria> {
    match text.to_lowercase().as_ref() {
        "score" => Some(RankCriteria::Score),
        "begin" => Some(RankCriteria::Begin),
        "end" => Some(RankCriteria::End),
        "-score" => Some(RankCriteria::NegScore),
        "-begin" => Some(RankCriteria::NegBegin),
        "-end" => Some(RankCriteria::NegEnd),
        "length" => Some(RankCriteria::Length),
        "-length" => Some(RankCriteria::NegLength),
        _ => None,
    }
}
<|endoftext|>


<commit_before>//! Draw Line

use internal;
use triangulation;
use Graphics;
use Color;
use math::Matrix2d;
use DrawState;

/// The shape of the line
#[derive(Copy, Clone)]
pub enum Shape {
    /// Square edges
    Square,
    /// Round edges
    Round,
    /// Bevel edges
    Bevel,
}

/// A colored line with a default border radius
#[derive(Copy, Clone)]
pub struct Line {
    /// The line color
    pub color: internal::Color,
    /// The line radius
    pub radius: internal::Radius,
    /// The line shape
    pub shape: Shape,
}

impl Line {
    /// Creates a new line
    pub fn new(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Square,
        }
    }

    /// Creates a new line
    pub fn new_round(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Round,
        }
    }

    /// Draw the line.
    pub fn draw<G>(
        &self,
        line: internal::Line,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        match self.shape {
            Shape::Square => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    2,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
            Shape::Round => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    64,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
            Shape::Bevel => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    3,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
        }
    }

    /// Draws an arrow
    ///
    /// Head size is the sides of the triangle
    /// between the arrow hooks and the line
    pub fn draw_arrow<G>(
        &self,
        line: internal::Line,
        head_size: internal::Scalar,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        use Transformed;

        self.draw(line, draw_state, transform, g);
        let diff = [line[2] - line[0], line[3] - line[1]];
        let arrow_head = transform
            .trans(line[2], line[3])
            .orient(diff[0], diff[1]);
        self.draw([-head_size, head_size, 0.0, 0.0], draw_state, arrow_head, g);
        self.draw([-head_size, -head_size, 0.0, 0.0], draw_state, arrow_head, g);
    }
}

/*
quack! {
    set:
        fn (val: Color) [] { l.color = val.0 }
        fn (val: Radius) [] { l.radius = val.0 }
        fn (val: Width) [] { l.radius = 0.5 * val.0 }
        fn (val: Shape) [] { l.shape = val }
    action:
}
*/

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

    #[test]
    fn test_line() {
        use Colored;

        let _line = Line::new([0.0; 4], 3.0)
            .set(Color([1.0; 4]))
            .set(Radius(3.0))
            .set(Shape::Round)
            .hue_deg(1.0);
        let Color(_) = _line.get();
    }
}
<commit_msg>Added builder methods for `Line`<commit_after>//! Draw Line

use internal;
use triangulation;
use Graphics;
use Color;
use math::Matrix2d;
use DrawState;

/// The shape of the line
#[derive(Copy, Clone)]
pub enum Shape {
    /// Square edges
    Square,
    /// Round edges
    Round,
    /// Bevel edges
    Bevel,
}

/// A colored line with a default border radius
#[derive(Copy, Clone)]
pub struct Line {
    /// The line color
    pub color: internal::Color,
    /// The line radius
    pub radius: internal::Radius,
    /// The line shape
    pub shape: Shape,
}

impl Line {
    /// Creates a new line
    pub fn new(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Square,
        }
    }

    /// Creates a new line
    pub fn new_round(color: internal::Color, radius: internal::Radius) -> Line {
        Line {
            color: color,
            radius: radius,
            shape: Shape::Round,
        }
    }

    /// Sets color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = value;
        self
    }

    /// Sets radius.
    pub fn radius(mut self, value: internal::Radius) -> Self {
        self.radius = value;
        self
    }

    /// Sets width.
    pub fn width(mut self, value: internal::Width) -> Self {
        self.radius = 0.5 * value;
        self
    }

    /// Sets shape.
    pub fn shape(mut self, value: Shape) -> Self {
        self.shape = value;
        self
    }

    /// Draw the line.
    pub fn draw<G>(
        &self,
        line: internal::Line,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        match self.shape {
            Shape::Square => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    2,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
            Shape::Round => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    64,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
            Shape::Bevel => {
                g.tri_list(
                    draw_state,
                    &self.color,
                    |f|
                triangulation::with_round_border_line_tri_list(
                    3,
                    transform,
                    line,
                    self.radius,
                    |vertices| f(vertices)
                ));
            }
        }
    }

    /// Draws an arrow
    ///
    /// Head size is the sides of the triangle
    /// between the arrow hooks and the line
    pub fn draw_arrow<G>(
        &self,
        line: internal::Line,
        head_size: internal::Scalar,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        use Transformed;

        self.draw(line, draw_state, transform, g);
        let diff = [line[2] - line[0], line[3] - line[1]];
        let arrow_head = transform
            .trans(line[2], line[3])
            .orient(diff[0], diff[1]);
        self.draw([-head_size, head_size, 0.0, 0.0], draw_state, arrow_head, g);
        self.draw([-head_size, -head_size, 0.0, 0.0], draw_state, arrow_head, g);
    }
}

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

    #[test]
    fn test_line() {
        use Colored;

        let _line = Line::new([0.0; 4], 3.0)
            .color([1.0; 4])
            .radius(3.0)
            .shape(Shape::Round)
            .hue_deg(1.0);
        let Color(_) = _line.get();
    }
}
<|endoftext|>


<commit_before>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(plugin, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use std::sync::{Arc,RWLock};
use std::comm::{DuplexStream,Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").as_slice(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = std::comm::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>Use Show instead of error message<commit_after>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(plugin, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use std::sync::{Arc,RWLock};
use std::comm::{DuplexStream,Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").as_slice(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = std::comm::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>


<commit_before>extern crate lz4;

use std::env;
use std::fs::File;
use std::io;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use lz4::Encoder;

fn main() {
    let args: &Vec<String> = &mut env::args().collect();

    let mut width: u64 = 0;
    let mut height: u64 = 0;
    let mut frame: u64 = 0;
    let mut out_file: &str = "";

    let mut index: usize = 0;
    for argument in args {
        let arg: &str = &argument;
        let args_len: usize = *(&args.len());

        match arg {
            "-w" => {
                if index < (args_len - 1) {
                    width = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-h" => {
                if index < (args_len - 1) {
                    height = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-frame" => {
                if index < (args_len - 1) {
                    frame = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-o" => {
                if index < (args_len - 1) {
                    out_file = &args[index + 1];
                }
            }
            _ => {}
        }
        index += 1;
    }

    if width == 0 || height == 0 || frame == 0 || out_file == "" {
        println!("Usage of : splityv12pipe -w <width> -h <height> -frame <number> -o <filename>");
        return;
    }

    let max_bytes_len: u64 = frame * (((width * height) + ((width * height) / 2)));
    compress(out_file.to_string(), max_bytes_len).unwrap();
}

fn compress(dst: String, maxlen: u64) -> Result<()> {
    let count: i32 = 0;
    let file_name: String = format!("{}_{}", dst, count.to_string());
    let path: &Path = Path::new(&file_name);

    let mut fi = io::stdin();
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));

    copy(&mut fi,
         &mut fo,
         &dst,
         maxlen,
         count + 1,
         &move || {
             println!("{}", path.display());
             return Ok(());
         })
        .unwrap();
    fo.finish();

    Ok(())
}

fn copy(fi: &mut Read,
        fo: &mut Encoder<std::fs::File>,
        dst: &str,
        maxlen: u64,
        count: i32,
        done: &Fn() -> Result<()>)
        -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    let mut write_len: u64 = 0;

    loop {
        let len = try!(fi.read(&mut buffer));
        let len_u64 = len as u64;
        if len == 0 {
            done().unwrap();
            break;
        }

        if write_len + len_u64 >= maxlen {
            let mut l = 0;
            if (write_len + len_u64) - maxlen > 0 {
                l = (maxlen - write_len) as usize;
                try!(fo.write_all(&buffer[0..l]));
            }
            done().unwrap();

            let file_name: &str = &format!("{}_{}", dst, count.to_string());
            let path = Path::new(file_name);
            let mut new_fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));
            try!(new_fo.write_all(&buffer[l..len]));

            copy(fi,
                 &mut new_fo,
                 dst,
                 maxlen,
                 count + 1,
                 &move || {
                     println!("{}", path.display());
                     return Ok(());
                 })
                .unwrap();

            new_fo.finish();

            break;
        }
        try!(fo.write_all(&buffer[0..len]));
        write_len += len_u64;
    }
    Ok(())
}
<commit_msg>fix file write<commit_after>extern crate lz4;

use std::env;
use std::fs::File;
use std::io;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use lz4::Encoder;

fn main() {
    let args: &Vec<String> = &mut env::args().collect();

    let mut width: u64 = 0;
    let mut height: u64 = 0;
    let mut frame: u64 = 0;
    let mut out_file: &str = "";

    let mut index: usize = 0;
    for argument in args {
        let arg: &str = &argument;
        let args_len: usize = *(&args.len());

        match arg {
            "-w" => {
                if index < (args_len - 1) {
                    width = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-h" => {
                if index < (args_len - 1) {
                    height = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-frame" => {
                if index < (args_len - 1) {
                    frame = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-o" => {
                if index < (args_len - 1) {
                    out_file = &args[index + 1];
                }
            }
            _ => {}
        }
        index += 1;
    }

    if width == 0 || height == 0 || frame == 0 || out_file == "" {
        println!("Usage of : splityv12pipe -w <width> -h <height> -frame <number> -o <filename>");
        return;
    }

    let max_bytes_len: u64 = frame * (((width * height) + ((width * height) / 2)));
    compress(out_file.to_string(), max_bytes_len).unwrap();
}

fn compress(dst: String, maxlen: u64) -> Result<()> {
    let count: i32 = 0;
    let file_name: String = format!("{}_{}", dst, count.to_string());
    let path: &Path = Path::new(&file_name);

    let mut fi = io::stdin();
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));

    copy(&mut fi,
         &mut fo,
         &dst,
         maxlen,
         0,
         count + 1,
         &move || {
             println!("{}", path.display());
             return Ok(());
         })
        .unwrap();
    fo.finish();

    Ok(())
}

fn copy(fi: &mut Read,
        fo: &mut Encoder<std::fs::File>,
        dst: &str,
        maxlen: u64,
        already_wrote_len: u64,
        count: i32,
        done: &Fn() -> Result<()>)
        -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    let mut write_len: u64 = 0 + already_wrote_len;

    loop {
        let len = try!(fi.read(&mut buffer));
        let len_u64 = len as u64;
        if len == 0 {
            done().unwrap();
            break;
        }

        if write_len + len_u64 >= maxlen {
            let mut l = 0;
            let mut l_u64 = 0;
            if (write_len + len_u64) - maxlen > 0 {
                l_u64 = maxlen - write_len;
                l = l_u64 as usize;
                try!(fo.write_all(&buffer[0..l]));
            }
            done().unwrap();

            let file_name: &str = &format!("{}_{}", dst, count.to_string());
            let path = Path::new(file_name);
            let mut new_fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));
            try!(new_fo.write_all(&buffer[l..len]));

            copy(fi,
                 &mut new_fo,
                 dst,
                 maxlen,
                 len_u64 - l_u64,
                 count + 1,
                 &move || {
                     println!("{}", path.display());
                     return Ok(());
                 })
                .unwrap();

            new_fo.finish();

            break;
        }
        try!(fo.write_all(&buffer[0..len]));
        write_len += len_u64;
    }
    Ok(())
}
<|endoftext|>