UNPKG

reified

Version:

JS Binary Data API. Structs, arrays, bitfields, and numbers. Reify and Reference like nobody's business.

227 lines (210 loc) 9.11 kB
var util = require('util'); var utility = require('./utility'); var maxLength = utility.maxLength; var strlen = utility.strlen; var indent = utility.indent; var unique = utility.unique; var pad = utility.pad; var names = [ 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'bblack', 'bred', 'bgreen', 'byellow', 'bblue', 'bmagenta', 'bcyan', 'bwhite', ]; var colors = {}; var esc = '\33['; for (var i = 16; i-- > 0;) { colors[names[i]] = [esc+(i > 7 ? '1;':'')+(i%8+30)+'m', esc+(i > 7 ?'2;':'')+'39m'] } for (var i = 0; i++ < 8;) { names.push('bg'+names[i]); colors['bg'+names[i]] = [esc+(i+40)+'m', esc+'49m'] } for (var i = 0; i++ < 8;) { names.push('bg'+names[i+8]); colors['bg'+names[i+8]] = [esc+(i+100)+'m', esc+'25;49m'] } function color(text, name, brackets){ if (color.useColor) { if (name[0] === '#') name = hex(name); if (Array.isArray(name)) { name = ansi(name); return name[0]+text+name[1]; } else { return colors[name][0]+text+colors[name][1]; } } else { return brackets ? brackets[0]+text+brackets[1] : text; } } function hex(c){ c = '0x' + c.slice(1).replace(c.length > 4 ? c : /./g,'$&$&') | 0; return [c >> 16, c >> 8 & 255, c & 255]; } function ansi(c){ function d(x){ return (x / 255 * 5 + .5) | 0 } var index = d(c[0]) * 36 + d(c[1]) * 6 + d(c[2]) + 16; var start = c[3] === 'bg' ? 48 : 38; return [esc+start + ';5;'+index+'m', esc+(start+1)+'m']; } names.forEach(function(n){ color[n] = function(t, b){ return color(t, n, b) } }); function getSettings(){ var caller = getSettings.caller; while (caller = caller.caller) { if (caller.name === 'formatValue') { return caller.arguments[0] || {}; } } return {}; } module.exports = function(className, type){ return function(depth){ if (this && this.hasOwnProperty && this.hasOwnProperty('constructor')) { return '[Data Prototype]'; } var settings = getSettings(); color.useColor = !!(process && process.stdout._type === 'tty') || !!(settings.stylize ? settings.stylize.name === 'stylizeWithColor' : false); return inspectors[className][type](this, settings.showHidden, depth, color.useColor); } } function toplevelProto(name){ return color('['+name+' Prototype]', [255, 0, 150]); } var inspectors = { Type: { Opaque: function(object, showHidden, depth, useColor){ return color(object.name, [200,175,125], '‹›'); }, NumericType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('NumericType'); return color.bmagenta(object.name, '‹›') + color.bblue('('+object.bytes+'b)'); }, PointerType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('PointerType'); var label = object.displayName; var pointee = util.inspect(object.pointeeType, showHidden, depth-1, useColor); if (~pointee.indexOf(' ')) { pointee = pointee.slice(pointee.indexOf(' ')); } else { pointee = ''; } if (pointee.length > 60 || ~pointee.indexOf('\n')) { label += '\n '; pointee = indent(pointee); } return color.red(label, '‹›') + pointee; }, CharType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('CharType'); return color.bgreen('CharArray', '‹›') + color.bblue('('+object.bytes+'b)'); }, ArrayType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('ArrayType'); var label = color.byellow(object.name, '‹›') + color.bblue('('+object.bytes+'b)'); var memberType = util.inspect(object.memberType, showHidden, depth-1, useColor); if (~memberType.indexOf('\n') || strlen(memberType) > 60) { label += '\n'; memberType = indent(memberType).slice(2); } else { label + ' ' } return label+'[ '+object.count+' '+memberType+' ]'; }, StructType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('StructType'); var length = 0; var fields = unique(object.keys.concat(Object.keys(object))); fields = fields.map(function(field){ field = [color.bwhite(field), util.inspect(object.fields[field], showHidden, depth-1, useColor)]; length += strlen(field[0]) + strlen(field[1]); return field; }); var label = color.bcyan(object.name, '‹›') + color.bblue('('+object.bytes+'b)'); if (length > 60) { var max = maxLength(object.keys)+4; return label+'\n| '+fields.map(function(field){ return pad(color.bwhite(field[0]+':'), max) + field[1] }).join('\n| '); } else { return label+' { '+fields.map(function(field){ return color.bwhite(field[0]+': ')+field[1] }).join(' | ') + ' }'; } }, BitfieldType: function(object, showHidden, depth, useColor){ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return toplevelProto('BitfieldType'); var label = color.bgreen(object.name || 'Bitfield', '‹›') + color.bblue('('+object.bytes*8+'bit)'); if (Object(object.keys) !== object.keys) return util.inspect(object.keys); var flags = Object.keys(object.keys); if (!flags.length) { return label; } else { return label+'\n'+flags.map(function(flag){ return ' · '+pad(color.bgreen('0x'+object.keys[flag].toString(16)), Math.log(object.bytes+1.3)*10|0) + flag; }).join('\n'); } } }, Data: { Opaque: function(object, showHidden, depth, useColor){ return color(object.constructor.name, [200,175,125], '<>')+' ('+object.bytes+'b)'; }, NumericType: function(object, showHidden, depth, useColor){ if (!object.reify) return toplevelProto('NumericData'); return color.magenta(object.constructor.name, '<>')+' '+color.bmagenta(object.reify()); }, PointerType: function(object, showHidden, depth, useColor){ if (!object.reify) return toplevelProto('PointerData'); var label = color.red(object.constructor.displayName, '<>'); var address = ' ('+util.inspect(object.address)+')'; var pointee = util.inspect(object.pointee, showHidden, depth-1, useColor); if (pointee.length > 60 || ~pointee.indexOf('\n')) { pointee = indent(pointee.slice(pointee.indexOf('\n'))).slice(2); } else { pointee = ~pointee.indexOf(' ') ? pointee.slice(pointee.indexOf(' ')) : ''; } return label + address + pointee; }, CharType: function(object, showHidden, depth, useColor){ if (object.bytes === 1) { return color.green('Char', '<>')+' '+color.bgreen("'"+object.reify()+"'").replace(/\0/g,' '); } else { return color.green('Char'+object.length, '<>')+' '+color.bgreen("'"+object.reify().replace(/\0/g,' ')+"'"); } }, ArrayType: function(object, showHidden, depth, useColor){ if (!object.constructor.memberType) return toplevelProto('ArrayData'); var fields = util.inspect(object.map(function(item){ return item }), showHidden, depth-1, useColor); var sep = strlen(fields) > 60 ? '\n' : ' '; return color.yellow(object.constructor.name, '<>')+sep+fields; }, StructType: function(object, showHidden, depth, useColor){ if (!object.constructor.keys) return toplevelProto('StructData'); var length = 0; var fields = unique((object.constructor.keys).concat(Object.keys(object))); var fields = fields.map(function(field){ field = [field, util.inspect(object[field], showHidden, depth-1, useColor)]; length += strlen(field[0]) + strlen(field[1]); return field; }); var label = color.cyan(object.constructor.name, '<>'); if (length > 60) { var max = maxLength(object.constructor.keys)+4; return label + '\n| '+fields.map(function(field){ return pad(field[0]+': ', max) + field[1] }).join('\n| '); } else { return label+' { '+fields.map(function(field){ return field.join(': ') }).join(' | ') + ' }'; } }, BitfieldType: function(object, showHidden, depth, useColor){ if (!object.flags) return toplevelProto('BitfieldData'); var label = color.green(object.constructor.name || 'Bitfield', '‹›'); var flags = object.flags ? Object.keys(object.flags) : []; if (!flags.length) { return label + '['+object+']'; } else { var max = maxLength(object.flags)+4; return label +'\n · ' + flags.map(function(flag, index){ return pad(color.bwhite(flag+':'), max) + color.green(object[flag]); }).join(',\n · '); } } } }; function stripansi(str){ return str.replace(/\033\[(?:\d+;)*\d+m/g, '') }