function serialize(mixed) {
    var tmp = null;
    
    switch(typeof mixed) {
        case 'boolean':
            if(mixed) {
                return 'b:1;';
            } else {
                return 'b:0;';
            }
            break;
        case 'object':
            var length = 0;
            var i = null;
            
            tmp = '';
            for(i in mixed) {
                tmp += serialize(i);
                tmp += serialize(mixed[i]);
                
                length++;
            }
            
            return 'a:' + length + ':{' + tmp + '}';
            break;
        case 'number':
            tmp = Math.round(mixed);
            
            if(tmp == mixed) {
                return 'i:' + mixed + ';';
            } else {
                return 'd:' + mixed + ';';
            }
            break;
        case 'string':
            if(isNaN(mixed) || mixed.substr(0, 1) == '0') {
                return 's:' + mixed.length + ':"' + mixed + '";';
            } else {
                return serialize(Number(mixed));
            }
            break;
    }
}

function unserialize(string) {
    switch(string.substr(0, 1)) {
        // array
        case 'a':
//        case 'O':
            var length = string.substring(string.indexOf(':') + 1, string.indexOf(':', string.indexOf(':') + 1));
            var tmp = new Array();
            string = string.substr((string.indexOf('{') + 1));
            var key = null;
            var value = null;
            var sub_length = null;
            var str_tmp = null;
            
            for(var i = 0; i < length; i++) {
                // extract key
                switch(string.substr(0, 1)) {
                    case 'i':
                        sub_length = string.indexOf(';') + 1;
                        key = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        break;
                    case 's':
                        str_tmp = string.substring(string.indexOf(':') + 1, string.indexOf(':', string.indexOf(':') + 1));
                        sub_length = parseInt(str_tmp.length) + parseInt(str_tmp) + 6;
                        key = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        break;
                }
                
                // extract value
                switch(string.substr(0, 1)) {
                    case 'a':
//                    case 'O':
                        var j = 1;
                        var level = 0;
                        
                        while(string.substr(j, 1) != '}' || level != 0) {
                            switch(string.substr(j, 1)) {
                                case 's':
                                    str_tmp = string.substring(j + 2, string.indexOf(':', j + 2));
                                    sub_length = parseInt(str_tmp.length) + parseInt(str_tmp) + 6;
                                    j = j + sub_length;
                                    break;
                                case 'a':
//                                case 'O':
                                    level++;
                                    j++;
                                    break;
                                case '}':
                                    level--;
                                    j++;
                                    break;
                                default:
                                    j++;
                                    break;
                            }
                        }
                        
                        sub_length = j + 1;
                        value = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        
                        tmp[key] = value;
                        break;
                    case 'b':
                        sub_length = 4;
                        value = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        
                        tmp[key] = value;
                        break;
                    case 'd':
                        sub_length = string.indexOf(';') + 1;
                        value = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        
                        tmp[key] = parseFloat(value);
                        break;
                    case 'i':
                        sub_length = string.indexOf(';') + 1;
                        value = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        
                        tmp[key] = parseInt(value);
                        break;
                    case 'N':
                        string = string.substr(2);
                        
                        tmp[key] = null;
                        break;
                    case 's':
                        str_tmp = string.substring(string.indexOf(':') + 1, string.indexOf(':', string.indexOf(':') + 1));
                        sub_length = parseInt(str_tmp.length) + parseInt(str_tmp) + 6;
                        value = unserialize(string.substr(0, sub_length));
                        string = string.substr(sub_length);
                        
                        tmp[key] = value;
                        break;
                }
            }
            return tmp;
            break;
        // boolean
        case 'b':
            if(string.charAt(2) == '1') {
                return true;
            } else if(string.charAt(2) == '0') {
                return false;
            }
            break;
        // float
        case 'd':
            return parseFloat(string.substring(2, string.indexOf(';')));
            break;
        // integer
        case 'i':
            return parseInt(string.substring(2, string.indexOf(';')));
            break;
        // null
        case 'N':
            return null;
            break;
        // string
        case 's':
            var length = string.substring(string.indexOf(':') + 1, string.indexOf(':', string.indexOf(':') + 1));
            return string.substr(string.indexOf('"') + 1, length);
            break;
        default:
            return '__error__';
            break;
    }
}
