kaitai-struct 0.7 → 0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f864fb7a549cb0ffb83d39e1e1a8f3e58feba59b
4
- data.tar.gz: f398b795f794ac82e4ab78838dc4f7eb1f773cbe
2
+ SHA256:
3
+ metadata.gz: cbdd2b873476556b609d64f78e10c3ef35ea5ede048ac5ee57a03a24f523bfac
4
+ data.tar.gz: db41f46711b11efcf12a982e282181ae20d25831f408b7a3e7e668791f14701b
5
5
  SHA512:
6
- metadata.gz: 9682c42a2b4636b58255f6b0ed111ba399e182e34269515707471206ae217bd72e26c336749b7737a3c5fa6a9b48eb640cfe0a21bfb4db464420797ef3dce7fb
7
- data.tar.gz: 1d6cf8627185ada694d03f2303259f21341f34e4091197907bcc9397b703dc7ba232c7fa36d5bd1244f707ba0dcb2ce1a7a690df65fa8a8fe599ffd5814d6510
6
+ metadata.gz: ea4b2780d4efa7c645175957059073f6506ee5e39d2525b62f7a5de41816d0115dde2980948ab47e8994b1a7fc97cb94e8fab7692882244fc7d9b58b18b3e8b3
7
+ data.tar.gz: 99cec16629be56c07b1df24f4a091fbffdd6240341dc0130ef6a5d04195a91c37d6238c4991ba3782667514cf25ae7746aa2fdd3aa307c34352c0dd0698ea4c9
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2015-2022 Kaitai Project
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Kaitai Struct: runtime library for Ruby
2
2
 
3
+ [![Gem version](https://img.shields.io/gem/v/kaitai-struct)](https://rubygems.org/gems/kaitai-struct/)
4
+ [![Gem downloads](https://img.shields.io/gem/dt/kaitai-struct)](https://rubygems.org/gems/kaitai-struct/#:~:text=TOTAL%20DOWNLOADS)
5
+
3
6
  This library implements Kaitai Struct API for Ruby.
4
7
 
5
8
  Kaitai Struct is a declarative language used for describe various binary
@@ -35,30 +38,7 @@ to install this runtime library.
35
38
 
36
39
  ### Manually
37
40
 
38
- This library is intentionally kept as very simple, one-file `.rb`
39
- file. One can just copy it to your project from this
40
- repository. Usually you won't `require` it directly, it will be loaded
41
- by Ruby source code generate by Kaitai Struct compiler.
42
-
43
- ## Licensing
44
-
45
- Copyright 2015-2017 Kaitai Project: MIT license
46
-
47
- Permission is hereby granted, free of charge, to any person obtaining
48
- a copy of this software and associated documentation files (the
49
- "Software"), to deal in the Software without restriction, including
50
- without limitation the rights to use, copy, modify, merge, publish,
51
- distribute, sublicense, and/or sell copies of the Software, and to
52
- permit persons to whom the Software is furnished to do so, subject to
53
- the following conditions:
54
-
55
- The above copyright notice and this permission notice shall be
56
- included in all copies or substantial portions of the Software.
57
-
58
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
59
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
61
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
62
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
63
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
64
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
+ This library is intentionally kept as very simple, one `.rb` file.
42
+ You can just copy it to your project from [this repository](https://github.com/kaitai-io/kaitai_struct_ruby_runtime).
43
+ Usually you won't `require` it directly, it will be loaded
44
+ by Ruby source code generated by Kaitai Struct compiler.
@@ -3,7 +3,7 @@ require 'stringio'
3
3
  module Kaitai
4
4
  module Struct
5
5
 
6
- VERSION = '0.7'
6
+ VERSION = '0.10'
7
7
 
8
8
  ##
9
9
  # Common base class for all structured generated by Kaitai Struct.
@@ -60,9 +60,8 @@ end
60
60
 
61
61
  ##
62
62
  # Kaitai::Struct::Stream is an implementation of
63
- # {https://github.com/kaitai-io/kaitai_struct/wiki/Kaitai-Struct-stream-API
64
- # Kaitai Struct stream API} for Ruby. It's implemented as a wrapper
65
- # for generic IO objects.
63
+ # {Kaitai Stream API}[https://doc.kaitai.io/stream_api.html] for Ruby.
64
+ # It's implemented as a wrapper for generic IO objects.
66
65
  #
67
66
  # It provides a wide variety of simple methods to read (parse) binary
68
67
  # representations of primitive types, such as integer and floating
@@ -77,6 +76,9 @@ end
77
76
  # and API to do the actual parsing job.
78
77
  class Stream
79
78
  ##
79
+ # Unused since Kaitai Struct Compiler v0.9+ - compatibility with
80
+ # older versions.
81
+ #
80
82
  # Exception class for an error that occurs when some fixed content
81
83
  # was expected to appear, but actual data read was different.
82
84
  class UnexpectedDataError < Exception
@@ -87,6 +89,7 @@ class Stream
87
89
  end
88
90
  end
89
91
 
92
+
90
93
  ##
91
94
  # Constructs new Kaitai Stream object.
92
95
  # @param arg [String, IO] if String, it will be used as byte array to read data from;
@@ -110,6 +113,12 @@ class Stream
110
113
  self.new(File.open(filename, 'rb:ASCII-8BIT'))
111
114
  end
112
115
 
116
+ ##
117
+ # Closes underlying IO object.
118
+ def close
119
+ @_io.close
120
+ end
121
+
113
122
  # Test endianness of the platform
114
123
  @@big_endian = [0x0102].pack('s') == [0x0102].pack('n')
115
124
 
@@ -118,7 +127,7 @@ class Stream
118
127
  ##
119
128
  # Check if stream pointer is at the end of stream.
120
129
  # @return [true, false] true if we are located at the end of the stream
121
- def eof?; @_io.eof?; end
130
+ def eof?; @_io.eof? and @bits_left == 0; end
122
131
 
123
132
  ##
124
133
  # Set stream pointer to designated position.
@@ -282,36 +291,72 @@ class Stream
282
291
  @bits = 0
283
292
  end
284
293
 
285
- def read_bits_int(n)
294
+ def read_bits_int_be(n)
295
+ res = 0
296
+
286
297
  bits_needed = n - @bits_left
298
+ @bits_left = -bits_needed % 8
299
+
287
300
  if bits_needed > 0
288
301
  # 1 bit => 1 byte
289
302
  # 8 bits => 1 byte
290
303
  # 9 bits => 2 bytes
291
- bytes_needed = ((bits_needed - 1) / 8) + 1
304
+ bytes_needed = ((bits_needed - 1) / 8) + 1 # `ceil(bits_needed / 8)`
292
305
  buf = read_bytes(bytes_needed)
293
306
  buf.each_byte { |byte|
294
- @bits <<= 8
295
- @bits |= byte
296
- @bits_left += 8
307
+ res = res << 8 | byte
297
308
  }
309
+
310
+ new_bits = res
311
+ res = res >> @bits_left | @bits << bits_needed
312
+ @bits = new_bits # will be masked at the end of the function
313
+ else
314
+ res = @bits >> -bits_needed # shift unneeded bits out
298
315
  end
299
316
 
300
- # raw mask with required number of 1s, starting from lowest bit
301
- mask = (1 << n) - 1
302
- # shift mask to align with highest bits available in @bits
303
- shift_bits = @bits_left - n
304
- mask <<= shift_bits
305
- # derive reading result
306
- res = (@bits & mask) >> shift_bits
307
- # clear top bits that we've just read => AND with 1s
308
- @bits_left -= n
309
- mask = (1 << @bits_left) - 1
317
+ mask = (1 << @bits_left) - 1 # `@bits_left` is in range 0..7
310
318
  @bits &= mask
311
319
 
312
320
  res
313
321
  end
314
322
 
323
+ # Unused since Kaitai Struct Compiler v0.9+ - compatibility with
324
+ # older versions.
325
+ def read_bits_int(n)
326
+ read_bits_int_be(n)
327
+ end
328
+
329
+ def read_bits_int_le(n)
330
+ res = 0
331
+ bits_needed = n - @bits_left
332
+
333
+ if bits_needed > 0 then
334
+ # 1 bit => 1 byte
335
+ # 8 bits => 1 byte
336
+ # 9 bits => 2 bytes
337
+ bytes_needed = ((bits_needed - 1) / 8) + 1 # `ceil(bits_needed / 8)`
338
+ buf = read_bytes(bytes_needed)
339
+ i = 0
340
+ buf.each_byte { |byte|
341
+ res |= byte << (i * 8)
342
+ i += 1
343
+ }
344
+
345
+ new_bits = res >> bits_needed
346
+ res = res << @bits_left | @bits
347
+ @bits = new_bits
348
+ else
349
+ res = @bits
350
+ @bits >>= n
351
+ end
352
+
353
+ @bits_left = -bits_needed % 8
354
+
355
+ mask = (1 << n) - 1 # no problem with this in Ruby (arbitrary precision integers)
356
+ res &= mask
357
+ return res
358
+ end
359
+
315
360
  # @!endgroup
316
361
 
317
362
  # @!group Byte arrays
@@ -361,6 +406,9 @@ class Stream
361
406
  end
362
407
 
363
408
  ##
409
+ # Unused since Kaitai Struct Compiler v0.9+ - compatibility with
410
+ # older versions.
411
+ #
364
412
  # Reads next len bytes from the stream and ensures that they match
365
413
  # expected fixed byte array. If they differ, throws a
366
414
  # {UnexpectedDataError} runtime exception.
@@ -377,9 +425,10 @@ class Stream
377
425
 
378
426
  def self.bytes_strip_right(bytes, pad_byte)
379
427
  new_len = bytes.length
380
- while bytes.getbyte(new_len - 1) == pad_byte
428
+ while new_len > 0 and bytes.getbyte(new_len - 1) == pad_byte
381
429
  new_len -= 1
382
430
  end
431
+
383
432
  bytes[0, new_len]
384
433
  end
385
434
 
@@ -485,8 +534,124 @@ class Stream
485
534
  (x & ~mask) - (x & mask)
486
535
  end
487
536
 
488
- def self.format_hex(arr)
489
- arr.unpack('H*')[0].gsub(/(..)/, '\1 ').chop
537
+ def self.format_hex(bytes)
538
+ bytes.unpack('H*')[0].gsub(/(..)/, '\1 ').chop
539
+ end
540
+
541
+ ###
542
+ # Guess if the given args are most likely byte arrays.
543
+ # <p>
544
+ # There's no way to know for sure, but {@code Encoding::ASCII_8BIT} is a special encoding that is
545
+ # usually used for a byte array(/string), not a character string. For those reasons, that encoding
546
+ # is NOT planned to be allowed for human readable texts by KS in general as well.
547
+ # </p>
548
+ # @param args [...] Something to check.
549
+ # @see <a href="https://ruby-doc.org/core-3.0.0/Encoding.html">Encoding</a>
550
+ # @see <a href="https://github.com/kaitai-io/kaitai_struct/issues/116">List of supported encodings</a>
551
+ #
552
+ def self.is_byte_array?(*args)
553
+ args.all? { |arg| arg.is_a?(String) and (arg.encoding == Encoding::ASCII_8BIT) }
554
+ end
555
+
556
+ def self.inspect_values(*args)
557
+ reprs = args.map { |arg|
558
+ if Stream.is_byte_array?(arg)
559
+ "[#{Stream.format_hex(arg)}]"
560
+ else
561
+ arg.inspect
562
+ end
563
+ }
564
+ reprs.length == 1 ? reprs[0] : reprs
565
+ end
566
+ end
567
+
568
+ ##
569
+ # Common ancestor for all error originating from Kaitai Struct usage.
570
+ # Stores KSY source path, pointing to an element supposedly guilty of
571
+ # an error.
572
+ class KaitaiStructError < Exception
573
+ def initialize(msg, src_path)
574
+ super("#{src_path}: #{msg}")
575
+ @src_path = src_path
576
+ end
577
+ end
578
+
579
+ ##
580
+ # Error that occurs when default endianness should be decided with
581
+ # a switch, but nothing matches (although using endianness expression
582
+ # implies that there should be some positive result).
583
+ class UndecidedEndiannessError < KaitaiStructError
584
+ def initialize(src_path)
585
+ super("unable to decide on endianness for a type", src_path)
586
+ end
587
+ end
588
+
589
+ ##
590
+ # Common ancestor for all validation failures. Stores pointer to
591
+ # KaitaiStream IO object which was involved in an error.
592
+ class ValidationFailedError < KaitaiStructError
593
+ def initialize(msg, io, src_path)
594
+ super("at pos #{io.pos}: validation failed: #{msg}", src_path)
595
+ @io = io
596
+ end
597
+ end
598
+
599
+ ##
600
+ # Signals validation failure: we required "actual" value to be equal to
601
+ # "expected", but it turned out that it's not.
602
+ class ValidationNotEqualError < ValidationFailedError
603
+ def initialize(expected, actual, io, src_path)
604
+ expected_repr, actual_repr = Stream.inspect_values(expected, actual)
605
+ super("not equal, expected #{expected_repr}, but got #{actual_repr}", io, src_path)
606
+
607
+ @expected = expected
608
+ @actual = actual
609
+ end
610
+ end
611
+
612
+ ##
613
+ # Signals validation failure: we required "actual" value to be greater
614
+ # than or equal to "min", but it turned out that it's not.
615
+ class ValidationLessThanError < ValidationFailedError
616
+ def initialize(min, actual, io, src_path)
617
+ min_repr, actual_repr = Stream.inspect_values(min, actual)
618
+ super("not in range, min #{min_repr}, but got #{actual_repr}", io, src_path)
619
+ @min = min
620
+ @actual = actual
621
+ end
622
+ end
623
+
624
+ ##
625
+ # Signals validation failure: we required "actual" value to be less
626
+ # than or equal to "max", but it turned out that it's not.
627
+ class ValidationGreaterThanError < ValidationFailedError
628
+ def initialize(max, actual, io, src_path)
629
+ max_repr, actual_repr = Stream.inspect_values(max, actual)
630
+ super("not in range, max #{max_repr}, but got #{actual_repr}", io, src_path)
631
+ @max = max
632
+ @actual = actual
633
+ end
634
+ end
635
+
636
+ ##
637
+ # Signals validation failure: we required "actual" value to be any of
638
+ # the given list, but it turned out that it's not.
639
+ class ValidationNotAnyOfError < ValidationFailedError
640
+ def initialize(actual, io, src_path)
641
+ actual_repr = Stream.inspect_values(actual)
642
+ super("not any of the list, got #{actual_repr}", io, src_path)
643
+ @actual = actual
644
+ end
645
+ end
646
+
647
+ ##
648
+ # Signals validation failure: we required "actual" value to match
649
+ # the expression, but it turned out that it doesn't.
650
+ class ValidationExprError < ValidationFailedError
651
+ def initialize(actual, io, src_path)
652
+ actual_repr = Stream.inspect_values(actual)
653
+ super("not matching the expression, got #{actual_repr}", io, src_path)
654
+ @actual = actual
490
655
  end
491
656
  end
492
657
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kaitai-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '0.10'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikhail Yakshin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-22 00:00:00.000000000 Z
11
+ date: 2022-07-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Kaitai Struct is a declarative language used for describe various binary data structures, laid out in files or in memory: i.e. binary file formats, network stream packet formats, etc.
@@ -21,15 +21,17 @@ executables: []
21
21
  extensions: []
22
22
  extra_rdoc_files: []
23
23
  files:
24
- - ".gitignore"
24
+ - LICENSE
25
25
  - README.md
26
- - kaitai-struct.gemspec
27
26
  - lib/kaitai/struct/struct.rb
28
27
  homepage: http://kaitai.io
29
28
  licenses:
30
29
  - MIT
31
- metadata: {}
32
- post_install_message:
30
+ metadata:
31
+ bug_tracker_uri: https://github.com/kaitai-io/kaitai_struct_ruby_runtime/issues
32
+ homepage_uri: http://kaitai.io
33
+ source_code_uri: https://github.com/kaitai-io/kaitai_struct_ruby_runtime
34
+ post_install_message:
33
35
  rdoc_options: []
34
36
  require_paths:
35
37
  - lib
@@ -44,9 +46,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
44
46
  - !ruby/object:Gem::Version
45
47
  version: '0'
46
48
  requirements: []
47
- rubyforge_project:
48
- rubygems_version: 2.5.2
49
- signing_key:
49
+ rubygems_version: 3.3.17
50
+ signing_key:
50
51
  specification_version: 4
51
52
  summary: 'Kaitai Struct: runtime library for Ruby'
52
53
  test_files: []
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- *.gem
@@ -1,31 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- require File.expand_path("../lib/kaitai/struct/struct", __FILE__)
4
- require 'date'
5
-
6
- Gem::Specification.new { |s|
7
- s.name = 'kaitai-struct'
8
- s.version = Kaitai::Struct::VERSION
9
- s.date = Date.today.to_s
10
-
11
- s.authors = ['Mikhail Yakshin']
12
- s.email = 'greycat@kaitai.io'
13
-
14
- s.homepage = 'http://kaitai.io'
15
- s.summary = 'Kaitai Struct: runtime library for Ruby'
16
- s.license = 'MIT'
17
- s.description = <<-EOF
18
- Kaitai Struct is a declarative language used for describe various binary data structures, laid out in files or in memory: i.e. binary file formats, network stream packet formats, etc.
19
-
20
- The main idea is that a particular format is described in Kaitai Struct language (.ksy file) and then can be compiled with ksc into source files in one of the supported programming languages. These modules will include a generated code for a parser that can read described data structure from a file / stream and give access to it in a nice, easy-to-comprehend API.
21
-
22
- This package provides small runtime library used by code generated by Kaitai Struct compiler.
23
- EOF
24
-
25
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
26
- s.require_paths = ['lib']
27
-
28
- s.files = `git ls-files`.split("\n")
29
- s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
30
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
31
- }