Class: Stupidedi::Reader::StreamReader
- Inherits:
-
Object
- Object
- Stupidedi::Reader::StreamReader
- Includes:
- Inspect
- Defined in:
- lib/stupidedi/reader/stream_reader.rb
Overview
The StreamReader is intended to scan the input for a valid ISA segment, after which the TokenReader class can be used to tokenize the remaining input.
Because X12 specifications have no bearing on what happens outside the
interchange envelope (from IEA
to ISA
), out-of-band data like blank
lines, human readable text, etc can occur between interchanges. This
reader is designed to deal with that problem.
Instance Attribute Summary collapse
-
#input
readonly
Returns the value of attribute input.
Instance Method Summary collapse
-
#consume_character ⇒ Either<StreamReader>
Skip a single character.
-
#empty? ⇒ Boolean
True if there is no remaining input.
-
#initialize(input) ⇒ StreamReader
constructor
A new instance of StreamReader.
-
#read_character ⇒ Either<Result<Character, StreamReader>>
Read a single character.
-
#read_segment ⇒ Either<Result<SegmentTok TokenReader>>
This method is unaware of subtle differences between interchange versions, so it really only tokenizes 16 elements, plus the element terminator and segment separators.
-
#stream? ⇒ Boolean
True.
Methods included from Inspect
Constructor Details
#initialize(input) ⇒ StreamReader
Returns a new instance of StreamReader.
21 22 23 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 21 def initialize(input) @input = input end |
Instance Attribute Details
#input (readonly)
Returns the value of attribute input.
19 20 21 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 19 def input @input end |
Instance Method Details
#consume_character ⇒ Either<StreamReader>
Skip a single character
49 50 51 52 53 54 55 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 49 def consume_character unless @input.empty? success(advance(1)) else failure("less than one character available") end end |
#empty? ⇒ Boolean
True if there is no remaining input
31 32 33 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 31 def empty? @input.empty? end |
#read_character ⇒ Either<Result<Character, StreamReader>>
Read a single character
38 39 40 41 42 43 44 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 38 def read_character unless @input.empty? result(@input.at(0), advance(1)) else failure("less than one character available") end end |
#read_segment ⇒ Either<Result<SegmentTok TokenReader>>
This method is unaware of subtle differences between interchange versions, so it really only tokenizes 16 elements, plus the element terminator and segment separators. It does not presume to understand the meaning of the elements, like the repetition separator or the component separator, because these are interchange version-dependent.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 64 def read_segment consume_isa.flatmap do |rest| # The character after "ISA" is defined to be the element separator rest.read_character.flatmap do |char, aR| separators = Separators.new(nil, nil, char, nil) remaining = success(TokenReader.new(aR.input, separators)) elements = [] # Read 15 simple elements into an array. Consume/discard the element # separator that follows each one. 15.times do remaining = remaining.flatmap(&:read_simple_element).flatmap do |e, eR| elements << e # Throw away the following element separator eR.consume_prefix(separators.element) end end # We have to assume the last (16th) element is fixed-length because # it is not terminated by an element separator. The {read_character} # method defined by TokenReader skips past control characters. remaining.flatmap do |w| w.read_character.flatmap do |isa16, cR| elements << SimpleElementTok.build(isa16, w.input, cR.input) # The character after the last element is defined to be the # segment terminator. The {read_character} method here, defined # by StreamReader, does not skip past control character, so the # separator could be a control character. cR.stream.read_character.flatmap do |char_, dR| if char_ == separators.element failure("element separator and segment terminator must be distinct", dR.input) else separators.segment = char_ token = SegmentTok.build(:ISA, elements, rest.input.position, dR.input.position) result(token, TokenReader.new(dR.input, separators)) end end end end end.or do |reason| # We read "ISA" but failed to tokenize the input that followed. This # was probably a random occurrence of the sequence "ISA", so we'll # skip past it and try again. # # @todo: We should log this as a warning, because we could otherwise # be silently discarding an entire interchange if the ISA segment # was bogus rest.read_segment end end end |
#stream? ⇒ Boolean
Returns true.
26 27 28 |
# File 'lib/stupidedi/reader/stream_reader.rb', line 26 def stream? true end |