<commit_before>var builder    = require('ltx'),
    Base       = require('xmpp-ftw/lib/base')
    
var Rpc = function() {}

Rpc.prototype = new Base()

Rpc.prototype.NS = 'jabber:iq:rpc'

Rpc.prototype._events = {
    'xmpp.rpc.perform': 'makeRequest'
}

Rpc.prototype.handles = function(stanza) {
    if (!stanza.is('iq') ||
        !stanza.getChild('query', this.NS)
    ) return false
        
    return true
}

Rpc.prototype.handle = function(stanza) {
    return false
}

Rpc.prototype.makeRequest = function(data, callback) {
    var self = this
    if (typeof callback !== 'function')
        return this._clientError('Missing callback', data)
    if (!data.to)
        return this._clientError('Missing \'to\' key', data, callback)
    if (!data.method)
        return this._clientError('Missing \'method\' key', data, callback)
    var stanza = new builder.Element(
        'iq',
        { type: 'set', id: this._getId(), to: data.to }
    ).c('query', { xmlns: this.NS})
     .c('methodCall').c('methodName').t(data.method)
     .up()
    
    if (data.params &&
        !this._addParams(data, stanza, callback)) return
           
    
    this.manager.trackId(stanza.root().attr('id'), function(stanza) {
        if ('error' == stanza.attrs.type)
            return callback(self._parseError(stanza))
        var results = []
        var params = stanza.getChild('query')
            .getChild('methodResponse')
            .getChild('params')
        if (params) self._handleParams(results, params)
        callback(null, results)
    })
    this.client.send(stanza)
}

Rpc.prototype._addParams = function(data, stanza, callback) {
    if ((typeof data.params !== 'object') ||
        (false === Array.isArray(data.params))) {
        this._clientError(
            '\'params\' must be an array', data, callback
        )
        return false
    }
    var params = stanza.c('params')
    var self = this
    var validParams = true
    data.params.some(function(param) {
        if (!param.type) {
            self._clientError('\'param\' must have \'type\' key', data, callback)
            validParams = false
            return false
        }
        if (!param.value) {
            self._clientError('\'param\' must have \'value\' key', data, callback)
            validParams = false
            return false
        }
        if (!self._addParam(param, params.c('param').c('value'))) {
            self._clientError('Parameter formatting error', data, callback)
            validParams = false
            return false
        }
    })
    return validParams
}

Rpc.prototype._addParam = function(param, stanza) {
    if (!param.type || !param.value) return false
    var type = stanza.c(param.type)
    var self = this
    switch (param.type) {
        case 'array':
            if ((typeof param.value !== 'object') ||
              (false === Array.isArray(param.value))) return false
            param.value.forEach(function(value) {
                self._addParam(value, type.c('data'))
            })
            break
        case 'struct':
            if ((typeof param.value !== 'object') ||
              (false === Array.isArray(param.value))) return false
            var validStruct = true
            param.value.some(function(value) {
                if (!value.name) {
                    validStruct = false
                    return false
                }
                var member = type.c('member')
                member.c('name').t(value.name)
                self._addParam(value, member.c('value'))
            })
            if (!validStruct) return false
            break
        case 'boolean':
            param.value = (param.value) ? '1' : '0'
        default:
            type.t(param.value)
    }
    return true
}

Rpc.prototype._handleParams = function(results, params) {
    params.getChildren('param').forEach(function(param) {
       var type = param.getChild('value').children[0]
       var result = { type: type.getName() }
       switch (type.getName()) {
           case 'struct':
               break
           case 'array':
               break
           case 'boolean':
               result.value = !!(type.getText())
               break
            case 'i4':
                result.value = parseInt(type.getText())
                break
            case 'int':
                result.value = parseInt(type.getText())
            case 'double':
                result.value = parseFloat(type.getText())
                break
            default:
               result.value = type.getText()
               break
                                 
       }
       results.push(result)
    })
}

module.exports = Rpc<commit_msg>Pull a method out for reuse in struct/array parsing<commit_after>var builder    = require('ltx'),
    Base       = require('xmpp-ftw/lib/base')
    
var Rpc = function() {}

Rpc.prototype = new Base()

Rpc.prototype.NS = 'jabber:iq:rpc'

Rpc.prototype._events = {
    'xmpp.rpc.perform': 'makeRequest'
}

Rpc.prototype.handles = function(stanza) {
    if (!stanza.is('iq') ||
        !stanza.getChild('query', this.NS)
    ) return false
        
    return true
}

Rpc.prototype.handle = function(stanza) {
    return false
}

Rpc.prototype.makeRequest = function(data, callback) {
    var self = this
    if (typeof callback !== 'function')
        return this._clientError('Missing callback', data)
    if (!data.to)
        return this._clientError('Missing \'to\' key', data, callback)
    if (!data.method)
        return this._clientError('Missing \'method\' key', data, callback)
    var stanza = new builder.Element(
        'iq',
        { type: 'set', id: this._getId(), to: data.to }
    ).c('query', { xmlns: this.NS})
     .c('methodCall').c('methodName').t(data.method)
     .up()
    
    if (data.params &&
        !this._addParams(data, stanza, callback)) return
           
    
    this.manager.trackId(stanza.root().attr('id'), function(stanza) {
        if ('error' == stanza.attrs.type)
            return callback(self._parseError(stanza))
        var results = []
        var params = stanza.getChild('query')
            .getChild('methodResponse')
            .getChild('params')
        if (params) self._handleParams(results, params)
        callback(null, results)
    })
    this.client.send(stanza)
}

Rpc.prototype._addParams = function(data, stanza, callback) {
    if ((typeof data.params !== 'object') ||
        (false === Array.isArray(data.params))) {
        this._clientError(
            '\'params\' must be an array', data, callback
        )
        return false
    }
    var params = stanza.c('params')
    var self = this
    var validParams = true
    data.params.some(function(param) {
        if (!param.type) {
            self._clientError('\'param\' must have \'type\' key', data, callback)
            validParams = false
            return false
        }
        if (!param.value) {
            self._clientError('\'param\' must have \'value\' key', data, callback)
            validParams = false
            return false
        }
        if (!self._addParam(param, params.c('param').c('value'))) {
            self._clientError('Parameter formatting error', data, callback)
            validParams = false
            return false
        }
    })
    return validParams
}

Rpc.prototype._addParam = function(param, stanza) {
    if (!param.type || !param.value) return false
    var type = stanza.c(param.type)
    var self = this
    switch (param.type) {
        case 'array':
            if ((typeof param.value !== 'object') ||
              (false === Array.isArray(param.value))) return false
            param.value.forEach(function(value) {
                self._addParam(value, type.c('data'))
            })
            break
        case 'struct':
            if ((typeof param.value !== 'object') ||
              (false === Array.isArray(param.value))) return false
            var validStruct = true
            param.value.some(function(value) {
                if (!value.name) {
                    validStruct = false
                    return false
                }
                var member = type.c('member')
                member.c('name').t(value.name)
                self._addParam(value, member.c('value'))
            })
            if (!validStruct) return false
            break
        case 'boolean':
            param.value = (param.value) ? '1' : '0'
        default:
            type.t(param.value)
    }
    return true
}

Rpc.prototype._handleParams = function(results, params) {
    var self = this
    params.getChildren('param').forEach(function(param) {
       results.push(self._parseParam(param))
    })
}

Rpc.prototype._parseParam = function(param) {
    var type = param.getChild('value').children[0]
   var result = { type: type.getName() }
   switch (type.getName()) {
       case 'struct':
           break
       case 'array':
           result.value = []
           break
       case 'boolean':
           result.value = !!(type.getText())
           break
        case 'i4':
            result.value = parseInt(type.getText())
            break
        case 'int':
            result.value = parseInt(type.getText())
        case 'double':
            result.value = parseFloat(type.getText())
            break
        default:
           result.value = type.getText()
           break
                             
   }
   return result
}

module.exports = Rpc
{'fraction_non_alphanumeric': 0.13569695051176534, 'fraction_numerical': 0.0008441489922971405, 'mean_word_length': 1.8208333333333333, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7603064', 'n_tokens_mistral': 2673, 'n_tokens_neox': 2645, 'n_words': 593}