<commit_before>use std::panic;
use webcore::ffi;

/// Initializes the library.
///
/// Calling this is required for anything to work.
pub fn initialize() {
    static mut INITIALIZED: bool = false;
    unsafe {
        if INITIALIZED {
            return;
        }

        INITIALIZED = true;
    }

    js! { @(no_return)
        Module.STDWEB = {};
        Module.STDWEB.to_js = function to_js( address ) {
            var kind = HEAPU8[ address + 12 ];
            if( kind === 0 ) {
                return undefined;
            } else if( kind === 1 ) {
                return null;
            } else if( kind === 2 ) {
                return HEAP32[ address / 4 ];
            } else if( kind === 3 ) {
                return HEAPF64[ address / 8 ];
            } else if( kind === 4 ) {
                var pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                return Module.STDWEB.to_js_string( pointer, length );
            } else if( kind === 5 ) {
                return false;
            } else if( kind === 6 ) {
                return true;
            } else if( kind === 7 ) {
                var pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                var output = [];
                for( var i = 0; i < length; ++i ) {
                    output.push( Module.STDWEB.to_js( pointer + i * 16 ) );
                }
                return output;
            } else if( kind === 8 ) {
                var value_array_pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                var key_array_pointer = HEAPU32[ (address + 8) / 4 ];
                var output = {};
                for( var i = 0; i < length; ++i ) {
                    var key_pointer = HEAPU32[ (key_array_pointer + i * 8) / 4 ];
                    var key_length = HEAPU32[ (key_array_pointer + 4 + i * 8) / 4 ];
                    var key = Module.STDWEB.to_js_string( key_pointer, key_length );
                    var value = Module.STDWEB.to_js( value_array_pointer + i * 16 );
                    output[ key ] = value;
                }
                return output;
            } else if( kind === 9 ) {
                return Module.STDWEB.acquire_js_reference( HEAP32[ address / 4 ] );
            } else if( kind === 10 ) {
                var adapter_pointer = HEAPU32[ address / 4 ];
                var pointer = HEAPU32[ (address + 4) / 4 ];
                var deallocator_pointer = HEAPU32[ (address + 8) / 4 ];
                var output = function() {
                    var args = _malloc( 16 );
                    Module.STDWEB.from_js( args, arguments );
                    Runtime.dynCall( "vii", adapter_pointer, [pointer, args] );
                    var result = Module.STDWEB.tmp;
                    Module.STDWEB.tmp = null;

                    return result;
                };

                output.drop = function() {
                    output.drop = null;
                    Runtime.dynCall( "vi", deallocator_pointer, [pointer] );
                };

                return output;
            }
        };
    };

    js! { @(no_return)
        Module.STDWEB.from_js = function from_js( address, value ) {
            var kind = Object.prototype.toString.call( value );
            if( kind === "[object String]" ) {
                var length = lengthBytesUTF8( value );
                var pointer = _malloc( length + 1 );
                stringToUTF8( value, pointer, length + 1 );
                HEAPU8[ address + 12 ] = 4;
                HEAPU32[ address / 4 ] = pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
            } else if( kind === "[object Number]" ) {
                if( value === (value|0) ) {
                    HEAPU8[ address + 12 ] = 2;
                    HEAP32[ address / 4 ] = value;
                } else {
                    HEAPU8[ address + 12 ] = 3;
                    HEAPF64[ address / 8 ] = value;
                }
            } else if( value === null ) {
                HEAPU8[ address + 12 ] = 1;
            } else if( value === undefined ) {
                HEAPU8[ address + 12 ] = 0;
            } else if( value === false ) {
                HEAPU8[ address + 12 ] = 5;
            } else if( value === true ) {
                HEAPU8[ address + 12 ] = 6;
            } else if( kind === "[object Array]" || kind === "[object Arguments]" ) {
                var length = value.length;
                var pointer = _malloc( length * 16 );
                HEAPU8[ address + 12 ] = 7;
                HEAPU32[ address / 4 ] = pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
                for( var i = 0; i < length; ++i ) {
                    Module.STDWEB.from_js( pointer + i * 16, value[ i ] );
                }
            } else if( kind === "[object Object]" ) {
                var keys = Object.keys( value );
                var length = keys.length;
                var key_array_pointer = _malloc( length * 8 );
                var value_array_pointer = _malloc( length * 16 );
                HEAPU8[ address + 12 ] = 8;
                HEAPU32[ address / 4 ] = value_array_pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
                HEAPU32[ (address + 8) / 4 ] = key_array_pointer;
                for( var i = 0; i < length; ++i ) {
                    var key = keys[ i ];
                    var key_length = lengthBytesUTF8( key );
                    var key_pointer = _malloc( key_length + 1 );
                    stringToUTF8( key, key_pointer, key_length + 1 );

                    var key_address = key_array_pointer + i * 8;
                    HEAPU32[ key_address / 4 ] = key_pointer;
                    HEAPU32[ (key_address + 4) / 4 ] = key_length;

                    Module.STDWEB.from_js( value_array_pointer + i * 16, value[ key ] );
                }
            } else {
                var refid = Module.STDWEB.acquire_rust_reference( value );
                HEAPU8[ address + 12 ] = 9;
                HEAP32[ address / 4 ] = refid;
            }
        };
    };

    js! { @(no_return)
        // This is ported from Rust's stdlib; it's faster than
        // the string conversion from Emscripten.
        Module.STDWEB.to_js_string = function to_js_string( index, length ) {
            index = index|0;
            length = length|0;
            var end = (index|0) + (length|0);
            var output = "";
            while( index < end ) {
                var x = HEAPU8[ index++ ];
                if( x < 128 ) {
                    output += String.fromCharCode( x );
                    continue;
                }
                var init = (x & (0x7F >> 2));
                var y = 0;
                if( index < end ) {
                    y = HEAPU8[ index++ ];
                }
                var ch = (init << 6) | (y & 63);
                if( x >= 0xE0 ) {
                    let z = 0;
                    if( index < end ) {
                        z = HEAPU8[ index++ ];
                    }
                    let y_z = ((y & 63) << 6) | (z & 63);
                    ch = init << 12 | y_z;
                    if( x >= 0xF0 ) {
                        let w = 0;
                        if( index < end ) {
                            w = HEAPU8[ index++ ];
                        }
                        ch = (init & 7) << 18 | ((y_z << 6) | (w & 63));
                    }
                }
                output += String.fromCharCode( ch );
                continue;
            }
            return output;
        };
    };

    js! { @(no_return)
        var id_to_ref_map = {};
        var id_to_refcount_map = {};
        var ref_to_id_map = new WeakMap();
        var last_refid = 1;

        Module.STDWEB.acquire_rust_reference = function( reference ) {
            if( reference === undefined || reference === null ) {
                return 0;
            }

            var refid = ref_to_id_map.get( reference );
            if( refid === undefined ) {
                refid = last_refid++;
                ref_to_id_map.set( reference, refid );
                id_to_ref_map[ refid ] = reference;
                id_to_refcount_map[ refid ] = 1;
            } else {
                id_to_refcount_map[ refid ]++;
            }

            return refid;
        };

        Module.STDWEB.acquire_js_reference = function( refid ) {
            return id_to_ref_map[ refid ];
        };

        Module.STDWEB.increment_refcount = function( refid ) {
            id_to_refcount_map[ refid ]++;
        };

        Module.STDWEB.decrement_refcount = function( refid ) {
            id_to_refcount_map[ refid ]--;
            if( id_to_refcount_map[ refid ] === 0 ) {
                var reference = id_to_ref_map[ refid ];
                delete id_to_ref_map[ refid ];
                delete id_to_refcount_map[ refid ];
                ref_to_id_map.delete( reference );
            }
        };
    }

    if cfg!( test ) == false {
        panic::set_hook( Box::new( |info| {
            em_asm_int!( "console.error( 'Encountered a panic!' );" );
            if let Some( value ) = info.payload().downcast_ref::< String >() {
                em_asm_int!( "\
                    console.error( 'Panic error message:', Module.STDWEB.to_js_string( $0, $1 ) );\
                ", value.as_ptr(), value.len() );
            }
            if let Some( location ) = info.location() {
                let file = location.file();
                em_asm_int!( "\
                    console.error( 'Panic location:', Module.STDWEB.to_js_string( $0, $1 ) + ':' + $2 );\
                ", file.as_ptr(), file.len(), location.line() );
            }
        }));
    }
}

/// Runs the event loop.
///
/// You should call this before returning from `main()`,
/// otherwise bad things will happen.
pub fn event_loop() -> ! {
    unsafe {
        ffi::emscripten_set_main_loop( Some( ffi::emscripten_pause_main_loop ), 0, 1 );
    }

    unreachable!();
}
<commit_msg>Replace `let` bindings with `var` ones<commit_after>use std::panic;
use webcore::ffi;

/// Initializes the library.
///
/// Calling this is required for anything to work.
pub fn initialize() {
    static mut INITIALIZED: bool = false;
    unsafe {
        if INITIALIZED {
            return;
        }

        INITIALIZED = true;
    }

    js! { @(no_return)
        Module.STDWEB = {};
        Module.STDWEB.to_js = function to_js( address ) {
            var kind = HEAPU8[ address + 12 ];
            if( kind === 0 ) {
                return undefined;
            } else if( kind === 1 ) {
                return null;
            } else if( kind === 2 ) {
                return HEAP32[ address / 4 ];
            } else if( kind === 3 ) {
                return HEAPF64[ address / 8 ];
            } else if( kind === 4 ) {
                var pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                return Module.STDWEB.to_js_string( pointer, length );
            } else if( kind === 5 ) {
                return false;
            } else if( kind === 6 ) {
                return true;
            } else if( kind === 7 ) {
                var pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                var output = [];
                for( var i = 0; i < length; ++i ) {
                    output.push( Module.STDWEB.to_js( pointer + i * 16 ) );
                }
                return output;
            } else if( kind === 8 ) {
                var value_array_pointer = HEAPU32[ address / 4 ];
                var length = HEAPU32[ (address + 4) / 4 ];
                var key_array_pointer = HEAPU32[ (address + 8) / 4 ];
                var output = {};
                for( var i = 0; i < length; ++i ) {
                    var key_pointer = HEAPU32[ (key_array_pointer + i * 8) / 4 ];
                    var key_length = HEAPU32[ (key_array_pointer + 4 + i * 8) / 4 ];
                    var key = Module.STDWEB.to_js_string( key_pointer, key_length );
                    var value = Module.STDWEB.to_js( value_array_pointer + i * 16 );
                    output[ key ] = value;
                }
                return output;
            } else if( kind === 9 ) {
                return Module.STDWEB.acquire_js_reference( HEAP32[ address / 4 ] );
            } else if( kind === 10 ) {
                var adapter_pointer = HEAPU32[ address / 4 ];
                var pointer = HEAPU32[ (address + 4) / 4 ];
                var deallocator_pointer = HEAPU32[ (address + 8) / 4 ];
                var output = function() {
                    var args = _malloc( 16 );
                    Module.STDWEB.from_js( args, arguments );
                    Runtime.dynCall( "vii", adapter_pointer, [pointer, args] );
                    var result = Module.STDWEB.tmp;
                    Module.STDWEB.tmp = null;

                    return result;
                };

                output.drop = function() {
                    output.drop = null;
                    Runtime.dynCall( "vi", deallocator_pointer, [pointer] );
                };

                return output;
            }
        };
    };

    js! { @(no_return)
        Module.STDWEB.from_js = function from_js( address, value ) {
            var kind = Object.prototype.toString.call( value );
            if( kind === "[object String]" ) {
                var length = lengthBytesUTF8( value );
                var pointer = _malloc( length + 1 );
                stringToUTF8( value, pointer, length + 1 );
                HEAPU8[ address + 12 ] = 4;
                HEAPU32[ address / 4 ] = pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
            } else if( kind === "[object Number]" ) {
                if( value === (value|0) ) {
                    HEAPU8[ address + 12 ] = 2;
                    HEAP32[ address / 4 ] = value;
                } else {
                    HEAPU8[ address + 12 ] = 3;
                    HEAPF64[ address / 8 ] = value;
                }
            } else if( value === null ) {
                HEAPU8[ address + 12 ] = 1;
            } else if( value === undefined ) {
                HEAPU8[ address + 12 ] = 0;
            } else if( value === false ) {
                HEAPU8[ address + 12 ] = 5;
            } else if( value === true ) {
                HEAPU8[ address + 12 ] = 6;
            } else if( kind === "[object Array]" || kind === "[object Arguments]" ) {
                var length = value.length;
                var pointer = _malloc( length * 16 );
                HEAPU8[ address + 12 ] = 7;
                HEAPU32[ address / 4 ] = pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
                for( var i = 0; i < length; ++i ) {
                    Module.STDWEB.from_js( pointer + i * 16, value[ i ] );
                }
            } else if( kind === "[object Object]" ) {
                var keys = Object.keys( value );
                var length = keys.length;
                var key_array_pointer = _malloc( length * 8 );
                var value_array_pointer = _malloc( length * 16 );
                HEAPU8[ address + 12 ] = 8;
                HEAPU32[ address / 4 ] = value_array_pointer;
                HEAPU32[ (address + 4) / 4 ] = length;
                HEAPU32[ (address + 8) / 4 ] = key_array_pointer;
                for( var i = 0; i < length; ++i ) {
                    var key = keys[ i ];
                    var key_length = lengthBytesUTF8( key );
                    var key_pointer = _malloc( key_length + 1 );
                    stringToUTF8( key, key_pointer, key_length + 1 );

                    var key_address = key_array_pointer + i * 8;
                    HEAPU32[ key_address / 4 ] = key_pointer;
                    HEAPU32[ (key_address + 4) / 4 ] = key_length;

                    Module.STDWEB.from_js( value_array_pointer + i * 16, value[ key ] );
                }
            } else {
                var refid = Module.STDWEB.acquire_rust_reference( value );
                HEAPU8[ address + 12 ] = 9;
                HEAP32[ address / 4 ] = refid;
            }
        };
    };

    js! { @(no_return)
        // This is ported from Rust's stdlib; it's faster than
        // the string conversion from Emscripten.
        Module.STDWEB.to_js_string = function to_js_string( index, length ) {
            index = index|0;
            length = length|0;
            var end = (index|0) + (length|0);
            var output = "";
            while( index < end ) {
                var x = HEAPU8[ index++ ];
                if( x < 128 ) {
                    output += String.fromCharCode( x );
                    continue;
                }
                var init = (x & (0x7F >> 2));
                var y = 0;
                if( index < end ) {
                    y = HEAPU8[ index++ ];
                }
                var ch = (init << 6) | (y & 63);
                if( x >= 0xE0 ) {
                    var z = 0;
                    if( index < end ) {
                        z = HEAPU8[ index++ ];
                    }
                    var y_z = ((y & 63) << 6) | (z & 63);
                    ch = init << 12 | y_z;
                    if( x >= 0xF0 ) {
                        var w = 0;
                        if( index < end ) {
                            w = HEAPU8[ index++ ];
                        }
                        ch = (init & 7) << 18 | ((y_z << 6) | (w & 63));
                    }
                }
                output += String.fromCharCode( ch );
                continue;
            }
            return output;
        };
    };

    js! { @(no_return)
        var id_to_ref_map = {};
        var id_to_refcount_map = {};
        var ref_to_id_map = new WeakMap();
        var last_refid = 1;

        Module.STDWEB.acquire_rust_reference = function( reference ) {
            if( reference === undefined || reference === null ) {
                return 0;
            }

            var refid = ref_to_id_map.get( reference );
            if( refid === undefined ) {
                refid = last_refid++;
                ref_to_id_map.set( reference, refid );
                id_to_ref_map[ refid ] = reference;
                id_to_refcount_map[ refid ] = 1;
            } else {
                id_to_refcount_map[ refid ]++;
            }

            return refid;
        };

        Module.STDWEB.acquire_js_reference = function( refid ) {
            return id_to_ref_map[ refid ];
        };

        Module.STDWEB.increment_refcount = function( refid ) {
            id_to_refcount_map[ refid ]++;
        };

        Module.STDWEB.decrement_refcount = function( refid ) {
            id_to_refcount_map[ refid ]--;
            if( id_to_refcount_map[ refid ] === 0 ) {
                var reference = id_to_ref_map[ refid ];
                delete id_to_ref_map[ refid ];
                delete id_to_refcount_map[ refid ];
                ref_to_id_map.delete( reference );
            }
        };
    }

    if cfg!( test ) == false {
        panic::set_hook( Box::new( |info| {
            em_asm_int!( "console.error( 'Encountered a panic!' );" );
            if let Some( value ) = info.payload().downcast_ref::< String >() {
                em_asm_int!( "\
                    console.error( 'Panic error message:', Module.STDWEB.to_js_string( $0, $1 ) );\
                ", value.as_ptr(), value.len() );
            }
            if let Some( location ) = info.location() {
                let file = location.file();
                em_asm_int!( "\
                    console.error( 'Panic location:', Module.STDWEB.to_js_string( $0, $1 ) + ':' + $2 );\
                ", file.as_ptr(), file.len(), location.line() );
            }
        }));
    }
}

/// Runs the event loop.
///
/// You should call this before returning from `main()`,
/// otherwise bad things will happen.
pub fn event_loop() -> ! {
    unsafe {
        ffi::emscripten_set_main_loop( Some( ffi::emscripten_pause_main_loop ), 0, 1 );
    }

    unreachable!();
}
<|endoftext|>


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

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use servo_util::str::{DOMString, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::cell::Ref;
use std::mem;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(tokens.as_slice()).map(|slice| Atom::from_slice(slice)) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = {
            let slices: Vec<&str> = atoms.iter().map(|atom| atom.as_slice()).collect();
            slices.connect("\x20")
        };
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
            AttrValue::TokenList(ref value, _) |
            AttrValue::UInt(ref value, _) => value.as_slice(),
            AttrValue::Atom(ref value) => value.as_slice(),
        }
    }
}

#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: Option<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: owner.map(|o| JS::from_rooted(o)),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Temporary<Attr> {
        reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
                           GlobalRef::Window(window), AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<DOMString> {
        &self.prefix
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().into_string()
    }

    fn Value(self) -> DOMString {
        self.value().as_slice().into_string()
    }

    fn SetValue(self, value: DOMString) {
        match self.owner {
            None => {
                *self.value.borrow_mut() = AttrValue::String(value)
            }
            Some(o) => {
                let owner = o.root();
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    fn TextContent(self) -> DOMString {
        self.Value()
    }

    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    fn Name(self) -> DOMString {
        self.name.as_slice().into_string()
    }

    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.into_string()),
        }
    }

    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }

    fn GetOwnerElement(self) -> Option<Temporary<Element>> {
        self.owner.map(|o| Temporary::new(o))
    }

    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) {
        assert!(Some(owner) == self.owner.map(|o| *o.root()));

        let node: JSRef<Node> = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().into_string(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

impl AttrHelpersForLayout for Attr {
    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        value.as_slice()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = self.value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        match *value {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<commit_msg>Remove unsound Root::deref() call in Attr::set_value.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::js::{OptionalRootedRootable, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use servo_util::str::{DOMString, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::cell::Ref;
use std::mem;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(tokens.as_slice()).map(|slice| Atom::from_slice(slice)) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = {
            let slices: Vec<&str> = atoms.iter().map(|atom| atom.as_slice()).collect();
            slices.connect("\x20")
        };
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
            AttrValue::TokenList(ref value, _) |
            AttrValue::UInt(ref value, _) => value.as_slice(),
            AttrValue::Atom(ref value) => value.as_slice(),
        }
    }
}

#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: Option<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: owner.map(|o| JS::from_rooted(o)),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Temporary<Attr> {
        reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
                           GlobalRef::Window(window), AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<DOMString> {
        &self.prefix
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().into_string()
    }

    fn Value(self) -> DOMString {
        self.value().as_slice().into_string()
    }

    fn SetValue(self, value: DOMString) {
        match self.owner {
            None => {
                *self.value.borrow_mut() = AttrValue::String(value)
            }
            Some(o) => {
                let owner = o.root();
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    fn TextContent(self) -> DOMString {
        self.Value()
    }

    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    fn Name(self) -> DOMString {
        self.name.as_slice().into_string()
    }

    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.into_string()),
        }
    }

    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }

    fn GetOwnerElement(self) -> Option<Temporary<Element>> {
        self.owner.map(|o| Temporary::new(o))
    }

    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) {
        assert!(Some(owner) == self.owner.root().r());

        let node: JSRef<Node> = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().into_string(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

impl AttrHelpersForLayout for Attr {
    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        value.as_slice()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = self.value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        match *value {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<|endoftext|>


<commit_before>use crate::rparser::*;
use crate::{gen_get_variants, Variant};
use httparse::{Request, Response, EMPTY_HEADER};

pub struct HTTPBuilder {}
impl RBuilder for HTTPBuilder {
    fn build(&self) -> Box<dyn RParser> {
        Box::new(HTTPParser::new(b"HTTP"))
    }
    fn get_l4_probe(&self) -> Option<ProbeL4> {
        Some(http_probe)
    }
}

pub struct HTTPParser<'a> {
    _name: Option<&'a [u8]>,

    // request
    pub version: Option<String>,
    pub method: Option<String>,
    pub uri: Option<String>,
    // response
    pub code: Option<u16>,
}

impl<'a> HTTPParser<'a> {
    pub fn new(name: &'a [u8]) -> Self {
        HTTPParser {
            _name: Some(name),
            version: None,
            method: None,
            uri: None,
            code: None,
        }
    }
}

impl<'a> RParser for HTTPParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        // apache usually sets a limit of 100 headers max
        const NUM_OF_HEADERS: usize = 20;
        let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
        if direction == STREAM_TOSERVER {
            let mut req = Request::new(&mut headers[..]);
            let status = req.parse(i);
            trace!("{:?}", status);
            trace!("{:?}", req);
            if let Some(version) = req.version {
                self.version = Some(format!("HTTP/1.{}", version));
            }
            if let Some(method) = req.method {
                self.method = Some(method.to_owned());
            }
            if let Some(uri) = req.path {
                self.uri = Some(uri.to_owned());
            }
        } else {
            let mut resp = Response::new(&mut headers[..]);
            let status = resp.parse(i);
            trace!("{:?}", status);
            trace!("{:?}", resp);
            if let Some(code) = resp.code {
                self.code = Some(code);
            }
        }
        R_STATUS_OK
    }

    gen_get_variants! {HTTPParser, "http.",
        // version     => |s| Some(Variant::from(&s.version)),
        version => map_as_ref,
        method  => map_as_ref,
        uri     => map_as_ref,
        code    => map,
    }
}

pub fn http_probe(i: &[u8], _l4info: &L4Info) -> ProbeResult {
    // number of headers to parse at once
    const NUM_OF_HEADERS: usize = 4;

    if i.len() < 6 {
        return ProbeResult::Unsure;
    }
    // check if first characters match start of "request-line"
    match &i[..4] {
        b"OPTI" | b"GET " | b"HEAD" | b"POST" | b"PUT " | b"PATC" | b"COPY" | b"MOVE" | b"DELE"
        | b"LINK" | b"UNLI" | b"TRAC" | b"WRAP" => (),
        _ => return ProbeResult::NotForUs,
    }
    // try parsing request
    let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
    let mut req = Request::new(&mut headers[..]);
    let status = req.parse(i);
    if let Err(e) = status {
        if e != httparse::Error::TooManyHeaders {
            trace!(
                "data could be HTTP, but got error {:?} while parsing",
                status
            );
            return ProbeResult::Unsure;
        }
    }
    // println!("probe {:?}", status);
    // println!("probe {:?}", req);
    ProbeResult::Certain
}

#[cfg(test)]
mod test {
    use super::http_probe;
    use crate::probe::{L4Info, ProbeResult};

    #[test]
    fn http_parse() {
        let l4_info = L4Info {
            src_port: 1234,
            dst_port: 80,
            l4_proto: 6,
        };
        println!("http request");
        let data = b"GET /foo/:foo.com HTTP/1.1\r\nHost: example.org\r\n\r\n";
        assert_eq!(http_probe(data, &l4_info), ProbeResult::Certain);
        println!("binary");
        let data = b"\x00\x30\x00\x00\x00\x00";
        assert_eq!(http_probe(data, &l4_info), ProbeResult::NotForUs);
    }
}
<commit_msg>HTTP: extract User-Agent<commit_after>use crate::rparser::*;
use crate::{gen_get_variants, Variant};
use httparse::{Request, Response, EMPTY_HEADER};

pub struct HTTPBuilder {}
impl RBuilder for HTTPBuilder {
    fn build(&self) -> Box<dyn RParser> {
        Box::new(HTTPParser::new(b"HTTP"))
    }
    fn get_l4_probe(&self) -> Option<ProbeL4> {
        Some(http_probe)
    }
}

#[derive(Default)]
pub struct HTTPParser<'a> {
    _name: Option<&'a [u8]>,

    // request
    pub version: Option<String>,
    pub method: Option<String>,
    pub uri: Option<String>,
    pub user_agent: Option<String>,
    // response
    pub code: Option<u16>,
}

impl<'a> HTTPParser<'a> {
    pub fn new(name: &'a [u8]) -> Self {
        HTTPParser {
            _name: Some(name),
            ..HTTPParser::default()
        }
    }
}

impl<'a> RParser for HTTPParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        // apache usually sets a limit of 100 headers max
        const NUM_OF_HEADERS: usize = 20;
        let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
        if direction == STREAM_TOSERVER {
            let mut req = Request::new(&mut headers[..]);
            let status = req.parse(i);
            trace!("{:?}", status);
            trace!("{:?}", req);
            if let Some(version) = req.version {
                self.version = Some(format!("HTTP/1.{}", version));
            }
            if let Some(method) = req.method {
                self.method = Some(method.to_owned());
            }
            if let Some(uri) = req.path {
                self.uri = Some(uri.to_owned());
            }
            for hdr in &headers {
                if hdr.name == "User-Agent" {
                    let s = String::from_utf8_lossy(hdr.value).into_owned();
                    self.user_agent = Some(s);
                }
            }
        } else {
            let mut resp = Response::new(&mut headers[..]);
            let status = resp.parse(i);
            trace!("{:?}", status);
            trace!("{:?}", resp);
            if let Some(code) = resp.code {
                self.code = Some(code);
            }
        }
        R_STATUS_OK
    }

    gen_get_variants! {HTTPParser, "http.",
        // version     => |s| Some(Variant::from(&s.version)),
        version    => map_as_ref,
        method     => map_as_ref,
        uri        => map_as_ref,
        user_agent => map_as_ref,
        code       => map,
    }
}

pub fn http_probe(i: &[u8], _l4info: &L4Info) -> ProbeResult {
    // number of headers to parse at once
    const NUM_OF_HEADERS: usize = 4;

    if i.len() < 6 {
        return ProbeResult::Unsure;
    }
    // check if first characters match start of "request-line"
    match &i[..4] {
        b"OPTI" | b"GET " | b"HEAD" | b"POST" | b"PUT " | b"PATC" | b"COPY" | b"MOVE" | b"DELE"
        | b"LINK" | b"UNLI" | b"TRAC" | b"WRAP" => (),
        _ => return ProbeResult::NotForUs,
    }
    // try parsing request
    let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
    let mut req = Request::new(&mut headers[..]);
    let status = req.parse(i);
    if let Err(e) = status {
        if e != httparse::Error::TooManyHeaders {
            trace!(
                "data could be HTTP, but got error {:?} while parsing",
                status
            );
            return ProbeResult::Unsure;
        }
    }
    // println!("probe {:?}", status);
    // println!("probe {:?}", req);
    ProbeResult::Certain
}

#[cfg(test)]
mod test {
    use super::http_probe;
    use crate::probe::{L4Info, ProbeResult};

    #[test]
    fn http_parse() {
        let l4_info = L4Info {
            src_port: 1234,
            dst_port: 80,
            l4_proto: 6,
        };
        println!("http request");
        let data = b"GET /foo/:foo.com HTTP/1.1\r\nHost: example.org\r\n\r\n";
        assert_eq!(http_probe(data, &l4_info), ProbeResult::Certain);
        println!("binary");
        let data = b"\x00\x30\x00\x00\x00\x00";
        assert_eq!(http_probe(data, &l4_info), ProbeResult::NotForUs);
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, Deserialize)]
/// A user object returned from the API
pub struct User{
    /// The username of the user
    pub username: String
}

#[derive(Debug, Deserialize)]
/// An object containing the ID of something newly created
pub struct Id<T>
{
    /// The ID
    pub id: T
}

use ::serde::Deserialize;

#[derive(Debug, Deserialize)]
/// A response that either is an error or a success
pub struct HueResponse<T> {
    /// The result from the bridge if it didn't fail
    pub success: Option<T>,
    /// The error that was returned from the bridge
    pub error: Option<Error>
}

use ::errors::HueError;

impl<'de, T> HueResponse<T> where T: Deserialize<'de> {
    pub fn into_result(self) -> Result<T, HueError> {
        if let Some(t) = self.success {
            Ok(t)
        } else if let Some(error) = self.error {
            Err(error.into())
        } else {
            Err("Malformed repsonse".into())
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct SceneRecall<'a> {
    pub scene: &'a str
}

#[derive(Debug, Deserialize)]
/// An error object returned from the API
pub struct Error {
    /// The URI the error happened on
    pub address: String,
    /// A short description of the error
    pub description: String,
    /// Its errorcode
    #[serde(rename="type")]
    pub code: u16,
}
<commit_msg>Make `json::HueResponse` an enum<commit_after>#[derive(Debug, Deserialize)]
/// A user object returned from the API
pub struct User{
    /// The username of the user
    pub username: String
}

#[derive(Debug, Deserialize)]
/// An object containing the ID of something newly created
pub struct Id<T>
{
    /// The ID
    pub id: T
}

use ::serde::Deserialize;

#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
/// A response that either is an error or a success
pub enum HueResponse<T> {
    /// The result from the bridge if it didn't fail
    Success(T),
    /// The error that was returned from the bridge
    Error(Error)
}

use ::errors::HueError;

impl<T> HueResponse<T> {
    pub fn into_result(self) -> Result<T, HueError> {
        match self {
            HueResponse::Success(s) => Ok(s),
            HueResponse::Error(e) => Err(e.into()),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct SceneRecall<'a> {
    pub scene: &'a str
}

#[derive(Debug, Deserialize)]
/// An error object returned from the API
pub struct Error {
    /// The URI the error happened on
    pub address: String,
    /// A short description of the error
    pub description: String,
    /// Its errorcode
    #[serde(rename="type")]
    pub code: u16,
}
<|endoftext|>


<commit_before>#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh {
        filename: String,
        #[serde(default = "default_scale")]
        #[serde(with = "urdf_vec3")]
        scale: [f64; 3],
    },
}

fn default_scale() -> [f64; 3] {
    [1.0f64; 3]
}

fn default_one() -> f64 {
    1.0f64
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: [0.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    #[serde(default = "default_rgba")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See http://wiki.ros.org/urdf/XML/link for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Visual,
    #[serde(default)]
    pub collision: Collision,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 3];
        for i in 0..3 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 4];
        for i in 0..4 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: [1.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

fn default_rgba() -> [f64; 4] {
    [1.0f64, 1.0, 1.0, 1.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    #[serde(default)]
    pub effort: f64,
    #[serde(default)]
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    joint: String,
    #[serde(default = "default_one")]
    multiplier: f64,
    #[serde(default)]
    offset: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    soft_lower_limit: f64,
    #[serde(default)]
    soft_upper_limit: f64,
    #[serde(default)]
    k_position: f64,
    k_velocity: f64,
}

/// Urdf Joint element
/// See http://wiki.ros.org/urdf/XML/joint for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    damping: f64,
    #[serde(default)]
    friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<commit_msg>Make robot.name optional<commit_after>#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh {
        filename: String,
        #[serde(default = "default_scale")]
        #[serde(with = "urdf_vec3")]
        scale: [f64; 3],
    },
}

fn default_scale() -> [f64; 3] {
    [1.0f64; 3]
}

fn default_one() -> f64 {
    1.0f64
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: [0.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    #[serde(default = "default_rgba")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See http://wiki.ros.org/urdf/XML/link for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Visual,
    #[serde(default)]
    pub collision: Collision,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 3];
        for i in 0..3 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 4];
        for i in 0..4 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: [1.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

fn default_rgba() -> [f64; 4] {
    [1.0f64, 1.0, 1.0, 1.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    #[serde(default)]
    pub effort: f64,
    #[serde(default)]
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    joint: String,
    #[serde(default = "default_one")]
    multiplier: f64,
    #[serde(default)]
    offset: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    soft_lower_limit: f64,
    #[serde(default)]
    soft_upper_limit: f64,
    #[serde(default)]
    k_position: f64,
    k_velocity: f64,
}

/// Urdf Joint element
/// See http://wiki.ros.org/urdf/XML/joint for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    damping: f64,
    #[serde(default)]
    friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::iter::Iterator;
use data::{Value, List, Cons, Scope, RuntimeError};

impl List
{
    pub fn cons(car: Value, cdr: List) -> List
    {
        List::Node(Rc::new(Cons{ car: car, cdr: cdr }))
    }

    pub fn from_vec(mut vec: Vec<Value>) -> List
    {
        let mut cdr = List::End;
        while let Some(car) = vec.pop()
        {
            cdr = List::cons(car, cdr);
        }
        cdr
    }

    pub fn iter(&self) -> ListIter
    {
        ListIter(self)
    }

    pub fn eval(&self, env: &mut Scope) -> Result<List, RuntimeError>
    {
        Ok(List::from_vec(try!(self.iter().map(|val| val.eval(env)).collect())))
    }

    pub fn call(&self, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        match *self {
            List::Node(ref cons) => match try!(cons.car.eval(env)) {
                Value::Function(ref func) => func.call(&cons.cdr, env),
                other => Err(RuntimeError::InvalidCall(other.type_name())),
            },
            List::End => Ok(Value::Nil),
        }
    }

    pub fn fold<T, F>(&self, mut acc: T, mut f: F) -> Result<T, RuntimeError>
        where F: FnMut(T, Value) -> Result<T, RuntimeError>
    {
        let mut iter = self.iter();
        while let Some(val) = iter.next()
        {
            acc = try!(f(acc, val))
        }
        Ok(acc)
    }
}

#[derive(Clone)]
pub struct ListIter<'a>(&'a List);

impl<'a> Iterator for ListIter<'a>
{
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item>
    {
        match *self.0 {
            List::Node(ref cons) => {
                self.0 = &cons.cdr;
                Some(cons.car.clone())
            },
            List::End => None,
        }
    }
}
<commit_msg>this looks prettier<commit_after>use std::rc::Rc;
use std::iter::Iterator;
use data::{Value, List, Cons, Scope, RuntimeError};

impl List
{
    pub fn cons(car: Value, cdr: List) -> List
    {
        List::Node(Rc::new(Cons{ car: car, cdr: cdr }))
    }

    pub fn from_vec(mut vec: Vec<Value>) -> List
    {
        let mut cdr = List::End;
        while let Some(car) = vec.pop()
        {
            cdr = List::cons(car, cdr);
        }
        cdr
    }

    pub fn iter(&self) -> ListIter
    {
        ListIter(self)
    }

    pub fn eval(&self, env: &mut Scope) -> Result<List, RuntimeError>
    {
        self.iter().map(|val| val.eval(env)).collect::<Result<_, _>>().map(|v| List::from_vec(v))
    }

    pub fn call(&self, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        match *self {
            List::Node(ref cons) => match try!(cons.car.eval(env)) {
                Value::Function(ref func) => func.call(&cons.cdr, env),
                other => Err(RuntimeError::InvalidCall(other.type_name())),
            },
            List::End => Ok(Value::Nil),
        }
    }

    pub fn fold<T, F>(&self, mut acc: T, mut f: F) -> Result<T, RuntimeError>
        where F: FnMut(T, Value) -> Result<T, RuntimeError>
    {
        let mut iter = self.iter();
        while let Some(val) = iter.next()
        {
            acc = try!(f(acc, val))
        }
        Ok(acc)
    }
}

#[derive(Clone)]
pub struct ListIter<'a>(&'a List);

impl<'a> Iterator for ListIter<'a>
{
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item>
    {
        match *self.0 {
            List::Node(ref cons) => {
                self.0 = &cons.cdr;
                Some(cons.car.clone())
            },
            List::End => None,
        }
    }
}
<|endoftext|>


<commit_before>//! IO operations for pattern and exception data provided by `hyph-UTF8`
//! and stored in the `patterns` folder.

use std::error;
use std::fmt;
use std::io;

use serde_json::{self as json};

use klpair::KLPair;
use language::{Corpus, Language, mins, tag};
use exception::{Exceptions};
use pattern::{Patterns};
use resources::ResourceId;

pub fn data_file(lang: Language, suffix: &str) -> Result<&[u8], Error> {
    let fname = format!("hyph-{}.{}.json", tag(lang), suffix);
    let res: Option<ResourceId> = ResourceId::from_name(&fname);

    match res {
        Some(data) => Ok(data.load()),
        None => Err(Error::Resource)
    }
}

pub fn patterns(lang: Language) -> Result<Vec<KLPair>, Error> {
    let f = try!(data_file(lang, "pat"));
    let pairs: Vec<(String, Vec<u32>)> = try!(json::from_slice(f));

    Ok(pairs)
}

pub fn exceptions(lang: Language) -> Result<Vec<KLPair>, Error> {
    let f = try!(data_file(lang, "hyp"));
    let pairs: Vec<(String, Vec<u32>)> = try!(json::from_reader(f));

    Ok(pairs)
}

/// Constructs the default `Corpus` for a given language.
pub fn language(lang: Language) -> Result<Corpus, Error> {
    let (l, r) = mins(lang);
    let pat_pairs = try!(patterns(lang));
    let ex_pairs = try!(exceptions(lang));

    let mut ps = Patterns::empty();
    for p in pat_pairs {
        ps.insert(p);
    }

    let mut exs = Exceptions::empty();
    for ex in ex_pairs {
        exs.insert(ex);
    }

    Ok(Corpus {
        language: lang,
        patterns: ps,
        exceptions: if !exs.0.is_empty() { Some(exs) } else { None },
        left_min: l,
        right_min: r
    })
}

/// Failure modes of pattern loading.
#[derive(Debug)]
pub enum Error {
    IO(io::Error),
    Deserialization(json::Error),
    Resource
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IO(ref e) => e.description(),
            Error::Deserialization(ref e) => e.description(),
            Error::Resource => "Pattern resource failed to load"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::IO(ref e) => e.fmt(f),
            Error::Deserialization(ref e) => e.fmt(f),
            Error::Resource => {
                let e = self as &error::Error;
                e.description().fmt(f)
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IO(err)
    }
}

impl From<json::Error> for Error {
    fn from(err: json::Error) -> Error {
        Error::Deserialization(err)
    }
}
<commit_msg>Oversight: load exceptions from slice<commit_after>//! IO operations for pattern and exception data provided by `hyph-UTF8`
//! and stored in the `patterns` folder.

use std::error;
use std::fmt;
use std::io;

use serde_json::{self as json};

use klpair::KLPair;
use language::{Corpus, Language, mins, tag};
use exception::{Exceptions};
use pattern::{Patterns};
use resources::ResourceId;

pub fn data_file(lang: Language, suffix: &str) -> Result<&[u8], Error> {
    let fname = format!("hyph-{}.{}.json", tag(lang), suffix);
    let res: Option<ResourceId> = ResourceId::from_name(&fname);

    match res {
        Some(data) => Ok(data.load()),
        None => Err(Error::Resource)
    }
}

pub fn patterns(lang: Language) -> Result<Vec<KLPair>, Error> {
    let f = try!(data_file(lang, "pat"));
    let pairs: Vec<(String, Vec<u32>)> = try!(json::from_slice(f));

    Ok(pairs)
}

pub fn exceptions(lang: Language) -> Result<Vec<KLPair>, Error> {
    let f = try!(data_file(lang, "hyp"));
    let pairs: Vec<(String, Vec<u32>)> = try!(json::from_slice(f));

    Ok(pairs)
}

/// Constructs the default `Corpus` for a given language.
pub fn language(lang: Language) -> Result<Corpus, Error> {
    let (l, r) = mins(lang);
    let pat_pairs = try!(patterns(lang));
    let ex_pairs = try!(exceptions(lang));

    let mut ps = Patterns::empty();
    for p in pat_pairs {
        ps.insert(p);
    }

    let mut exs = Exceptions::empty();
    for ex in ex_pairs {
        exs.insert(ex);
    }

    Ok(Corpus {
        language: lang,
        patterns: ps,
        exceptions: if !exs.0.is_empty() { Some(exs) } else { None },
        left_min: l,
        right_min: r
    })
}

/// Failure modes of pattern loading.
#[derive(Debug)]
pub enum Error {
    IO(io::Error),
    Deserialization(json::Error),
    Resource
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IO(ref e) => e.description(),
            Error::Deserialization(ref e) => e.description(),
            Error::Resource => "Pattern resource failed to load"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::IO(ref e) => e.fmt(f),
            Error::Deserialization(ref e) => e.fmt(f),
            Error::Resource => {
                let e = self as &error::Error;
                e.description().fmt(f)
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IO(err)
    }
}

impl From<json::Error> for Error {
    fn from(err: json::Error) -> Error {
        Error::Deserialization(err)
    }
}
<|endoftext|>


<commit_before>use hyper::Client;
use hyper::client::Response;
use serde_json::StreamDeserializer;
use std::io::{BufRead, BufReader, Read};
use std::sync::mpsc::{Sender, channel};
use std::thread;
use super::Error;
use super::rand;
use super::serde_json;
use super::term;
use super::url;

include!(concat!(env!("OUT_DIR"), "/logs.rs"));

const PROXY_HOST: &'static str = "http://127.0.0.1:8001";

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

#[derive(Default, Debug)]
pub struct Logs {
    follow: bool,
    label: Option<String>,
    namespace: Option<String>,
}

impl Logs {
    pub fn new(follow: bool, label: Option<String>, namespace: Option<String>) -> Logs {
        Logs {
            follow: follow,
            label: label,
            namespace: namespace,
        }
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let colors = vec![term::color::CYAN,
                          term::color::MAGENTA,
                          term::color::GREEN,
                          term::color::YELLOW,
                          term::color::BRIGHT_BLUE];
        let mut rng = rand::thread_rng();
        let client = Client::new();
        let mut pods_endpoint = match self.namespace {
            Some(ref ns) => {
                try!(try!(url::Url::parse(PROXY_HOST))
                    .join(&format!("/api/v1/namespaces/{}/pods", ns)))
            }
            _ => try!(try!(url::Url::parse(PROXY_HOST)).join("/api/v1/pods")),

        };
        if let Some(ref label) = self.label {
            pods_endpoint.query_pairs_mut().append_pair("labelSelector", label);
        }
        if self.follow {
            pods_endpoint.query_pairs_mut().append_pair("watch", true.to_string().as_str());
        }
        let response = try!(client.get(pods_endpoint).send());
        let (tx, rx) = channel();
        // recv records from the channel
        let mut t = term::stdout().unwrap();
        thread::spawn(move || {
            loop {
                if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                    t.reset().unwrap();
                    t.fg(color).unwrap();
                    write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                    t.reset().unwrap();
                    writeln!(t, " {}", text).unwrap();
                }
            }
        });

        fn podlogs(client: &Client,
                   follow: bool,
                   pod: Pod,
                   px: Sender<Record>,
                   color: term::color::Color)
                   -> thread::JoinHandle<()> {
            let containers = pod.spec.containers.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
            let mut logs_endpoint = url::Url::parse(PROXY_HOST)
                .unwrap()
                .join(&format!("/api/v1/namespaces/{}/pods/{}/log",
                               pod.metadata.namespace,
                               pod.metadata.name))
                .unwrap();
            logs_endpoint.query_pairs_mut()
                .extend_pairs(vec![("container", containers[0].as_str()),
                                   ("follow", follow.to_string().as_str())]);
            let reader = BufReader::new(client.get(logs_endpoint).send().unwrap());

            thread::spawn(move || {
                for l in reader.lines() {
                    if let Ok(text) = l {
                        let _ = px.send(Record {
                            namespace: pod.metadata.namespace.clone(),
                            pod: pod.metadata.name.clone(),
                            container: containers[0].clone(),
                            color: color,
                            text: text,
                        });
                    }
                }
            })
        }

        if self.follow {
            let stream: StreamDeserializer<PodEvent, _> = StreamDeserializer::new(response.bytes());
            for e in stream {
                match e {
                    Ok(event) => {
                        let _ = podlogs(&client,
                                        self.follow,
                                        event.object,
                                        tx.clone(),
                                        rand::sample(&mut rng, colors.clone(), 1)[0]);
                    }
                    Err(_) => {
                        break;
                    }
                }
            }
        } else {
            let pods = try!(serde_json::from_reader::<Response, PodList>(response));
            for pod in pods.items {
                let _ = podlogs(&client,
                                self.follow,
                                pod,
                                tx.clone(),
                                rand::sample(&mut rng, colors.clone(), 1)[0]);
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>capture logs from all containers, not just the first<commit_after>use hyper::Client;
use hyper::client::Response;
use serde_json::StreamDeserializer;
use std::io::{BufRead, BufReader, Read};
use std::sync::mpsc::{Sender, channel};
use std::thread;
use super::Error;
use super::rand;
use super::serde_json;
use super::term;
use super::url;

include!(concat!(env!("OUT_DIR"), "/logs.rs"));

const PROXY_HOST: &'static str = "http://127.0.0.1:8001";

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

#[derive(Default, Debug)]
pub struct Logs {
    follow: bool,
    label: Option<String>,
    namespace: Option<String>,
}

impl Logs {
    pub fn new(follow: bool, label: Option<String>, namespace: Option<String>) -> Logs {
        Logs {
            follow: follow,
            label: label,
            namespace: namespace,
        }
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let colors = vec![term::color::CYAN,
                          term::color::MAGENTA,
                          term::color::GREEN,
                          term::color::YELLOW,
                          term::color::BRIGHT_BLUE];
        let mut rng = rand::thread_rng();
        let client = Client::new();
        let mut pods_endpoint = match self.namespace {
            Some(ref ns) => {
                try!(try!(url::Url::parse(PROXY_HOST))
                    .join(&format!("/api/v1/namespaces/{}/pods", ns)))
            }
            _ => try!(try!(url::Url::parse(PROXY_HOST)).join("/api/v1/pods")),

        };
        if let Some(ref label) = self.label {
            pods_endpoint.query_pairs_mut().append_pair("labelSelector", label);
        }
        if self.follow {
            pods_endpoint.query_pairs_mut().append_pair("watch", true.to_string().as_str());
        }
        let response = try!(client.get(pods_endpoint).send());
        let (tx, rx) = channel();
        // recv records from the channel
        let mut t = term::stdout().unwrap();
        thread::spawn(move || {
            loop {
                if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                    t.reset().unwrap();
                    t.fg(color).unwrap();
                    write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                    t.reset().unwrap();
                    writeln!(t, " {}", text).unwrap();
                }
            }
        });

        fn podlogs(client: &Client,
                   follow: bool,
                   pod: Pod,
                   px: Sender<Record>,
                   color: term::color::Color)
                   -> Vec<thread::JoinHandle<()>> {
            let mut tails = vec![];
            for container in pod.spec.containers {
                let pxc = px.clone();
                let this_namespace = pod.metadata.namespace.clone();
                let this_pod_name = pod.metadata.name.clone();
                let mut logs_endpoint = url::Url::parse(PROXY_HOST)
                    .unwrap()
                    .join(&format!("/api/v1/namespaces/{}/pods/{}/log",
                                   this_namespace,
                                   this_pod_name))
                    .unwrap();
                logs_endpoint.query_pairs_mut()
                    .extend_pairs(vec![("container", container.name.as_str()),
                                       ("follow", follow.to_string().as_str())]);
                let reader = BufReader::new(client.get(logs_endpoint).send().unwrap());

                tails.push(thread::spawn(move || {
                    for l in reader.lines() {
                        if let Ok(text) = l {
                            let _ = pxc.send(Record {
                                namespace: this_namespace.clone(),
                                pod: this_pod_name.clone(),
                                container: container.name.clone(),
                                color: color,
                                text: text,
                            });
                        }
                    }
                }))
            }
            tails
        }

        if self.follow {
            let stream: StreamDeserializer<PodEvent, _> = StreamDeserializer::new(response.bytes());
            for e in stream {
                match e {
                    Ok(event) => {
                        let _ = podlogs(&client,
                                        self.follow,
                                        event.object,
                                        tx.clone(),
                                        rand::sample(&mut rng, colors.clone(), 1)[0]);
                    }
                    Err(_) => {
                        break;
                    }
                }
            }
        } else {
            let pods = try!(serde_json::from_reader::<Response, PodList>(response));
            for pod in pods.items {
                let _ = podlogs(&client,
                                self.follow,
                                pod,
                                tx.clone(),
                                rand::sample(&mut rng, colors.clone(), 1)[0]);
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


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

//! lron stands for Lightroom Object Notation, specific to Lightroom
//! that is found throughout the catalog database to store abtrary bu
//! structured data.
//!
//! lron looks like plist (before XML) or JSON, but doesn't match
//! either.
//!
//! Note: I couldn't figure out what this format was called, so I
//! couldn't reuse an existing parser. If you have a better idea,
//! please, let me know.
//!
//! It has the form
//! ```json
//! name = {
//!   object = {
//!     x = 1.3,
//!     string = "some text",
//!   },
//! }
//! ```
//!
//! The text is parsed using peg.
//!
//! You obtain the expression from the text by the following:
//! ```
//! use lrcat::lron;
//!
//! let lron_text = "name = {}"; // load the text in the string
//!
//! if let Ok(object) = lron::Object::from_string(lron_text) {
//!     // do your stuff with it
//! }
//! ```

/// Lron Value
#[derive(Debug, PartialEq)]
pub enum Value {
    Dict(Vec<Object>),
    Str(String),
    ZStr(String),
    Int(i32),
    Float(f64),
    Bool(bool),
}

impl Value {
    /// Try to convert the value into a number of type T.  This is
    /// because number are untyped in Lron, and the parser will manage
    /// float or int.  Instead of having a generic Number type, it's
    /// better this way.
    pub fn to_number<T>(&self) -> Option<T>
    where
        T: std::convert::From<i32> + std::convert::From<f64>,
    {
        match *self {
            Self::Int(i) => Some(i.into()),
            Self::Float(f) => Some(f.into()),
            _ => None,
        }
    }
}

/// A key/value pair.
#[derive(Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Value,
}

/// Lron Object
#[derive(Debug, PartialEq)]
pub enum Object {
    Dict(Vec<Object>),
    Pair(Pair),
    Str(String),
    ZStr(String),
    Int(i32),
}

/// Alias result type for parsing a Lron object.
type Result<T> = std::result::Result<T, peg::error::ParseError<peg::str::LineCol>>;

impl Object {
    /// Create an object from a string
    pub fn from_string(s: &str) -> Result<Object> {
        lron::root(s)
    }
}

// lron stand for Lightroom Object Notation
// Some sort of JSON specific to Lightroom
//
// lron data syntax is defined in this PEG grammar.
peg::parser! {grammar lron() for str {

use std::str::FromStr;

pub rule root() -> Object
        = key:identifier() _() "=" _() value:array() _()
    { Object::Pair(Pair{key, value: Value::Dict(value)}) }

rule array() -> Vec<Object>
        = "{" _() v:(object() ** (_() "," _())) _()(",")? _() "}" { v }

rule object() -> Object
        = a:array() { Object::Dict(a) } /
        p:pair() { Object::Pair(p) } /
        s:string_literal() { Object::Str(s) } /
        z:zstr() { Object::ZStr(z) } /
        n:int() { Object::Int(n) }

rule pair() -> Pair
        = key:identifier() _() "=" _() value:value() { Pair { key, value } } /
        "[" key:string_literal() "]" _() "=" _() value:value()
    { Pair { key, value } }

rule value() -> Value
        = i:int() { Value::Int(i) } /
        b:bool() { Value::Bool(b) } /
        f:float() { Value::Float(f) } /
        s:string_literal() { Value::Str(s) } /
        a:array() { Value::Dict(a) } /
        z:zstr() { Value::ZStr(z) }

rule int() -> i32
        = n:$("-"? ['0'..='9']+) !"." { i32::from_str(n).unwrap() } / expected!("integer")

rule bool() -> bool
        = "true" { true } / "false" { false }

rule float() -> f64
        = f:$("-"? ['0'..='9']+ "." ['0'..='9']+) { f64::from_str(f).unwrap() } / expected!("floating point")

rule identifier() -> String
        = s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_']+) { s.to_owned() } / expected!("identifier")

rule string_literal() -> String
        = "\"" s:$((!['"'][_])*) "\"" { s.to_owned() }

rule zstr() -> String
        = "ZSTR" _() s:string_literal() { s }

rule _() = quiet!{[' ' | '\r' | '\n' | '\t']*}

}}

#[test]
fn test_parser() {
    const DATA: &'static str = "s = { \
         { \
         criteria = \"rating\", \
         operation = \">\", \
         value = 0, \
         value2 = 0, \
         }, \
         combine = \"intersect\", \
         }";
    let r = Object::from_string(DATA);

    assert!(r.is_ok());
    let o = r.unwrap();

    println!("{:?}", o);
    assert!(matches!(o, Object::Pair(_)));
    if let Object::Pair(ref p) = o {
        assert_eq!(p.key, "s");
        assert!(matches!(p.value, Value::Dict(_)));

        if let Value::Dict(ref d) = p.value {
            assert_eq!(d.len(), 2);
            assert!(matches!(d[0], Object::Dict(_)));
            if let Object::Dict(ref d) = d[0] {
                assert_eq!(d.len(), 4);
                assert!(matches!(d[0], Object::Pair(_)));
                assert!(matches!(d[1], Object::Pair(_)));
                assert!(matches!(d[2], Object::Pair(_)));
                assert!(matches!(d[3], Object::Pair(_)));
            }
            assert!(matches!(d[1], Object::Pair(_)));
            if let Object::Pair(ref p) = d[1] {
                assert_eq!(p.key, "combine");
                assert_eq!(p.value, Value::Str("intersect".to_owned()));
            }
        }
    } else {
        assert!(false);
    }
}
<commit_msg>Fix some documentation typos<commit_after>/*
 This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

//! lron stands for Lightroom Object Notation, specific to Lightroom
//! that is found throughout the catalog database to store arbitrary
//! but structured data.
//!
//! lron looks like plist (before XML) or JSON, but doesn't match
//! either syntax.
//!
//! Note: I couldn't figure out what this format was called, so I
//! couldn't reuse an existing parser. If you have a better idea,
//! please, let me know.
//!
//! It has the form
//! ```json
//! name = {
//!   object = {
//!     x = 1.3,
//!     string = "some text",
//!   },
//! }
//! ```
//!
//! The text is parsed using peg.
//!
//! You obtain the expression from the text by the following:
//! ```
//! use lrcat::lron;
//!
//! let lron_text = "name = {}"; // load the text in the string
//!
//! if let Ok(object) = lron::Object::from_string(lron_text) {
//!     // do your stuff with it
//! }
//! ```

/// Lron Value
#[derive(Debug, PartialEq)]
pub enum Value {
    Dict(Vec<Object>),
    Str(String),
    ZStr(String),
    Int(i32),
    Float(f64),
    Bool(bool),
}

impl Value {
    /// Try to convert the value into a number of type T.  This is
    /// because number are untyped in Lron, and the parser will manage
    /// float or int.  Instead of having a generic Number type, it's
    /// better this way.
    pub fn to_number<T>(&self) -> Option<T>
    where
        T: std::convert::From<i32> + std::convert::From<f64>,
    {
        match *self {
            Self::Int(i) => Some(i.into()),
            Self::Float(f) => Some(f.into()),
            _ => None,
        }
    }
}

/// A key/value pair.
#[derive(Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Value,
}

/// Lron Object
#[derive(Debug, PartialEq)]
pub enum Object {
    Dict(Vec<Object>),
    Pair(Pair),
    Str(String),
    ZStr(String),
    Int(i32),
}

/// Alias result type for parsing a Lron object.
type Result<T> = std::result::Result<T, peg::error::ParseError<peg::str::LineCol>>;

impl Object {
    /// Create an object from a string
    pub fn from_string(s: &str) -> Result<Object> {
        lron::root(s)
    }
}

// lron stand for Lightroom Object Notation
// Some sort of JSON specific to Lightroom
//
// lron data syntax is defined in this PEG grammar.
peg::parser! {grammar lron() for str {

use std::str::FromStr;

pub rule root() -> Object
        = key:identifier() _() "=" _() value:array() _()
    { Object::Pair(Pair{key, value: Value::Dict(value)}) }

rule array() -> Vec<Object>
        = "{" _() v:(object() ** (_() "," _())) _()(",")? _() "}" { v }

rule object() -> Object
        = a:array() { Object::Dict(a) } /
        p:pair() { Object::Pair(p) } /
        s:string_literal() { Object::Str(s) } /
        z:zstr() { Object::ZStr(z) } /
        n:int() { Object::Int(n) }

rule pair() -> Pair
        = key:identifier() _() "=" _() value:value() { Pair { key, value } } /
        "[" key:string_literal() "]" _() "=" _() value:value()
    { Pair { key, value } }

rule value() -> Value
        = i:int() { Value::Int(i) } /
        b:bool() { Value::Bool(b) } /
        f:float() { Value::Float(f) } /
        s:string_literal() { Value::Str(s) } /
        a:array() { Value::Dict(a) } /
        z:zstr() { Value::ZStr(z) }

rule int() -> i32
        = n:$("-"? ['0'..='9']+) !"." { i32::from_str(n).unwrap() } / expected!("integer")

rule bool() -> bool
        = "true" { true } / "false" { false }

rule float() -> f64
        = f:$("-"? ['0'..='9']+ "." ['0'..='9']+) { f64::from_str(f).unwrap() } / expected!("floating point")

rule identifier() -> String
        = s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_']+) { s.to_owned() } / expected!("identifier")

rule string_literal() -> String
        = "\"" s:$((!['"'][_])*) "\"" { s.to_owned() }

rule zstr() -> String
        = "ZSTR" _() s:string_literal() { s }

rule _() = quiet!{[' ' | '\r' | '\n' | '\t']*}

}}

#[test]
fn test_parser() {
    const DATA: &'static str = "s = { \
         { \
         criteria = \"rating\", \
         operation = \">\", \
         value = 0, \
         value2 = 0, \
         }, \
         combine = \"intersect\", \
         }";
    let r = Object::from_string(DATA);

    assert!(r.is_ok());
    let o = r.unwrap();

    println!("{:?}", o);
    assert!(matches!(o, Object::Pair(_)));
    if let Object::Pair(ref p) = o {
        assert_eq!(p.key, "s");
        assert!(matches!(p.value, Value::Dict(_)));

        if let Value::Dict(ref d) = p.value {
            assert_eq!(d.len(), 2);
            assert!(matches!(d[0], Object::Dict(_)));
            if let Object::Dict(ref d) = d[0] {
                assert_eq!(d.len(), 4);
                assert!(matches!(d[0], Object::Pair(_)));
                assert!(matches!(d[1], Object::Pair(_)));
                assert!(matches!(d[2], Object::Pair(_)));
                assert!(matches!(d[3], Object::Pair(_)));
            }
            assert!(matches!(d[1], Object::Pair(_)));
            if let Object::Pair(ref p) = d[1] {
                assert_eq!(p.key, "combine");
                assert_eq!(p.value, Value::Str("intersect".to_owned()));
            }
        }
    } else {
        assert!(false);
    }
}
<|endoftext|>


<commit_before>use getopts::{getopts,OptGroup,Matches};
use help;
use creator;
use editor;

/// The initializer module parses arguments and verfies commands are valid
/// before passing them for execution.

/// The init method accepts a `Vec<String>` of arguments. If an argument or
/// command does not match valid input print the help screen.
pub fn init(args: Vec<String>) {
    let program = args[0].clone();
    let opts = help::opts();
    let matches = &get_matches(args.tail(), opts.clone());

    if matches.opt_present("h") || !validate_command(matches) {
        help::print_usage(program.as_slice(), opts);
        return;
    }

    run_command(matches);
}

/// Accept the current arguments and match them using getopts.
/// # Errors
/// Will fail if arguments are not found.
fn get_matches(tail: &[String], opts: &[OptGroup]) -> Matches {
    return match getopts(tail, opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    }
}

/// Validate the free text passed to the application. If the free text can match
/// an application command return `true` otherwise `false`.
fn validate_command(matches: &Matches) -> bool {
    let command = if matches.free.len() == 2 {
        matches.free[0].as_slice()
    } else {
        return false
    };

    return match command {
        "new"  => true,
        "open" => true,
        _      => false
    }
}

/// Once the free text has been validated use the command to execute the
/// operation.
/// # Errors
/// prints out “Nope”.
/// # TODO:
/// Fix the fallthrough execution path to not print “Nope”.
fn run_command(matches: &Matches) {
    let command = matches.free[0].as_slice();
    let value = matches.free[1].as_slice();

    match command {
        "new"  => creator::new(value),
        "open" => editor::new(value),
        _      => println!("Nope")
    }
}

#[test]
fn validate_command_new_returns_true() {
    let matches = &get_matches([String::from_str("new"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), true);
}

#[test]
fn validate_command_open_returns_true() {
    let matches = &get_matches([String::from_str("open"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), true);
}

#[test]
fn validate_command_value_returns_false() {
    let matches = &get_matches([String::from_str("value"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), false);
}

#[test]
#[should_fail]
fn get_matches_returns_failure_with_bad_opts() {
    get_matches([String::from_str("-m")], help::opts());
}
<commit_msg>Spacing.<commit_after>use getopts::{getopts,OptGroup,Matches};
use help;
use creator;
use editor;

/// The initializer module parses arguments and verfies commands are valid
/// before passing them for execution.

/// The init method accepts a `Vec<String>` of arguments. If an argument or
/// command does not match valid input print the help screen.
pub fn init(args: Vec<String>) {
    let program = args[0].clone();
    let opts = help::opts();
    let matches = &get_matches(args.tail(), opts.clone());

    if matches.opt_present("h") || !validate_command(matches) {
        help::print_usage(program.as_slice(), opts);
        return;
    }

    run_command(matches);
}

/// Accept the current arguments and match them using getopts.
/// # Errors
/// Will fail if arguments are not found.
fn get_matches(tail: &[String], opts: &[OptGroup]) -> Matches {
    return match getopts(tail, opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    }
}

/// Validate the free text passed to the application. If the free text can match
/// an application command return `true` otherwise `false`.
fn validate_command(matches: &Matches) -> bool {
    let command = if matches.free.len() == 2 {
        matches.free[0].as_slice()
    } else {
        return false
    };

    return match command {
        "new"  => true,
        "open" => true,
        _      => false
    }
}

/// Once the free text has been validated use the command to execute the
/// operation.
/// # Errors
/// prints out “Nope”.
/// # TODO:
/// Fix the fallthrough execution path to not print “Nope”.
fn run_command(matches: &Matches) {
    let command = matches.free[0].as_slice();
    let value   = matches.free[1].as_slice();

    match command {
        "new"  => creator::new(value),
        "open" => editor::new(value),
        _      => println!("Nope")
    }
}

#[test]
fn validate_command_new_returns_true() {
    let matches = &get_matches([String::from_str("new"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), true);
}

#[test]
fn validate_command_open_returns_true() {
    let matches = &get_matches([String::from_str("open"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), true);
}

#[test]
fn validate_command_value_returns_false() {
    let matches = &get_matches([String::from_str("value"), String::from_str("muxed")], help::opts());
    assert_eq!(validate_command(matches), false);
}

#[test]
#[should_fail]
fn get_matches_returns_failure_with_bad_opts() {
    get_matches([String::from_str("-m")], help::opts());
}
<|endoftext|>