This commit is the initial sync of all files from ruby/yarp into ruby/ruby. Notably, it does the following: * Sync all ruby/yarp/lib/ files to ruby/ruby/lib/yarp * Sync all ruby/yarp/src/ files to ruby/ruby/yarp/ * Sync all ruby/yarp/test/ files to ruby/ruby/test/yarp
186 lines
4.5 KiB
Ruby
186 lines
4.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module YARP
|
|
module Pack
|
|
%i[
|
|
SPACE
|
|
COMMENT
|
|
INTEGER
|
|
UTF8
|
|
BER
|
|
FLOAT
|
|
STRING_SPACE_PADDED
|
|
STRING_NULL_PADDED
|
|
STRING_NULL_TERMINATED
|
|
STRING_MSB
|
|
STRING_LSB
|
|
STRING_HEX_HIGH
|
|
STRING_HEX_LOW
|
|
STRING_UU
|
|
STRING_MIME
|
|
STRING_BASE64
|
|
STRING_FIXED
|
|
STRING_POINTER
|
|
MOVE
|
|
BACK
|
|
NULL
|
|
|
|
UNSIGNED
|
|
SIGNED
|
|
SIGNED_NA
|
|
|
|
AGNOSTIC_ENDIAN
|
|
LITTLE_ENDIAN
|
|
BIG_ENDIAN
|
|
NATIVE_ENDIAN
|
|
ENDIAN_NA
|
|
|
|
SIZE_SHORT
|
|
SIZE_INT
|
|
SIZE_LONG
|
|
SIZE_LONG_LONG
|
|
SIZE_8
|
|
SIZE_16
|
|
SIZE_32
|
|
SIZE_64
|
|
SIZE_P
|
|
SIZE_NA
|
|
|
|
LENGTH_FIXED
|
|
LENGTH_MAX
|
|
LENGTH_RELATIVE
|
|
LENGTH_NA
|
|
].each do |const|
|
|
const_set(const, const)
|
|
end
|
|
|
|
class Directive
|
|
attr_reader :version, :variant, :source, :type, :signed, :endian, :size, :length_type, :length
|
|
|
|
def initialize(version, variant, source, type, signed, endian, size, length_type, length)
|
|
@version = version
|
|
@variant = variant
|
|
@source = source
|
|
@type = type
|
|
@signed = signed
|
|
@endian = endian
|
|
@size = size
|
|
@length_type = length_type
|
|
@length = length
|
|
end
|
|
|
|
ENDIAN_DESCRIPTIONS = {
|
|
AGNOSTIC_ENDIAN: 'agnostic',
|
|
LITTLE_ENDIAN: 'little-endian (VAX)',
|
|
BIG_ENDIAN: 'big-endian (network)',
|
|
NATIVE_ENDIAN: 'native-endian',
|
|
ENDIAN_NA: 'n/a'
|
|
}
|
|
|
|
SIGNED_DESCRIPTIONS = {
|
|
UNSIGNED: 'unsigned',
|
|
SIGNED: 'signed',
|
|
SIGNED_NA: 'n/a'
|
|
}
|
|
|
|
SIZE_DESCRIPTIONS = {
|
|
SIZE_SHORT: 'short',
|
|
SIZE_INT: 'int-width',
|
|
SIZE_LONG: 'long',
|
|
SIZE_LONG_LONG: 'long long',
|
|
SIZE_8: '8-bit',
|
|
SIZE_16: '16-bit',
|
|
SIZE_32: '32-bit',
|
|
SIZE_64: '64-bit',
|
|
SIZE_P: 'pointer-width'
|
|
}
|
|
|
|
def describe
|
|
case type
|
|
when SPACE
|
|
'whitespace'
|
|
when COMMENT
|
|
'comment'
|
|
when INTEGER
|
|
if size == SIZE_8
|
|
base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} integer"
|
|
else
|
|
base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} integer"
|
|
end
|
|
case length_type
|
|
when LENGTH_FIXED
|
|
if length > 1
|
|
base + ", x#{length}"
|
|
else
|
|
base
|
|
end
|
|
when LENGTH_MAX
|
|
base + ', as many as possible'
|
|
end
|
|
when UTF8
|
|
'UTF-8 character'
|
|
when BER
|
|
'BER-compressed integer'
|
|
when FLOAT
|
|
"#{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} float"
|
|
when STRING_SPACE_PADDED
|
|
'arbitrary binary string (space padded)'
|
|
when STRING_NULL_PADDED
|
|
'arbitrary binary string (null padded, count is width)'
|
|
when STRING_NULL_TERMINATED
|
|
'arbitrary binary string (null padded, count is width), except that null is added with *'
|
|
when STRING_MSB
|
|
'bit string (MSB first)'
|
|
when STRING_LSB
|
|
'bit string (LSB first)'
|
|
when STRING_HEX_HIGH
|
|
'hex string (high nibble first)'
|
|
when STRING_HEX_LOW
|
|
'hex string (low nibble first)'
|
|
when STRING_UU
|
|
'UU-encoded string'
|
|
when STRING_MIME
|
|
'quoted printable, MIME encoding'
|
|
when STRING_BASE64
|
|
'base64 encoded string'
|
|
when STRING_FIXED
|
|
'pointer to a structure (fixed-length string)'
|
|
when STRING_POINTER
|
|
'pointer to a null-terminated string'
|
|
when MOVE
|
|
'move to absolute position'
|
|
when BACK
|
|
'back up a byte'
|
|
when NULL
|
|
'null byte'
|
|
else
|
|
raise
|
|
end
|
|
end
|
|
end
|
|
|
|
class Format
|
|
attr_reader :directives, :encoding
|
|
|
|
def initialize(directives, encoding)
|
|
@directives = directives
|
|
@encoding = encoding
|
|
end
|
|
|
|
def describe
|
|
source_width = directives.map { |d| d.source.inspect.length }.max
|
|
directive_lines = directives.map do |directive|
|
|
if directive.type == SPACE
|
|
source = directive.source.inspect
|
|
else
|
|
source = directive.source
|
|
end
|
|
" #{source.ljust(source_width)} #{directive.describe}"
|
|
end
|
|
|
|
(['Directives:'] + directive_lines + ['Encoding:', " #{encoding}"]).join("\n")
|
|
end
|
|
end
|
|
end
|
|
end
|