UNPKG

cbor

Version:

Encode and parse CBOR documents.

177 lines (150 loc) 5.2 kB
# jslint node: true stream = require 'stream' Evented = require './evented' BufferStream = require '../lib/BufferStream' Simple = require '../lib/simple' utils = require '../lib/utils' # Output the diagnostic format from a set of CBOR bytes. Either pipe another # stream into an instance of this class, or pass a string, Buffer, or # BufferStream into `options.input`, assign callbacks, then call `start()`. # # @event end() Done processing the input # @event error(er) An error has occured # @param er [Error] # @event complete(obj) A complete CBOR object has been read from the stream # There is no need to hook this event usually, it's mostly for testing. # @param obj [Stream] the stream that was written to # @todo Consider turning this into a Transform stream module.exports = class Diagnose extends stream.Writable # Create a Diagnose. # @param options [Object] options for creation # @option options separator [String] output between detected objects (default: '\n') # @option options output [Writable] where the output should go (default: process.stdout) # @option options input [Buffer,String,BufferStream] optional input # @option options encoding [String] encoding of a String `input` (default: 'hex') # @option options offset [Integer] *byte* offset into the input from which to start constructor: (options={}) -> super() @options = utils.extend separator: '\n' output: process.stdout streamErrors: false , options @on 'finish', ()-> @parser.end() @parser = new Evented @options @parser.on 'value', @_on_value @parser.on 'array-start', @_on_array_start @parser.on 'array-stop', @_on_array_stop @parser.on 'map-start', @_on_map_start @parser.on 'map-stop', @_on_map_stop @parser.on 'stream-start', @_on_stream_start @parser.on 'stream-stop', @_on_stream_stop @parser.on 'end', @_on_end @parser.on 'error', @_on_error # All events have been hooked, start parsing the input. # @note This MUST NOT be called if you're piping a Readable stream in. start: ()-> @parser.start() # Convenience function to print to (e.g.) stdout. # @param input [Buffer,String,BufferStream] the CBOR bytes to write # @param encoding [String] encoding if `input` is a string (default: 'hex') # @param output [Writable] Writable stream to output diagnosis info into # (default: process.stdout) # @param done [function()] @diagnose: (input, encoding='hex', output=process.stdout, done)-> if !input? throw new Error 'input required' d = new Diagnose input: input encoding: encoding output: output if done d.on 'end', done d.start() # @nodoc _stream_val: (val) -> @options.output.write switch when val == undefined then 'undefined' when val == null then 'nil' when typeof(val) == 'number' if isNaN(val) then "NaN" else if !isFinite(val) if val < 0 then '-Infinity' else 'Infinity' else JSON.stringify(val) when Simple.isSimple(val) then val.toString() when Buffer.isBuffer(val) then "h'" + val.toString('hex') + "'" else JSON.stringify(val) # @nodoc _on_error: (er) => if @options.streamErrors @options.output.write er.toString() @emit 'error', er # @nodoc _fore: (kind) -> switch kind when 'array', 'key', 'stream' then @options.output.write ', ' # @nodoc _aft: (kind) -> switch kind when 'key', 'key-first' then @options.output.write ': ' when null if @options.separator? @options.output.write @options.separator @emit 'complete', @options.output # @nodoc _on_value: (val,tags,kind)=> @_fore kind if tags? and tags.length @options.output.write "#{t}(" for t in tags @_stream_val val if tags? and tags.length @options.output.write ")" for t in tags @_aft kind # @nodoc _on_array_start: (count,tags,kind)=> @_fore kind if tags? and tags.length @options.output.write "#{t}(" for t in tags @options.output.write "[" if count == -1 @options.output.write "_ " # @nodoc _on_array_stop: (count,tags,kind)=> @options.output.write "]" if tags? and tags.length @options.output.write ")" for t in tags @_aft kind # @nodoc _on_map_start: (count,tags,kind)=> @_fore kind if tags? and tags.length @options.output.write "#{t}(" for t in tags @options.output.write "{" if count == -1 @options.output.write "_ " # @nodoc _on_map_stop: (count,tags,kind)=> @options.output.write "}" if tags? and tags.length @options.output.write ")" for t in tags @_aft kind # @nodoc _on_stream_start: (mt,tags,kind)=> @_fore kind if tags? and tags.length @options.output.write "#{t}(" for t in tags @options.output.write "(_ " # @nodoc _on_stream_stop: (count,mt,tags,kind)=> @options.output.write ")" if tags? and tags.length @options.output.write ")" for t in tags @_aft kind # @nodoc _on_end: ()=> @emit 'end' # @nodoc _write: (chunk, enc, next)-> @parser.write chunk, enc, next