1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 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
|
require "json"
require_relative "byte_array"
require_relative "numeric_array"
require_relative "cigar"
require_relative "error"
require_relative "field_array"
#
# Methods to parse the string representations of the GFA fields
# @api private
#
module RGFA::FieldParser
# Parse a string representation of a GFA field value
# @raise [RGFA::Error] if the value is not valid
# @param datatype [RGFA::Line::FIELD_DATATYPE]
def parse_gfa_field(datatype: nil,
validate_strings: true,
fieldname: nil,
frozen: false)
case datatype
when :cmt
return self
when :A, :Z, :seq
validate_gfa_field!(datatype, fieldname: fieldname) if validate_strings
self.freeze if frozen
return self
when :lbl
validate_segment_name!
validate_gfa_field!(datatype, fieldname: fieldname) if validate_strings
return to_sym.freeze
when :orn
validate_gfa_field!(datatype, fieldname: fieldname) if validate_strings
return to_sym.freeze
when :i
return Integer(self)
when :pos
value = Integer(self)
raise RGFA::FieldParser::FormatError if value < 0
return value
when :f
return Float(self)
when :H
value = to_byte_array
value.freeze if frozen
return value
when :B
value = to_numeric_array
value.freeze if frozen
return value
when :J
value = JSON.parse(self)
# RGFA convention for array of fields
if value.kind_of?(Array) and value.rgfa_field_array?
value = value.to_rgfa_field_array
end
# no need to freeze, as any Hash or Array will be valid
return value
when :cig
value = to_cigar
value.freeze if frozen
return value
when :cgs
value = split(",").map do |c|
c = c.to_cigar
c.freeze if frozen
c
end
value.freeze if frozen
return value
when :lbs
value = split(",").map do |l|
o = l[-1].to_sym
l = l[0..-2]
if validate_strings
l.validate_gfa_field!(:lbl, fieldname: "#{fieldname} "+
"(entire field content: #{self})" )
end
os = [l.to_sym, o].to_oriented_segment
os.freeze if frozen
os
end
value.freeze if frozen
return value
else
raise RGFA::FieldParser::UnknownDatatypeError,
"Datatype unknown: #{datatype.inspect}"
end
end
# Parses an optional field in the form tagname:datatype:value
# and parses the value according to the datatype
# @raise [RGFA::FieldParser::FormatError] if the string does not represent
# an optional field
# @return [Array(Symbol, RGFA::Line::FIELD_DATATYPE, String)]
# the parsed content of the field
def parse_gfa_optfield
if self =~ /^([A-Za-z][A-Za-z0-9]):([AifZJHB]):(.+)$/
return $1.to_sym, $2.to_sym, $3
else
raise RGFA::FieldParser::FormatError,
"Expected optional field, found: #{self.inspect}"
end
end
end
# Error raised if the field content has an invalid format
class RGFA::FieldParser::FormatError < RGFA::Error; end
# Error raised if an unknown datatype symbol is used
class RGFA::FieldParser::UnknownDatatypeError < RGFA::Error; end
class String
include RGFA::FieldParser
end
|