<commit_before>#![allow(non_snake_case)]
#![feature(link_args)]
extern crate libc;

use std::default::Default;
use std::ptr;

#[repr(C)]
pub struct Local<T> {
    val_: *const T,
}

#[repr(C)] pub struct Context;
#[repr(C)] pub struct Isolate;
#[repr(C)] pub struct Script;
#[repr(C)] pub struct ScriptOrigin;
#[repr(C)] pub struct String;
#[repr(C)] pub struct TryCatch;
#[repr(C)] pub struct Value;
#[repr(C)] pub struct V8;

pub fn with_context_scope(context: Local<Context>, closure: ||) {
    (*context).Enter();
    closure();
    (*context).Exit();
}

pub fn with_isolate(closure: |&Isolate|) {
    let isolate = Isolate::New();
    closure(isolate);
    drop(isolate);
}

pub fn with_isolate_scope(isolate: &Isolate, closure: ||) {
    isolate.Enter();
    closure();
    isolate.Exit();
}

pub fn with_handle_scope(isolate: &Isolate, closure: ||) {
    unsafe extern fn trampoline(closure: *const ||) {
        (*closure)()
    }
    unsafe {
        HandleScope_With(isolate, trampoline, &closure)
    }
}

pub fn with_try_catch(closure: |&TryCatch|) {
    unsafe extern fn trampoline(try_catch: &TryCatch,
                                closure: *const |&TryCatch|) {
        (*closure)(try_catch)
    }
    unsafe {
        TryCatch_With(trampoline, &closure)
    }
}

impl<T> Local<T> {
    pub fn IsEmpty(&self) -> bool {
        self.val_ == ptr::null()
    }
}

impl<T> Default for Local<T> {
    fn default() -> Local<T> {
        Local { val_: ptr::null() }
    }
}

impl<T> Deref<T> for Local<T> {
    fn deref<'a>(&self) -> &T {
        unsafe { &*self.val_ }
    }
}

impl Context {
    pub fn Enter(&self) {
        unsafe { Context_Enter(self) }
    }

    pub fn Exit(&self) {
        unsafe { Context_Exit(self) }
    }

    pub fn New(isolate: &Isolate) -> Local<Context> {
        unsafe { Context_New(isolate) }
    }
}

// FIXME(bnoordhuis) Should probably implement Drop and, er, drop Dispose().
impl Isolate {
    pub fn Dispose(&mut self) {
        unsafe { Isolate_Dispose(self) }
    }

    pub fn Enter(&self) {
        unsafe { Isolate_Enter(self) }
    }

    pub fn Exit(&self) {
        unsafe { Isolate_Exit(self) }
    }

    pub fn New<'a>() -> &'a mut Isolate {
        unsafe { Isolate_New() }
    }
}

impl Drop for Isolate {
    fn drop(&mut self) {
        self.Dispose()
    }
}

impl String {
    pub fn NewFromUtf8(isolate: &Isolate, data: *const u8, typ: i32,
                       length: i32) -> Local<String> {
        unsafe { String_NewFromUtf8(isolate, data, typ, length) }
    }
}

fn to_local<T>(val: *const T) -> Local<T> {
    Local { val_: val }
}

impl Script {
    pub fn Compile(source: Local<String>,
                   _: Option<ScriptOrigin>) -> Local<Script> {
        unsafe { Script_Compile(source, ptr::null()) }
    }

    pub fn Run(&self) -> Local<Value> {
        unsafe { Script_Run(to_local(self)) }
    }
}

impl ScriptOrigin {
}

impl TryCatch {
    pub fn CanContinue(&self) -> bool {
        unsafe { TryCatch_CanContinue(self) }
    }

    pub fn Exception(&self) -> Local<Value> {
        unsafe { TryCatch_Exception(self) }
    }

    pub fn HasCaught(&self) -> bool {
        unsafe { TryCatch_HasCaught(self) }
    }

    pub fn HasTerminated(&self) -> bool {
        unsafe { TryCatch_HasTerminated(self) }
    }

    pub fn ReThrow(&self) -> Local<Value> {
        unsafe { TryCatch_ReThrow(self) }
    }

    pub fn Reset(&self) {
        unsafe { TryCatch_Reset(self) }
    }

    pub fn StackTrace(&self) -> Local<Value> {
        unsafe { TryCatch_StackTrace(self) }
    }
}

impl V8 {
    pub fn Dispose() -> bool {
        return unsafe { V8_Dispose() }
    }

    pub fn Initialize() -> bool {
        return unsafe { V8_Initialize() }
    }
}

impl Value {
    pub fn BooleanValue(&self) -> bool {
        unsafe { Value_BooleanValue(self) }
    }

    pub fn Int32Value(&self) -> i32 {
        unsafe { Value_Int32Value(self) }
    }

    pub fn IntegerValue(&self) -> i64 {
        unsafe { Value_IntegerValue(self) }
    }

    pub fn IsArgumentsObject(&self) -> bool {
        unsafe { Value_IsArgumentsObject(self) }
    }

    pub fn IsArray(&self) -> bool {
        unsafe { Value_IsArray(self) }
    }

    pub fn IsArrayBuffer(&self) -> bool {
        unsafe { Value_IsArrayBuffer(self) }
    }

    pub fn IsArrayBufferView(&self) -> bool {
        unsafe { Value_IsArrayBufferView(self) }
    }

    pub fn IsBoolean(&self) -> bool {
        unsafe { Value_IsBoolean(self) }
    }

    pub fn IsBooleanObject(&self) -> bool {
        unsafe { Value_IsBooleanObject(self) }
    }

    pub fn IsDataView(&self) -> bool {
        unsafe { Value_IsDataView(self) }
    }

    pub fn IsDate(&self) -> bool {
        unsafe { Value_IsDate(self) }
    }

    pub fn IsExternal(&self) -> bool {
        unsafe { Value_IsExternal(self) }
    }

    pub fn IsFalse(&self) -> bool {
        unsafe { Value_IsFalse(self) }
    }

    pub fn IsFloat32Array(&self) -> bool {
        unsafe { Value_IsFloat32Array(self) }
    }

    pub fn IsFloat64Array(&self) -> bool {
        unsafe { Value_IsFloat64Array(self) }
    }

    pub fn IsFunction(&self) -> bool {
        unsafe { Value_IsFunction(self) }
    }

    pub fn IsGeneratorFunction(&self) -> bool {
        unsafe { Value_IsGeneratorFunction(self) }
    }

    pub fn IsGeneratorObject(&self) -> bool {
        unsafe { Value_IsGeneratorObject(self) }
    }

    pub fn IsInt16Array(&self) -> bool {
        unsafe { Value_IsInt16Array(self) }
    }

    pub fn IsInt32(&self) -> bool {
        unsafe { Value_IsInt32(self) }
    }

    pub fn IsInt32Array(&self) -> bool {
        unsafe { Value_IsInt32Array(self) }
    }

    pub fn IsInt8Array(&self) -> bool {
        unsafe { Value_IsInt8Array(self) }
    }

    pub fn IsMap(&self) -> bool {
        unsafe { Value_IsMap(self) }
    }

    pub fn IsName(&self) -> bool {
        unsafe { Value_IsName(self) }
    }

    pub fn IsNativeError(&self) -> bool {
        unsafe { Value_IsNativeError(self) }
    }

    pub fn IsNull(&self) -> bool {
        unsafe { Value_IsNull(self) }
    }

    pub fn IsNumber(&self) -> bool {
        unsafe { Value_IsNumber(self) }
    }

    pub fn IsNumberObject(&self) -> bool {
        unsafe { Value_IsNumberObject(self) }
    }

    pub fn IsObject(&self) -> bool {
        unsafe { Value_IsObject(self) }
    }

    pub fn IsPromise(&self) -> bool {
        unsafe { Value_IsPromise(self) }
    }

    pub fn IsRegExp(&self) -> bool {
        unsafe { Value_IsRegExp(self) }
    }

    pub fn IsSet(&self) -> bool {
        unsafe { Value_IsSet(self) }
    }

    pub fn IsString(&self) -> bool {
        unsafe { Value_IsString(self) }
    }

    pub fn IsStringObject(&self) -> bool {
        unsafe { Value_IsStringObject(self) }
    }

    pub fn IsSymbol(&self) -> bool {
        unsafe { Value_IsSymbol(self) }
    }

    pub fn IsSymbolObject(&self) -> bool {
        unsafe { Value_IsSymbolObject(self) }
    }

    pub fn IsTrue(&self) -> bool {
        unsafe { Value_IsTrue(self) }
    }

    pub fn IsTypedArray(&self) -> bool {
        unsafe { Value_IsTypedArray(self) }
    }

    pub fn IsUint16Array(&self) -> bool {
        unsafe { Value_IsUint16Array(self) }
    }

    pub fn IsUint32(&self) -> bool {
        unsafe { Value_IsUint32(self) }
    }

    pub fn IsUint32Array(&self) -> bool {
        unsafe { Value_IsUint32Array(self) }
    }

    pub fn IsUint8Array(&self) -> bool {
        unsafe { Value_IsUint8Array(self) }
    }

    pub fn IsUint8ClampedArray(&self) -> bool {
        unsafe { Value_IsUint8ClampedArray(self) }
    }

    pub fn IsUndefined(&self) -> bool {
        unsafe { Value_IsUndefined(self) }
    }

    pub fn IsWeakMap(&self) -> bool {
        unsafe { Value_IsWeakMap(self) }
    }

    pub fn IsWeakSet(&self) -> bool {
        unsafe { Value_IsWeakSet(self) }
    }

    pub fn NumberValue(&self) -> f64 {
        unsafe { Value_NumberValue(self) }
    }
}

#[link(name="glue")]
#[link(name="v8")]
#[link(name="stdc++")]  // __gxx_personality_v0@@CXXABI_1.3
extern {
    fn HandleScope_With(isolate: &Isolate,
                        callback: unsafe extern fn(*const ||),
                        closure: *const ||);
    fn Context_Enter(context: &Context);
    fn Context_Exit(context: &Context);
    fn Context_New(isolate: &Isolate) -> Local<Context>;
    fn Isolate_Dispose(isolate: &mut Isolate);
    fn Isolate_Enter(isolate: &Isolate);
    fn Isolate_Exit(isolate: &Isolate);
    fn Isolate_New() -> &mut Isolate;
    fn Script_Compile(source: Local<String>,
                      origin: *const ScriptOrigin) -> Local<Script>;
    fn Script_Run(script: Local<Script>) -> Local<Value>;
    fn String_NewFromUtf8(isolate: &Isolate, data: *const u8, typ: i32,
                          length: i32) -> Local<String>;
    fn TryCatch_CanContinue(try_catch: &TryCatch) -> bool;
    fn TryCatch_Exception(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_HasCaught(try_catch: &TryCatch) -> bool;
    fn TryCatch_HasTerminated(try_catch: &TryCatch) -> bool;
    fn TryCatch_ReThrow(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_Reset(try_catch: &TryCatch);
    fn TryCatch_StackTrace(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_With(callback: unsafe extern fn(&TryCatch, *const |&TryCatch|),
                     closure: *const |&TryCatch|);
    fn V8_Dispose() -> bool;
    fn V8_Initialize() -> bool;
    fn Value_BooleanValue(that: &Value) -> bool;
    fn Value_Int32Value(that: &Value) -> i32;
    fn Value_IntegerValue(that: &Value) -> i64;
    fn Value_IsArgumentsObject(that: &Value) -> bool;
    fn Value_IsArray(that: &Value) -> bool;
    fn Value_IsArrayBuffer(that: &Value) -> bool;
    fn Value_IsArrayBufferView(that: &Value) -> bool;
    fn Value_IsBoolean(that: &Value) -> bool;
    fn Value_IsBooleanObject(that: &Value) -> bool;
    fn Value_IsDataView(that: &Value) -> bool;
    fn Value_IsDate(that: &Value) -> bool;
    fn Value_IsExternal(that: &Value) -> bool;
    fn Value_IsFalse(that: &Value) -> bool;
    fn Value_IsFloat32Array(that: &Value) -> bool;
    fn Value_IsFloat64Array(that: &Value) -> bool;
    fn Value_IsFunction(that: &Value) -> bool;
    fn Value_IsGeneratorFunction(that: &Value) -> bool;
    fn Value_IsGeneratorObject(that: &Value) -> bool;
    fn Value_IsInt16Array(that: &Value) -> bool;
    fn Value_IsInt32(that: &Value) -> bool;
    fn Value_IsInt32Array(that: &Value) -> bool;
    fn Value_IsInt8Array(that: &Value) -> bool;
    fn Value_IsMap(that: &Value) -> bool;
    fn Value_IsName(that: &Value) -> bool;
    fn Value_IsNativeError(that: &Value) -> bool;
    fn Value_IsNull(that: &Value) -> bool;
    fn Value_IsNumber(that: &Value) -> bool;
    fn Value_IsNumberObject(that: &Value) -> bool;
    fn Value_IsObject(that: &Value) -> bool;
    fn Value_IsPromise(that: &Value) -> bool;
    fn Value_IsRegExp(that: &Value) -> bool;
    fn Value_IsSet(that: &Value) -> bool;
    fn Value_IsString(that: &Value) -> bool;
    fn Value_IsStringObject(that: &Value) -> bool;
    fn Value_IsSymbol(that: &Value) -> bool;
    fn Value_IsSymbolObject(that: &Value) -> bool;
    fn Value_IsTrue(that: &Value) -> bool;
    fn Value_IsTypedArray(that: &Value) -> bool;
    fn Value_IsUint16Array(that: &Value) -> bool;
    fn Value_IsUint32(that: &Value) -> bool;
    fn Value_IsUint32Array(that: &Value) -> bool;
    fn Value_IsUint8Array(that: &Value) -> bool;
    fn Value_IsUint8ClampedArray(that: &Value) -> bool;
    fn Value_IsUndefined(that: &Value) -> bool;
    fn Value_IsWeakMap(that: &Value) -> bool;
    fn Value_IsWeakSet(that: &Value) -> bool;
    fn Value_NumberValue(that: &Value) -> f64;
}
<commit_msg>Remove unused #![feature(link_args)].<commit_after>#![allow(non_snake_case)]
extern crate libc;

use std::default::Default;
use std::ptr;

#[repr(C)]
pub struct Local<T> {
    val_: *const T,
}

#[repr(C)] pub struct Context;
#[repr(C)] pub struct Isolate;
#[repr(C)] pub struct Script;
#[repr(C)] pub struct ScriptOrigin;
#[repr(C)] pub struct String;
#[repr(C)] pub struct TryCatch;
#[repr(C)] pub struct Value;
#[repr(C)] pub struct V8;

pub fn with_context_scope(context: Local<Context>, closure: ||) {
    (*context).Enter();
    closure();
    (*context).Exit();
}

pub fn with_isolate(closure: |&Isolate|) {
    let isolate = Isolate::New();
    closure(isolate);
    drop(isolate);
}

pub fn with_isolate_scope(isolate: &Isolate, closure: ||) {
    isolate.Enter();
    closure();
    isolate.Exit();
}

pub fn with_handle_scope(isolate: &Isolate, closure: ||) {
    unsafe extern fn trampoline(closure: *const ||) {
        (*closure)()
    }
    unsafe {
        HandleScope_With(isolate, trampoline, &closure)
    }
}

pub fn with_try_catch(closure: |&TryCatch|) {
    unsafe extern fn trampoline(try_catch: &TryCatch,
                                closure: *const |&TryCatch|) {
        (*closure)(try_catch)
    }
    unsafe {
        TryCatch_With(trampoline, &closure)
    }
}

impl<T> Local<T> {
    pub fn IsEmpty(&self) -> bool {
        self.val_ == ptr::null()
    }
}

impl<T> Default for Local<T> {
    fn default() -> Local<T> {
        Local { val_: ptr::null() }
    }
}

impl<T> Deref<T> for Local<T> {
    fn deref<'a>(&self) -> &T {
        unsafe { &*self.val_ }
    }
}

impl Context {
    pub fn Enter(&self) {
        unsafe { Context_Enter(self) }
    }

    pub fn Exit(&self) {
        unsafe { Context_Exit(self) }
    }

    pub fn New(isolate: &Isolate) -> Local<Context> {
        unsafe { Context_New(isolate) }
    }
}

// FIXME(bnoordhuis) Should probably implement Drop and, er, drop Dispose().
impl Isolate {
    pub fn Dispose(&mut self) {
        unsafe { Isolate_Dispose(self) }
    }

    pub fn Enter(&self) {
        unsafe { Isolate_Enter(self) }
    }

    pub fn Exit(&self) {
        unsafe { Isolate_Exit(self) }
    }

    pub fn New<'a>() -> &'a mut Isolate {
        unsafe { Isolate_New() }
    }
}

impl Drop for Isolate {
    fn drop(&mut self) {
        self.Dispose()
    }
}

impl String {
    pub fn NewFromUtf8(isolate: &Isolate, data: *const u8, typ: i32,
                       length: i32) -> Local<String> {
        unsafe { String_NewFromUtf8(isolate, data, typ, length) }
    }
}

fn to_local<T>(val: *const T) -> Local<T> {
    Local { val_: val }
}

impl Script {
    pub fn Compile(source: Local<String>,
                   _: Option<ScriptOrigin>) -> Local<Script> {
        unsafe { Script_Compile(source, ptr::null()) }
    }

    pub fn Run(&self) -> Local<Value> {
        unsafe { Script_Run(to_local(self)) }
    }
}

impl ScriptOrigin {
}

impl TryCatch {
    pub fn CanContinue(&self) -> bool {
        unsafe { TryCatch_CanContinue(self) }
    }

    pub fn Exception(&self) -> Local<Value> {
        unsafe { TryCatch_Exception(self) }
    }

    pub fn HasCaught(&self) -> bool {
        unsafe { TryCatch_HasCaught(self) }
    }

    pub fn HasTerminated(&self) -> bool {
        unsafe { TryCatch_HasTerminated(self) }
    }

    pub fn ReThrow(&self) -> Local<Value> {
        unsafe { TryCatch_ReThrow(self) }
    }

    pub fn Reset(&self) {
        unsafe { TryCatch_Reset(self) }
    }

    pub fn StackTrace(&self) -> Local<Value> {
        unsafe { TryCatch_StackTrace(self) }
    }
}

impl V8 {
    pub fn Dispose() -> bool {
        return unsafe { V8_Dispose() }
    }

    pub fn Initialize() -> bool {
        return unsafe { V8_Initialize() }
    }
}

impl Value {
    pub fn BooleanValue(&self) -> bool {
        unsafe { Value_BooleanValue(self) }
    }

    pub fn Int32Value(&self) -> i32 {
        unsafe { Value_Int32Value(self) }
    }

    pub fn IntegerValue(&self) -> i64 {
        unsafe { Value_IntegerValue(self) }
    }

    pub fn IsArgumentsObject(&self) -> bool {
        unsafe { Value_IsArgumentsObject(self) }
    }

    pub fn IsArray(&self) -> bool {
        unsafe { Value_IsArray(self) }
    }

    pub fn IsArrayBuffer(&self) -> bool {
        unsafe { Value_IsArrayBuffer(self) }
    }

    pub fn IsArrayBufferView(&self) -> bool {
        unsafe { Value_IsArrayBufferView(self) }
    }

    pub fn IsBoolean(&self) -> bool {
        unsafe { Value_IsBoolean(self) }
    }

    pub fn IsBooleanObject(&self) -> bool {
        unsafe { Value_IsBooleanObject(self) }
    }

    pub fn IsDataView(&self) -> bool {
        unsafe { Value_IsDataView(self) }
    }

    pub fn IsDate(&self) -> bool {
        unsafe { Value_IsDate(self) }
    }

    pub fn IsExternal(&self) -> bool {
        unsafe { Value_IsExternal(self) }
    }

    pub fn IsFalse(&self) -> bool {
        unsafe { Value_IsFalse(self) }
    }

    pub fn IsFloat32Array(&self) -> bool {
        unsafe { Value_IsFloat32Array(self) }
    }

    pub fn IsFloat64Array(&self) -> bool {
        unsafe { Value_IsFloat64Array(self) }
    }

    pub fn IsFunction(&self) -> bool {
        unsafe { Value_IsFunction(self) }
    }

    pub fn IsGeneratorFunction(&self) -> bool {
        unsafe { Value_IsGeneratorFunction(self) }
    }

    pub fn IsGeneratorObject(&self) -> bool {
        unsafe { Value_IsGeneratorObject(self) }
    }

    pub fn IsInt16Array(&self) -> bool {
        unsafe { Value_IsInt16Array(self) }
    }

    pub fn IsInt32(&self) -> bool {
        unsafe { Value_IsInt32(self) }
    }

    pub fn IsInt32Array(&self) -> bool {
        unsafe { Value_IsInt32Array(self) }
    }

    pub fn IsInt8Array(&self) -> bool {
        unsafe { Value_IsInt8Array(self) }
    }

    pub fn IsMap(&self) -> bool {
        unsafe { Value_IsMap(self) }
    }

    pub fn IsName(&self) -> bool {
        unsafe { Value_IsName(self) }
    }

    pub fn IsNativeError(&self) -> bool {
        unsafe { Value_IsNativeError(self) }
    }

    pub fn IsNull(&self) -> bool {
        unsafe { Value_IsNull(self) }
    }

    pub fn IsNumber(&self) -> bool {
        unsafe { Value_IsNumber(self) }
    }

    pub fn IsNumberObject(&self) -> bool {
        unsafe { Value_IsNumberObject(self) }
    }

    pub fn IsObject(&self) -> bool {
        unsafe { Value_IsObject(self) }
    }

    pub fn IsPromise(&self) -> bool {
        unsafe { Value_IsPromise(self) }
    }

    pub fn IsRegExp(&self) -> bool {
        unsafe { Value_IsRegExp(self) }
    }

    pub fn IsSet(&self) -> bool {
        unsafe { Value_IsSet(self) }
    }

    pub fn IsString(&self) -> bool {
        unsafe { Value_IsString(self) }
    }

    pub fn IsStringObject(&self) -> bool {
        unsafe { Value_IsStringObject(self) }
    }

    pub fn IsSymbol(&self) -> bool {
        unsafe { Value_IsSymbol(self) }
    }

    pub fn IsSymbolObject(&self) -> bool {
        unsafe { Value_IsSymbolObject(self) }
    }

    pub fn IsTrue(&self) -> bool {
        unsafe { Value_IsTrue(self) }
    }

    pub fn IsTypedArray(&self) -> bool {
        unsafe { Value_IsTypedArray(self) }
    }

    pub fn IsUint16Array(&self) -> bool {
        unsafe { Value_IsUint16Array(self) }
    }

    pub fn IsUint32(&self) -> bool {
        unsafe { Value_IsUint32(self) }
    }

    pub fn IsUint32Array(&self) -> bool {
        unsafe { Value_IsUint32Array(self) }
    }

    pub fn IsUint8Array(&self) -> bool {
        unsafe { Value_IsUint8Array(self) }
    }

    pub fn IsUint8ClampedArray(&self) -> bool {
        unsafe { Value_IsUint8ClampedArray(self) }
    }

    pub fn IsUndefined(&self) -> bool {
        unsafe { Value_IsUndefined(self) }
    }

    pub fn IsWeakMap(&self) -> bool {
        unsafe { Value_IsWeakMap(self) }
    }

    pub fn IsWeakSet(&self) -> bool {
        unsafe { Value_IsWeakSet(self) }
    }

    pub fn NumberValue(&self) -> f64 {
        unsafe { Value_NumberValue(self) }
    }
}

#[link(name="glue")]
#[link(name="v8")]
#[link(name="stdc++")]  // __gxx_personality_v0@@CXXABI_1.3
extern {
    fn HandleScope_With(isolate: &Isolate,
                        callback: unsafe extern fn(*const ||),
                        closure: *const ||);
    fn Context_Enter(context: &Context);
    fn Context_Exit(context: &Context);
    fn Context_New(isolate: &Isolate) -> Local<Context>;
    fn Isolate_Dispose(isolate: &mut Isolate);
    fn Isolate_Enter(isolate: &Isolate);
    fn Isolate_Exit(isolate: &Isolate);
    fn Isolate_New() -> &mut Isolate;
    fn Script_Compile(source: Local<String>,
                      origin: *const ScriptOrigin) -> Local<Script>;
    fn Script_Run(script: Local<Script>) -> Local<Value>;
    fn String_NewFromUtf8(isolate: &Isolate, data: *const u8, typ: i32,
                          length: i32) -> Local<String>;
    fn TryCatch_CanContinue(try_catch: &TryCatch) -> bool;
    fn TryCatch_Exception(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_HasCaught(try_catch: &TryCatch) -> bool;
    fn TryCatch_HasTerminated(try_catch: &TryCatch) -> bool;
    fn TryCatch_ReThrow(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_Reset(try_catch: &TryCatch);
    fn TryCatch_StackTrace(try_catch: &TryCatch) -> Local<Value>;
    fn TryCatch_With(callback: unsafe extern fn(&TryCatch, *const |&TryCatch|),
                     closure: *const |&TryCatch|);
    fn V8_Dispose() -> bool;
    fn V8_Initialize() -> bool;
    fn Value_BooleanValue(that: &Value) -> bool;
    fn Value_Int32Value(that: &Value) -> i32;
    fn Value_IntegerValue(that: &Value) -> i64;
    fn Value_IsArgumentsObject(that: &Value) -> bool;
    fn Value_IsArray(that: &Value) -> bool;
    fn Value_IsArrayBuffer(that: &Value) -> bool;
    fn Value_IsArrayBufferView(that: &Value) -> bool;
    fn Value_IsBoolean(that: &Value) -> bool;
    fn Value_IsBooleanObject(that: &Value) -> bool;
    fn Value_IsDataView(that: &Value) -> bool;
    fn Value_IsDate(that: &Value) -> bool;
    fn Value_IsExternal(that: &Value) -> bool;
    fn Value_IsFalse(that: &Value) -> bool;
    fn Value_IsFloat32Array(that: &Value) -> bool;
    fn Value_IsFloat64Array(that: &Value) -> bool;
    fn Value_IsFunction(that: &Value) -> bool;
    fn Value_IsGeneratorFunction(that: &Value) -> bool;
    fn Value_IsGeneratorObject(that: &Value) -> bool;
    fn Value_IsInt16Array(that: &Value) -> bool;
    fn Value_IsInt32(that: &Value) -> bool;
    fn Value_IsInt32Array(that: &Value) -> bool;
    fn Value_IsInt8Array(that: &Value) -> bool;
    fn Value_IsMap(that: &Value) -> bool;
    fn Value_IsName(that: &Value) -> bool;
    fn Value_IsNativeError(that: &Value) -> bool;
    fn Value_IsNull(that: &Value) -> bool;
    fn Value_IsNumber(that: &Value) -> bool;
    fn Value_IsNumberObject(that: &Value) -> bool;
    fn Value_IsObject(that: &Value) -> bool;
    fn Value_IsPromise(that: &Value) -> bool;
    fn Value_IsRegExp(that: &Value) -> bool;
    fn Value_IsSet(that: &Value) -> bool;
    fn Value_IsString(that: &Value) -> bool;
    fn Value_IsStringObject(that: &Value) -> bool;
    fn Value_IsSymbol(that: &Value) -> bool;
    fn Value_IsSymbolObject(that: &Value) -> bool;
    fn Value_IsTrue(that: &Value) -> bool;
    fn Value_IsTypedArray(that: &Value) -> bool;
    fn Value_IsUint16Array(that: &Value) -> bool;
    fn Value_IsUint32(that: &Value) -> bool;
    fn Value_IsUint32Array(that: &Value) -> bool;
    fn Value_IsUint8Array(that: &Value) -> bool;
    fn Value_IsUint8ClampedArray(that: &Value) -> bool;
    fn Value_IsUndefined(that: &Value) -> bool;
    fn Value_IsWeakMap(that: &Value) -> bool;
    fn Value_IsWeakSet(that: &Value) -> bool;
    fn Value_NumberValue(that: &Value) -> f64;
}
<|endoftext|>


<commit_before>use ast;
use lexer;
use parser;

use interp::env;
use interp::types;

use core::hashmap::linear;
use core::to_bytes;

/*
 * aster - AST EvaulatoR
 *
 * aster evaluates a Prismo program via reduction of the AST.
 *
 * "It's pretty terrible."
 * -- Tony, 2013
 */

impl to_bytes::IterBytes for ast::RecordName {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        match self {
            &ast::RecordName(n, s) => (n, s).iter_bytes(lsb0, f)
        }
    }
}

impl to_bytes::IterBytes for ast::DottedName {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        match self {
            &ast::DottedName(s) => s.iter_bytes(lsb0, f)
        }
    }
}

pub struct Interp {
    record_types: @mut linear::LinearMap<@ast::RecordName, @ast::RecordDeclaration>,
    import_paths: @[Path],
    root: @mut env::Env<Interp>,
    argv: @[@str],
    filename: @str,
    current_frame: @mut option::Option<@mut Frame>
}

pub impl Interp {
    pub fn new(import_paths: @[Path], argv: @[@str], filename: @str) -> Interp {
        Interp {
            record_types: @mut linear::LinearMap::new(),
            import_paths: import_paths,
            root: @mut env::Env::new(),
            argv: argv,
            filename: filename,
            current_frame: @mut option::None
        }
    }
}

fn wind(interp: @mut Interp, env: @mut env::Env<Interp>, lineno: uint) -> @mut Frame {
    // allocate a new frame
    let frame = @mut Frame::new(interp, env, interp.filename, lineno);
    interp.current_frame = @mut option::Some(frame);
    frame
}

fn unwind(interp: @mut Interp) -> () {
    interp.current_frame = match *interp.current_frame {
        option::None => @mut option::None,
        option::Some(frame) => frame.parent
    };
}

pub struct Frame {
    parent: @mut option::Option<@mut Frame>,
    env: @mut env::Env<Interp>,
    file: @str,
    lineno: uint,
    exception: @mut option::Option<@mut types::Val<Interp>>
}

pub impl Frame {
    pub fn new(interp: @mut Interp, env: @mut env::Env<Interp>, file: @str, lineno: uint) -> Frame {
        Frame {
            parent: interp.current_frame,
            env: env,
            file: file,
            lineno: lineno,
            exception: @mut option::None
        }
    }
}

pub fn import_module(interp: @mut Interp, name: &ast::DottedName, qualified: bool) -> () {
    let module_parts = (**name).to_owned().map(|x| (*x).to_owned());
    let mut parts = copy module_parts;

    vec::reverse(parts);
    let module_name = copy parts[0];
    let filename = fmt!("%s.pr", module_name);
    parts = vec::tail(parts).to_owned();
    vec::reverse(parts);

    let mut found = false;
    let mut paths = interp.import_paths.to_owned();

    for paths.each_mut |import_path| {
        // make a path inside the import path and check if that exists
        let base_path = (copy *import_path).push_many(parts);
        let path = base_path.push(filename);

        if os::path_exists(&path) {
            // make a copy of the import paths then give them to a new sub-interpreter
            let mut import_paths1 = interp.import_paths.to_owned();
            import_paths1.unshift(base_path);

            let interp1 = @mut Interp::new(at_vec::from_owned(import_paths1), interp.argv, path.to_str().to_managed());

            // run the file in the sub-interpreter
            run_file(interp1, &path);

            if qualified {
                let module_name = ast::Sym(module_name.to_managed());

                // qualified imports symbols from child interpreter into a module
                env::declare(interp.root, &module_name,
                             @mut types::Module(interp1.root.vars));

                for interp1.record_types.each_key |k| {
                    interp.record_types.insert(match *k {
                        @ast::RecordName(modu, name) => @ast::RecordName(@ast::DottedName(**modu + [module_name]), name)
                    }, *interp1.record_types.find(k).unwrap());
                }
            } else {
                // otherwise we just plop all the symbols in
                for interp1.root.vars.each_key |k| {
                    env::declare(interp.root, k, *interp1.root.vars.find(k).unwrap());
                }

                // import record types
                for interp1.record_types.each_key |k| {
                    interp.record_types.insert(*k, *interp1.record_types.find(k).unwrap());
                }
            }

            found = true;
            break;
        }
    };

    if !found {
        fail!(fmt!("couldn't import module %s", str::connect(module_parts, ".")))
    };
}

fn unify_pattern_basic(interp: @mut Interp, env: @mut env::Env<Interp>, pat: &ast::Pat, val: @mut types::Val<Interp>) -> bool {
    // perform pattern matching of basic patterns -- if a match fails, we leave all the symbols in
    // scope and not care, because we unwind the stack during an exception and we won't be able to
    // get the environment back.
    match *pat {
        ast::AnyPattern => true,
        ast::ManyPattern => false,
        ast::UnitPattern => match *val {
            types::Unit => true,
            _ => false
        },
        ast::LiteralPattern(lit) => *val == types::gen_lit(lit),
        ast::SymbolPattern(sym) => {
            env::declare(env, &sym, val);
            true
        },
        ast::BoundPattern(sym, pat) => {
            let r = unify_pattern_basic(interp, env, pat, val);
            env::declare(env, &sym, val);
            r
        },
        ast::DisjunctivePattern(pat1, pat2) => {
            unify_pattern_basic(interp, env, pat1, val) || unify_pattern_basic(interp, env, pat2, val)
        },
        ast::ConjunctivePattern(pat1, pat2) => {
            unify_pattern_basic(interp, env, pat1, val) && unify_pattern_basic(interp, env, pat2, val)
        },
        ast::RecordPattern(pat_decl, pats) => fail!(~":V"),
        ast::ListPattern(pats) => {
            match *val {
                types::List(vals) => {
                    if vals.len() < pats.len() {
                        false
                    } else {
                        match pats[pats.len() - 1] {
                            ast::ManyPattern => {
                                // pattern match with a spread argument
                                let mut ok = true;
                                let mut i = 0;
                                while i < pats.len() - 1 {
                                    ok = unify_pattern_basic(interp, env, &pats[i], vals[i]);
                                    if !ok { break; };
                                    i += 1;
                                }
                                ok
                            },
                            _ => {
                                if vals.len() > pats.len() {
                                    // no spread argument, :(
                                    false
                                } else {
                                    // pattern match with a full pattern list
                                    let mut ok = true;
                                    let mut i = 0;
                                    while i < pats.len() {
                                        ok = unify_pattern_basic(interp, env, &pats[i], vals[i]);
                                        if !ok { break; };
                                        i += 1;
                                    }
                                    ok
                                }
                            }
                        }
                    }
                },
                _ => false
            }
        }
    }
}

fn unify_pattern_let(interp: @mut Interp, env: @mut env::Env<Interp>, pat: &ast::LetPat, val: @mut types::Val<Interp>) -> bool {
    match *pat {
        ast::BasicPattern(pat) => unify_pattern_basic(interp, env, &pat, val),
        _ => fail!(~":V")
    }
}

fn eval_exp(interp: @mut Interp, env: @mut env::Env<Interp>, exp: &ast::Exp) -> types::Val<Interp> {
    let frame = interp.current_frame.unwrap();

    let r = match exp.exp {
        ast::UnitExpression => types::Unit,
        ast::LiteralExpression(l) => types::gen_lit(l),
        ast::LambdaExpression(pat, exp) => types::Function(@[types::Fun {
            pattern: pat,
            body: exp,
            env: env
        }]),
        ast::ListExpression(exps) => types::List(at_vec::map(exps, |exp| @mut eval_exp(interp, env, exp))),
        ast::SymbolExpression(sym) => {
            match env::find(env, &sym) {
                option::Some(x) => types::Unit,
                option::None => {
                    frame.exception = @mut option::Some(@mut types::String(fmt!("symbol `%s` not found in scope", *sym).to_managed()));
                    types::Unit
                }
            }
        },
        _ => fail!(~":V")
    };

    r
}

fn exec_stmt(interp: @mut Interp, env: @mut env::Env<Interp>, stmt: &ast::Stmt) -> () {
    let frame = interp.current_frame.unwrap();

    match stmt.stmt {
        ast::LetBindingStatement(pat, exp) => {
            if !unify_pattern_let(interp, env, &pat, @mut eval_exp(interp, env, &exp)) {
                // uh oh, we need to throw an exception and unwind
                frame.exception = @mut option::Some(@mut types::String(@"pattern match failed"));
            }
        },
        ast::ExpressionStatement(exp) => { eval_exp(interp, env, &exp); }
    };
}

pub fn run_file(interp: @mut Interp, path: &Path) -> () {
    match io::file_reader(path) {
        result::Ok(r) => {
            let tokens = lexer::lex(r);
            let program = parser::parse(tokens);
            run(interp, program);
        },
        result::Err(f) => fail!(f)
    }
}

pub fn run(interp: @mut Interp, prog: ast::Program) -> () {
    for prog.imports.each |imp| {
        import_module(interp, &imp.module, imp.qualified);
    }

    for prog.records.each |rec| {
        interp.record_types.insert(@rec.name, @*rec);
    }

    for prog.body.each |stmt| {
        let mut frame = wind(interp, interp.root, stmt.lineno);

        exec_stmt(interp, interp.root, stmt);

        match *frame.exception {
            option::None => unwind(interp),
            option::Some(f) => {
                fail!(fmt!("%? in %s:%u", f, frame.file, frame.lineno))
            }
        }
    }
}
<commit_msg>unwind frame on exception in list expression<commit_after>use ast;
use lexer;
use parser;

use interp::env;
use interp::types;

use core::hashmap::linear;
use core::to_bytes;

/*
 * aster - AST EvaulatoR
 *
 * aster evaluates a Prismo program via reduction of the AST.
 *
 * "It's pretty terrible."
 * -- Tony, 2013
 */

impl to_bytes::IterBytes for ast::RecordName {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        match self {
            &ast::RecordName(n, s) => (n, s).iter_bytes(lsb0, f)
        }
    }
}

impl to_bytes::IterBytes for ast::DottedName {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        match self {
            &ast::DottedName(s) => s.iter_bytes(lsb0, f)
        }
    }
}

pub struct Interp {
    record_types: @mut linear::LinearMap<@ast::RecordName, @ast::RecordDeclaration>,
    import_paths: @[Path],
    root: @mut env::Env<Interp>,
    argv: @[@str],
    filename: @str,
    current_frame: @mut option::Option<@mut Frame>
}

pub impl Interp {
    pub fn new(import_paths: @[Path], argv: @[@str], filename: @str) -> Interp {
        Interp {
            record_types: @mut linear::LinearMap::new(),
            import_paths: import_paths,
            root: @mut env::Env::new(),
            argv: argv,
            filename: filename,
            current_frame: @mut option::None
        }
    }
}

fn wind(interp: @mut Interp, env: @mut env::Env<Interp>, lineno: uint) -> @mut Frame {
    // allocate a new frame
    let frame = @mut Frame::new(interp, env, interp.filename, lineno);
    interp.current_frame = @mut option::Some(frame);
    frame
}

fn unwind(interp: @mut Interp) -> () {
    interp.current_frame = match *interp.current_frame {
        option::None => @mut option::None,
        option::Some(frame) => frame.parent
    };
}

pub struct Frame {
    parent: @mut option::Option<@mut Frame>,
    env: @mut env::Env<Interp>,
    file: @str,
    lineno: uint,
    exception: @mut option::Option<@mut types::Val<Interp>>
}

pub impl Frame {
    pub fn new(interp: @mut Interp, env: @mut env::Env<Interp>, file: @str, lineno: uint) -> Frame {
        Frame {
            parent: interp.current_frame,
            env: env,
            file: file,
            lineno: lineno,
            exception: @mut option::None
        }
    }
}

pub fn import_module(interp: @mut Interp, name: &ast::DottedName, qualified: bool) -> () {
    let module_parts = (**name).to_owned().map(|x| (*x).to_owned());
    let mut parts = copy module_parts;

    vec::reverse(parts);
    let module_name = copy parts[0];
    let filename = fmt!("%s.pr", module_name);
    parts = vec::tail(parts).to_owned();
    vec::reverse(parts);

    let mut found = false;
    let mut paths = interp.import_paths.to_owned();

    for paths.each_mut |import_path| {
        // make a path inside the import path and check if that exists
        let base_path = (copy *import_path).push_many(parts);
        let path = base_path.push(filename);

        if os::path_exists(&path) {
            // make a copy of the import paths then give them to a new sub-interpreter
            let mut import_paths1 = interp.import_paths.to_owned();
            import_paths1.unshift(base_path);

            let interp1 = @mut Interp::new(at_vec::from_owned(import_paths1), interp.argv, path.to_str().to_managed());

            // run the file in the sub-interpreter
            run_file(interp1, &path);

            if qualified {
                let module_name = ast::Sym(module_name.to_managed());

                // qualified imports symbols from child interpreter into a module
                env::declare(interp.root, &module_name,
                             @mut types::Module(interp1.root.vars));

                for interp1.record_types.each_key |k| {
                    interp.record_types.insert(match *k {
                        @ast::RecordName(modu, name) => @ast::RecordName(@ast::DottedName(**modu + [module_name]), name)
                    }, *interp1.record_types.find(k).unwrap());
                }
            } else {
                // otherwise we just plop all the symbols in
                for interp1.root.vars.each_key |k| {
                    env::declare(interp.root, k, *interp1.root.vars.find(k).unwrap());
                }

                // import record types
                for interp1.record_types.each_key |k| {
                    interp.record_types.insert(*k, *interp1.record_types.find(k).unwrap());
                }
            }

            found = true;
            break;
        }
    };

    if !found {
        fail!(fmt!("couldn't import module %s", str::connect(module_parts, ".")))
    };
}

fn unify_pattern_basic(interp: @mut Interp, env: @mut env::Env<Interp>, pat: &ast::Pat, val: @mut types::Val<Interp>) -> bool {
    // perform pattern matching of basic patterns -- if a match fails, we leave all the symbols in
    // scope and not care, because we unwind the stack during an exception and we won't be able to
    // get the environment back.
    match *pat {
        ast::AnyPattern => true,
        ast::ManyPattern => false,
        ast::UnitPattern => match *val {
            types::Unit => true,
            _ => false
        },
        ast::LiteralPattern(lit) => *val == types:: gen_lit(lit),
        ast::SymbolPattern(sym) => {
            env::declare(env, &sym, val);
            true
        },
        ast::BoundPattern(sym, pat) => {
            let r = unify_pattern_basic(interp, env, pat, val);
            env::declare(env, &sym, val);
            r
        },
        ast::DisjunctivePattern(pat1, pat2) => {
            unify_pattern_basic(interp, env, pat1, val) || unify_pattern_basic(interp, env, pat2, val)
        },
        ast::ConjunctivePattern(pat1, pat2) => {
            unify_pattern_basic(interp, env, pat1, val) && unify_pattern_basic(interp, env, pat2, val)
        },
        ast::RecordPattern(pat_decl, pats) => fail!(~":V"),
        ast::ListPattern(pats) => {
            match *val {
                types::List(vals) => {
                    if vals.len() < pats.len() {
                        false
                    } else {
                        match pats[pats.len() - 1] {
                            ast::ManyPattern => {
                                // pattern match with a spread argument
                                let mut ok = true;
                                let mut i = 0;
                                while i < pats.len() - 1 {
                                    ok = unify_pattern_basic(interp, env, &pats[i], vals[i]);
                                    if !ok { break; };
                                    i += 1;
                                }
                                ok
                            },
                            _ => {
                                if vals.len() > pats.len() {
                                    // no spread argument, :(
                                    false
                                } else {
                                    // pattern match with a full pattern list
                                    let mut ok = true;
                                    let mut i = 0;
                                    while i < pats.len() {
                                        ok = unify_pattern_basic(interp, env, &pats[i], vals[i]);
                                        if !ok { break; };
                                        i += 1;
                                    }
                                    ok
                                }
                            }
                        }
                    }
                },
                _ => false
            }
        }
    }
}

fn unify_pattern_let(interp: @mut Interp, env: @mut env::Env<Interp>, pat: &ast::LetPat, val: @mut types::Val<Interp>) -> bool {
    match *pat {
        ast::BasicPattern(pat) => unify_pattern_basic(interp, env, &pat, val),
        _ => fail!(~":V")
    }
}

fn eval_exp(interp: @mut Interp, env: @mut env::Env<Interp>, exp: &ast::Exp) -> types::Val<Interp> {
    let frame = interp.current_frame.unwrap();

    let r = match exp.exp {
        ast::UnitExpression => types::Unit,
        ast::LiteralExpression(l) => types::gen_lit(l),
        ast::LambdaExpression(pat, exp) => types::Function(@[types::Fun {
            pattern: pat,
            body: exp,
            env: env
        }]),
        ast::ListExpression(exps) => {
            let mut vals = @[];

            for exps.each |exp| {
                vals += [@mut eval_exp(interp, env, exp)];
                if !frame.exception.is_none() {
                    return types::Unit;
                }
            }

            types::List(vals)
        },
        ast::SymbolExpression(sym) => {
            match env::find(env, &sym) {
                option::Some(x) => types::Unit,
                option::None => {
                    frame.exception = @mut option::Some(@mut types::String(fmt!("symbol `%s` not found in scope", *sym).to_managed()));
                    types::Unit
                }
            }
        },
        _ => fail!(~":V")
    };

    r
}

fn exec_stmt(interp: @mut Interp, env: @mut env::Env<Interp>, stmt: &ast::Stmt) -> () {
    let frame = interp.current_frame.unwrap();

    match stmt.stmt {
        ast::LetBindingStatement(pat, exp) => {
            if !unify_pattern_let(interp, env, &pat, @mut eval_exp(interp, env, &exp)) {
                // uh oh, we need to throw an exception and unwind
                frame.exception = @mut option::Some(@mut types::String(@"pattern match failed"));
            }
        },
        ast::ExpressionStatement(exp) => { eval_exp(interp, env, &exp); }
    };
}

pub fn run_file(interp: @mut Interp, path: &Path) -> () {
    match io::file_reader(path) {
        result::Ok(r) => {
            let tokens = lexer::lex(r);
            let program = parser::parse(tokens);
            run(interp, program);
        },
        result::Err(f) => fail!(f)
    }
}

pub fn run(interp: @mut Interp, prog: ast::Program) -> () {
    for prog.imports.each |imp| {
        import_module(interp, &imp.module, imp.qualified);
    }

    for prog.records.each |rec| {
        interp.record_types.insert(@rec.name, @*rec);
    }

    for prog.body.each |stmt| {
        let mut frame = wind(interp, interp.root, stmt.lineno);

        exec_stmt(interp, interp.root, stmt);

        match *frame.exception {
            option::None => unwind(interp),
            option::Some(f) => {
                fail!(fmt!("%? in %s:%u", f, frame.file, frame.lineno))
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use std::collections::HashMap;

/* Fields with a custom rename are for deserializing
 * the secifications json file in amq-protocol-codegen
 */
#[derive(Debug, Deserialize, Serialize)]
pub enum AMQPType {
    #[serde(rename="bit")]
    Boolean,
    #[serde(rename="octet")]
    ShortShortInt,
    ShortShortUInt,
    #[serde(rename="short")]
    ShortInt,
    ShortUInt,
    #[serde(rename="long")]
    LongInt,
    LongUInt,
    #[serde(rename="longlong")]
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    #[serde(rename="shortstr")]
    ShortString,
    #[serde(rename="longstr")]
    LongString,
    FieldArray,
    #[serde(rename="timestamp")]
    TimeStamp,
    #[serde(rename="table")]
    FieldTable,
    Void,
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type DecimalValue   = i64;    /* FIXME: find out what this is exactly */
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<commit_msg>types: add conversion from/to type id<commit_after>extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use std::collections::HashMap;

/* Fields with a custom rename are for deserializing
 * the secifications json file in amq-protocol-codegen
 */
#[derive(Debug, Deserialize, Serialize)]
pub enum AMQPType {
    #[serde(rename="bit")]
    Boolean,
    #[serde(rename="octet")]
    ShortShortInt,
    ShortShortUInt,
    #[serde(rename="short")]
    ShortInt,
    ShortUInt,
    #[serde(rename="long")]
    LongInt,
    LongUInt,
    #[serde(rename="longlong")]
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    #[serde(rename="shortstr")]
    ShortString,
    #[serde(rename="longstr")]
    LongString,
    FieldArray,
    #[serde(rename="timestamp")]
    TimeStamp,
    #[serde(rename="table")]
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> AMQPType {
        match id {
            't' => AMQPType::Boolean,
            'b' => AMQPType::ShortShortInt,
            'B' => AMQPType::ShortShortUInt,
            'U' => AMQPType::ShortInt,
            'u' => AMQPType::ShortUInt,
            'I' => AMQPType::LongInt,
            'i' => AMQPType::LongUInt,
            'L' => AMQPType::LongLongInt,
            'l' => AMQPType::LongLongUInt,
            'f' => AMQPType::Float,
            'd' => AMQPType::Double,
            'D' => AMQPType::DecimalValue,
            's' => AMQPType::ShortString,
            'S' => AMQPType::LongString,
            'A' => AMQPType::FieldArray,
            'T' => AMQPType::TimeStamp,
            'F' => AMQPType::FieldTable,
            'V' => AMQPType::Void,
            _ => panic!("Unknown type id {}", id), /*FIXME: don't panic*/
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type DecimalValue   = i64;    /* FIXME: find out what this is exactly */
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<|endoftext|>


<commit_before>// Copyright 2021 Chad Williamson
//
// Use of this source code is governed by an MIT-syle license that can be
// found in the LICENSE file or at https://opensource.org/licenses/MIT.

// This file contains integration tests for the find command.
//
// Note: the `serial` macro is used on tests that make assumptions about the
// working directory, since we have at least one test that needs to change it.

use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
use std::env;
use std::fs::File;
use tempdir::TempDir;

#[serial(working_dir)]
#[test]
fn no_args() {
    Command::cargo_bin("find")
        .expect("found binary")
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_both_match() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "d", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_one_matches() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "f", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());
}

#[test]
fn matcher_with_side_effects_at_end() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-name", "test", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(temp_dir.path().exists(), "temp dir should NOT be deleted");
}

#[test]
fn matcher_with_side_effects_in_front() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-delete", "-name", "test"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(!temp_dir.path().exists(), "temp dir should also be deleted");
}

// This could be covered by a unit test in principle... in practice, changing
// the working dir can't be done safely in unit tests unless `--test-threads=1`
// or `serial` goes everywhere, and it doesn't seem possible to get an
// appropriate `walkdir::DirEntry` for "." without actually changing dirs
// (or risking deletion of the repo itself).
#[serial(working_dir)]
#[test]
fn delete_on_dot_dir() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let original_dir = env::current_dir().unwrap();
    env::set_current_dir(&temp_dir.path()).expect("working dir changed");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[".", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    env::set_current_dir(original_dir).expect("restored original working dir");

    assert!(temp_dir.path().exists(), "temp dir should still exist");
}
<commit_msg>Fix copyright header in find_cmd_tests.rs<commit_after>// Copyright 2021 Chad Williamson <chad@dahc.us>
//
// Use of this source code is governed by an MIT-syle license that can be
// found in the LICENSE file or at https://opensource.org/licenses/MIT.

// This file contains integration tests for the find command.
//
// Note: the `serial` macro is used on tests that make assumptions about the
// working directory, since we have at least one test that needs to change it.

use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
use std::env;
use std::fs::File;
use tempdir::TempDir;

#[serial(working_dir)]
#[test]
fn no_args() {
    Command::cargo_bin("find")
        .expect("found binary")
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_both_match() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "d", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_one_matches() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "f", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());
}

#[test]
fn matcher_with_side_effects_at_end() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-name", "test", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(temp_dir.path().exists(), "temp dir should NOT be deleted");
}

#[test]
fn matcher_with_side_effects_in_front() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-delete", "-name", "test"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(!temp_dir.path().exists(), "temp dir should also be deleted");
}

// This could be covered by a unit test in principle... in practice, changing
// the working dir can't be done safely in unit tests unless `--test-threads=1`
// or `serial` goes everywhere, and it doesn't seem possible to get an
// appropriate `walkdir::DirEntry` for "." without actually changing dirs
// (or risking deletion of the repo itself).
#[serial(working_dir)]
#[test]
fn delete_on_dot_dir() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let original_dir = env::current_dir().unwrap();
    env::set_current_dir(&temp_dir.path()).expect("working dir changed");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[".", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    env::set_current_dir(original_dir).expect("restored original working dir");

    assert!(temp_dir.path().exists(), "temp dir should still exist");
}
<|endoftext|>


<commit_before>#![allow(clippy::manual_assert)]

mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "ee160f2f5e73b6f5954bc33f059c316d9e8582c4";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // TODO: impl ~const T {}
    // https://github.com/dtolnay/syn/issues/1051
    "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/early/closing-args-token.rs",
    "src/test/ui/const-generics/early/const-expression-parameter.rs",

    // Need at least one trait in impl Trait, no such type as impl 'static
    "src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",
    "src/tools/rustfmt/tests/source/trait.rs",
    "src/tools/rustfmt/tests/target/trait.rs",

    // Placeholder syntax for "throw expressions"
    "src/test/pretty/yeet-expr.rs",
    "src/test/ui/try-trait/yeet-for-option.rs",
    "src/test/ui/try-trait/yeet-for-result.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Testing rustfmt on invalid syntax
    "src/tools/rustfmt/tests/coverage/target/comments.rs",
    "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
    "src/tools/rustfmt/tests/parser/issue_4418.rs",
    "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
    "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/source/type.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/target/type.rs",

    // Testing compiler diagnostic localization on invalid syntax
    "src/test/run-make/translation/basic-translation.rs",

    // Clippy lint lists represented as expressions
    "src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_all.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_style.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/macros/include-single-expr-helper.rs",
    "src/test/ui/macros/include-single-expr-helper-1.rs",
    "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map_or(true, |e| e != "rs") {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Factor out a static array of directories to skip testing<commit_after>#![allow(clippy::manual_assert)]

mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "ee160f2f5e73b6f5954bc33f059c316d9e8582c4";

#[rustfmt::skip]
static EXCLUDE_FILES: &[&str] = &[
    // TODO: impl ~const T {}
    // https://github.com/dtolnay/syn/issues/1051
    "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/early/closing-args-token.rs",
    "src/test/ui/const-generics/early/const-expression-parameter.rs",

    // Need at least one trait in impl Trait, no such type as impl 'static
    "src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",
    "src/tools/rustfmt/tests/source/trait.rs",
    "src/tools/rustfmt/tests/target/trait.rs",

    // Placeholder syntax for "throw expressions"
    "src/test/pretty/yeet-expr.rs",
    "src/test/ui/try-trait/yeet-for-option.rs",
    "src/test/ui/try-trait/yeet-for-result.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Testing rustfmt on invalid syntax
    "src/tools/rustfmt/tests/coverage/target/comments.rs",
    "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
    "src/tools/rustfmt/tests/parser/issue_4418.rs",
    "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
    "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/source/type.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/target/type.rs",

    // Testing compiler diagnostic localization on invalid syntax
    "src/test/run-make/translation/basic-translation.rs",

    // Clippy lint lists represented as expressions
    "src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_all.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_style.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/macros/include-single-expr-helper.rs",
    "src/test/ui/macros/include-single-expr-helper-1.rs",
    "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];

#[rustfmt::skip]
static EXCLUDE_DIRS: &[&str] = &[];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path_string = if path_string == "tests/rust" {
        return true;
    } else if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.is_dir() {
        return !EXCLUDE_DIRS.contains(&path_string);
    }

    if path.extension().map_or(true, |e| e != "rs") {
        return false;
    }

    if path_string.starts_with("src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE_FILES.contains(&path_string)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE_FILES {
        if !test_src.join(exclude).is_file() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    for exclude in EXCLUDE_DIRS {
        if !test_src.join(exclude).is_dir() {
            missing += "\ntests/rust/";
            missing += exclude;
            missing += "/";
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate serde_json;
extern crate mimir;

use mimir::Members;

/// Simple call to a BANO load into ES base
/// Checks that we are able to find one object (a specific address)
pub fn osm2mimir_sample_test(es_wrapper: ::ElasticSearchWrapper) {
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    ::launch_and_assert(osm2mimir,
                        vec!["--input=./tests/fixtures/three_cities.osm.pbf".into(),
                             "--import-way".into(),
                             "--import-admin".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    // Test: Import of Admin
    let res: Vec<_> = es_wrapper.search_and_filter("label:Livry-sur-Seine", |_| true).collect();
    assert_eq!(res.len(), 1);
    assert!(res[0].is_admin());

    // Test: search for "Rue des Près"
    let res: Vec<_> = es_wrapper.search_and_filter("label:Rue des Près", |_| true).collect();
    assert!(res.len() != 0);
    assert!(res[0].is_street());
    // The first hit should be "Rue des Près"
    assert!(res[0].label() == "Rue des Près");

    // And there should be only ONE "Rue des Près"
    let place_filter = |place: &mimir::Place| place.is_street() && place.label() == "Rue des Près";
    let nb = es_wrapper.search_and_filter("label:Rue des Près", place_filter).count();
    assert_eq!(nb, 1);

    // Test: Search for "Rue du Four à Chaux" in "Livry-sur-Seine"
    let place_filter = |place: &mimir::Place| {
        place.is_street() && place.label() == "Rue du Four à Chaux" &&
        place.admins().first().and_then(|admin| Some(admin.label() == "Livry-sur-Seine")).unwrap_or(false)
    };
    let nb = es_wrapper.search_and_filter("label:Rue du Four à Chaux", place_filter).count();
    assert_eq!(nb, 6);

    // Test: Streets having the same label in different cities
    let place_filter = |place: &mimir::Place| {
        place.is_street() && place.label() == "Rue du Port"
        && place.admins().first().and_then(|admin| Some(admin.label() == "Melun")).unwrap_or(false)
    };
    let nb = es_wrapper.search_and_filter("label:Rue du Port", place_filter).count();
    assert_eq!(nb, 1);
}
<commit_msg>improvements<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate serde_json;
extern crate mimir;

use mimir::Members;

/// Simple call to a BANO load into ES base
/// Checks that we are able to find one object (a specific address)
pub fn osm2mimir_sample_test(es_wrapper: ::ElasticSearchWrapper) {
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    ::launch_and_assert(osm2mimir,
                        vec!["--input=./tests/fixtures/three_cities.osm.pbf".into(),
                             "--import-way".into(),
                             "--import-admin".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    // Test: Import of Admin
    let res: Vec<_> = es_wrapper.search_and_filter("label:Livry-sur-Seine", |_| true).collect();
    assert_eq!(res.len(), 1);
    assert!(res[0].is_admin());

    // Test: search for "Rue des Près"
    let res: Vec<_> = es_wrapper.search_and_filter("label:Rue des Près", |_| true).collect();
    assert!(res.len() != 0);
    assert!(res[0].is_street());
    // The first hit should be "Rue des Près"
    assert!(res[0].label() == "Rue des Près");

    // And there should be only ONE "Rue des Près"
    assert_eq!(res.iter().filter(|place| place.is_street() && place.label() == "Rue des Près").count(), 1);

    // Test: Search for "Rue du Four à Chaux" in "Livry-sur-Seine"
    let place_filter = |place: &mimir::Place| {
        place.is_street() && place.label() == "Rue du Four à Chaux" &&
        place.admins().first().map(|admin| admin.label() == "Livry-sur-Seine").unwrap_or(false)
    };
    let nb = es_wrapper.search_and_filter("label:Rue du Four à Chaux", place_filter).count();
    assert_eq!(nb, 6);

    // Test: Streets having the same label in different cities
    let place_filter = |place: &mimir::Place| {
        place.is_street() && place.label() == "Rue du Port"
        && place.admins().first().map(|admin| admin.label() == "Melun").unwrap_or(false)
    };
    let nb = es_wrapper.search_and_filter("label:Rue du Port", place_filter).count();
    assert_eq!(nb, 1);
}
<|endoftext|>


<commit_before>// Allow unstable items until Rust hits 1.0

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::io::Cursor;

macro_rules! test_utf8{
    ($filename: expr, $expected: expr) => (
        test_file!(yaml::ffi::YamlEncoding::YamlUtf8Encoding, $filename, $expected)
    )
}

macro_rules! test_file{
    ($encoding: expr, $filename: expr, $expected: expr) => (
        {
            let data = include_bytes!($filename);
            let mut reader = Cursor::new(data);
            match yaml::parse_io(&mut reader, $encoding) {
                Ok(docs) => if docs.len() == 1 {
                    assert_eq!(docs[..].first().unwrap(), &$expected)
                } else {
                    panic!("too many number of documents: {:?}", docs)
                },
                Err(e) => panic!("parse failure: {:?}", e)
            }
        }
    )
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    test_utf8!("source/ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    test_utf8!("source/player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    test_utf8!("source/ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    test_utf8!("source/multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    test_utf8!("source/csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    test_utf8!("source/map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    test_utf8!("source/alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    test_utf8!("source/complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    test_utf8!("source/block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    test_utf8!("source/plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    test_utf8!("source/quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    test_utf8!("source/multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    test_file!(YamlEncoding::YamlUtf16LeEncoding, "source/utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    test_file!(YamlEncoding::YamlUtf16BeEncoding, "source/utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<commit_msg>Make type casting explicit for test<commit_after>// Allow unstable items until Rust hits 1.0

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::io::Cursor;

macro_rules! test_utf8{
    ($filename: expr, $expected: expr) => (
        test_file!(yaml::ffi::YamlEncoding::YamlUtf8Encoding, $filename, $expected)
    )
}

macro_rules! test_file{
    ($encoding: expr, $filename: expr, $expected: expr) => (
        {
            let data: &[u8] = include_bytes!($filename);
            let mut reader = Cursor::new(data);
            match yaml::parse_io(&mut reader, $encoding) {
                Ok(docs) => if docs.len() == 1 {
                    assert_eq!(docs[..].first().unwrap(), &$expected)
                } else {
                    panic!("too many number of documents: {:?}", docs)
                },
                Err(e) => panic!("parse failure: {:?}", e)
            }
        }
    )
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    test_utf8!("source/ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    test_utf8!("source/player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    test_utf8!("source/ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    test_utf8!("source/multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    test_utf8!("source/csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    test_utf8!("source/map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    test_utf8!("source/alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    test_utf8!("source/complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    test_utf8!("source/block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    test_utf8!("source/plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    test_utf8!("source/quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    test_utf8!("source/multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    test_file!(YamlEncoding::YamlUtf16LeEncoding, "source/utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    test_file!(YamlEncoding::YamlUtf16BeEncoding, "source/utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]
#![crate_name = "servo_url"]
#![crate_type = "rlib"]

#[macro_use]
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
#[macro_use]
extern crate serde;

pub mod origin;

pub use crate::origin::{ImmutableOrigin, MutableOrigin, OpaqueOrigin};

use std::fmt;
use std::net::IpAddr;
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
use std::path::Path;
use std::sync::Arc;
use url::{Position, Url};

pub use url::Host;

#[derive(Clone, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct ServoUrl(#[ignore_malloc_size_of = "Arc"] Arc<Url>);

impl ServoUrl {
    pub fn from_url(url: Url) -> Self {
        ServoUrl(Arc::new(url))
    }

    pub fn parse_with_base(base: Option<&Self>, input: &str) -> Result<Self, url::ParseError> {
        Url::options()
            .base_url(base.map(|b| &*b.0))
            .parse(input)
            .map(Self::from_url)
    }

    pub fn into_string(self) -> String {
        Arc::try_unwrap(self.0)
            .unwrap_or_else(|s| (*s).clone())
            .into_string()
    }

    pub fn into_url(self) -> Url {
        Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())
    }

    pub fn as_url(&self) -> &Url {
        &self.0
    }

    pub fn parse(input: &str) -> Result<Self, url::ParseError> {
        Url::parse(input).map(Self::from_url)
    }

    pub fn cannot_be_a_base(&self) -> bool {
        self.0.cannot_be_a_base()
    }

    pub fn domain(&self) -> Option<&str> {
        self.0.domain()
    }

    pub fn fragment(&self) -> Option<&str> {
        self.0.fragment()
    }

    pub fn path(&self) -> &str {
        self.0.path()
    }

    pub fn origin(&self) -> ImmutableOrigin {
        ImmutableOrigin::new(self.0.origin())
    }

    pub fn scheme(&self) -> &str {
        self.0.scheme()
    }

    pub fn is_secure_scheme(&self) -> bool {
        let scheme = self.scheme();
        scheme == "https" || scheme == "wss"
    }

    pub fn is_chrome(&self) -> bool {
        self.scheme() == "chrome"
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn as_mut_url(&mut self) -> &mut Url {
        Arc::make_mut(&mut self.0)
    }

    pub fn set_username(&mut self, user: &str) -> Result<(), ()> {
        self.as_mut_url().set_username(user)
    }

    pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> {
        self.as_mut_url().set_ip_host(addr)
    }

    pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> {
        self.as_mut_url().set_password(pass)
    }

    pub fn set_fragment(&mut self, fragment: Option<&str>) {
        self.as_mut_url().set_fragment(fragment)
    }

    pub fn username(&self) -> &str {
        self.0.username()
    }

    pub fn password(&self) -> Option<&str> {
        self.0.password()
    }

    pub fn to_file_path(&self) -> Result<::std::path::PathBuf, ()> {
        self.0.to_file_path()
    }

    pub fn host(&self) -> Option<url::Host<&str>> {
        self.0.host()
    }

    pub fn host_str(&self) -> Option<&str> {
        self.0.host_str()
    }

    pub fn port(&self) -> Option<u16> {
        self.0.port()
    }

    pub fn port_or_known_default(&self) -> Option<u16> {
        self.0.port_or_known_default()
    }

    pub fn join(&self, input: &str) -> Result<ServoUrl, url::ParseError> {
        self.0.join(input).map(Self::from_url)
    }

    pub fn path_segments(&self) -> Option<::std::str::Split<char>> {
        self.0.path_segments()
    }

    pub fn query(&self) -> Option<&str> {
        self.0.query()
    }

    pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Self, ()> {
        Ok(Self::from_url(Url::from_file_path(path)?))
    }
}

impl fmt::Display for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl fmt::Debug for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl Index<RangeFull> for ServoUrl {
    type Output = str;
    fn index(&self, _: RangeFull) -> &str {
        &self.0[..]
    }
}

impl Index<RangeFrom<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeFrom<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<RangeTo<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeTo<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<Range<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: Range<Position>) -> &str {
        &self.0[range]
    }
}

impl From<Url> for ServoUrl {
    fn from(url: Url) -> Self {
        ServoUrl::from_url(url)
    }
}

impl serde::Serialize for ServoUrl {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        url_serde::serialize(&*self.0, serializer)
    }
}

impl<'de> serde::Deserialize<'de> for ServoUrl {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        url_serde::deserialize(deserializer).map(Self::from_url)
    }
}
<commit_msg>  Truncate long URLs when doing debug prints<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]
#![crate_name = "servo_url"]
#![crate_type = "rlib"]

#[macro_use]
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
#[macro_use]
extern crate serde;

pub mod origin;

pub use crate::origin::{ImmutableOrigin, MutableOrigin, OpaqueOrigin};

use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::Hasher;
use std::net::IpAddr;
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
use std::path::Path;
use std::sync::Arc;
use url::{Position, Url};

pub use url::Host;

#[derive(Clone, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct ServoUrl(#[ignore_malloc_size_of = "Arc"] Arc<Url>);

impl ServoUrl {
    pub fn from_url(url: Url) -> Self {
        ServoUrl(Arc::new(url))
    }

    pub fn parse_with_base(base: Option<&Self>, input: &str) -> Result<Self, url::ParseError> {
        Url::options()
            .base_url(base.map(|b| &*b.0))
            .parse(input)
            .map(Self::from_url)
    }

    pub fn into_string(self) -> String {
        Arc::try_unwrap(self.0)
            .unwrap_or_else(|s| (*s).clone())
            .into_string()
    }

    pub fn into_url(self) -> Url {
        Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())
    }

    pub fn as_url(&self) -> &Url {
        &self.0
    }

    pub fn parse(input: &str) -> Result<Self, url::ParseError> {
        Url::parse(input).map(Self::from_url)
    }

    pub fn cannot_be_a_base(&self) -> bool {
        self.0.cannot_be_a_base()
    }

    pub fn domain(&self) -> Option<&str> {
        self.0.domain()
    }

    pub fn fragment(&self) -> Option<&str> {
        self.0.fragment()
    }

    pub fn path(&self) -> &str {
        self.0.path()
    }

    pub fn origin(&self) -> ImmutableOrigin {
        ImmutableOrigin::new(self.0.origin())
    }

    pub fn scheme(&self) -> &str {
        self.0.scheme()
    }

    pub fn is_secure_scheme(&self) -> bool {
        let scheme = self.scheme();
        scheme == "https" || scheme == "wss"
    }

    pub fn is_chrome(&self) -> bool {
        self.scheme() == "chrome"
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn as_mut_url(&mut self) -> &mut Url {
        Arc::make_mut(&mut self.0)
    }

    pub fn set_username(&mut self, user: &str) -> Result<(), ()> {
        self.as_mut_url().set_username(user)
    }

    pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> {
        self.as_mut_url().set_ip_host(addr)
    }

    pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> {
        self.as_mut_url().set_password(pass)
    }

    pub fn set_fragment(&mut self, fragment: Option<&str>) {
        self.as_mut_url().set_fragment(fragment)
    }

    pub fn username(&self) -> &str {
        self.0.username()
    }

    pub fn password(&self) -> Option<&str> {
        self.0.password()
    }

    pub fn to_file_path(&self) -> Result<::std::path::PathBuf, ()> {
        self.0.to_file_path()
    }

    pub fn host(&self) -> Option<url::Host<&str>> {
        self.0.host()
    }

    pub fn host_str(&self) -> Option<&str> {
        self.0.host_str()
    }

    pub fn port(&self) -> Option<u16> {
        self.0.port()
    }

    pub fn port_or_known_default(&self) -> Option<u16> {
        self.0.port_or_known_default()
    }

    pub fn join(&self, input: &str) -> Result<ServoUrl, url::ParseError> {
        self.0.join(input).map(Self::from_url)
    }

    pub fn path_segments(&self) -> Option<::std::str::Split<char>> {
        self.0.path_segments()
    }

    pub fn query(&self) -> Option<&str> {
        self.0.query()
    }

    pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Self, ()> {
        Ok(Self::from_url(Url::from_file_path(path)?))
    }
}

impl fmt::Display for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl fmt::Debug for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.0.as_str().len() > 40 {
            let hasher = DefaultHasher::new();
            let truncated: String = self.0.as_str().chars().take(40).collect();
            let result = format!("{}... ({})", truncated, hasher.finish().to_string());
            return result.fmt(formatter);
        }
        self.0.fmt(formatter)
    }
}

impl Index<RangeFull> for ServoUrl {
    type Output = str;
    fn index(&self, _: RangeFull) -> &str {
        &self.0[..]
    }
}

impl Index<RangeFrom<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeFrom<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<RangeTo<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeTo<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<Range<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: Range<Position>) -> &str {
        &self.0[range]
    }
}

impl From<Url> for ServoUrl {
    fn from(url: Url) -> Self {
        ServoUrl::from_url(url)
    }
}

impl serde::Serialize for ServoUrl {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        url_serde::serialize(&*self.0, serializer)
    }
}

impl<'de> serde::Deserialize<'de> for ServoUrl {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        url_serde::deserialize(deserializer).map(Self::from_url)
    }
}
<|endoftext|>