rstruct¶ ↑
Rstruct is yet another ruby binary struct parser/builder framework based around a declarative syntax. Rstruct is designed with simplicity in mind and with a a slightly less active focus on performance.
The goal of Rstruct is is to provide a system that lets you define structures once, and use them in many ways as you see fit. Kind-of like… C structs in system/API header files.
The structure declaration syntax emulates C structures syntax, although Rstruct is not intended to be able to parse C structures from C header files. (however an addon could conceivably be built to do so with minimal fuss)
Multiple approaches to parsing and building are supported and more can be added with minimal fuss. For example, you might not wish to use the same interface to build or parse a structure on an IO object as you would a String object. In other words, it’s nice to have something that can work easily with streamed IO as well as buffers.
Rstruct was written because the authors wanted something comparable to C structures without having a strong need for extra ‘magic’ in parsing or building structures. While there exist numerous options in this space, they all seem to have suffered from a combination of performance and interface issues which limit their potential (and in some cases, spotty maintenance). Having, tried pretty much all of these alternatives (and even contributed to a few) in previous projects, the author still decided to write rstruct.
That said, the author does not claim Rstruct to be superior to any others, it’s just another approach. There are several other excellent binary structure library options out there such as BinData, BitStruct, or Ruckus. Some of these support variable length structures which, at this time, Rstruct does not. If you are looking for something to parse variable length data automatically, you are may be better off checking out one of these alterntives.
Installation¶ ↑
(sudo)? gem install rstruct
Synopsis¶ ↑
Here is a trivial example defining and packing a raw structure
require 'rstruct' extend Rstruct::ClassMethods example = struct(:example) { uint32 :a uint32 :b uint32 :c }.instance example.a = 0x41 example.b = 0x42 example.c = 0x43 raw = example.write() # => "A\x00\x00\x00B\x00\x00\x00C\x00\x00\x00" # on a little endian machine # => "\x00\x00\x00A\x00\x00\x00B\x00\x00\x00C" # on a big endian machine
Here is a fully functional Rstruct parser example using Apple’s FAT file structure.
# To compare the structs to their C counterparts, see: # http://fxr.watson.org/fxr/source/EXTERNAL_HEADERS/mach-o/fat.h?v=xnu-1228 require 'rstruct' extend Rstruct::ClassMethods FAT_MAGIC = 0xcafebabe FAT_CIGAM = 0xbebafeca struct(:fat_header) { uint32be :magic; # FAT_MAGIC uint32be :nfat_arch; # number of structs that follow } typedef :uint32be, :cpu_type_t typedef :uint32be, :cpu_subtype_t struct(:fat_arch) { cpu_type_t :cputype # cpu specifier (int) cpu_subtype_t :cpusubtype # machine specifier (int) uint32be :offset # file offset to this object file uint32be :size # size of this object file uint32be :align # alignment as a power of 2 } # a basic helper to produce textual dumps of fields def dump(struct) struct.each_pair.map {|k,v| " #{k} = 0x%0.8x" % v} end File.open('ls.from_a_mac','r') do |f| # Read and dump the FAT header from the file head = get_type(:fat_header).read(f) puts "FAT header:", dump(head) puts # Read and dump the architectures after the header fat_arch = get_type(:fat_arch) (head.nfat_arch).times do |i| arch = fat_arch.read(f) # note, it reads to a new object on each arch puts " Architecture #{i}:" puts " " << dump(arch).join("\n ") puts end end
.. which should produce output something like the following:
FAT header: magic = 0xcafebabe nfat_arch = 0x00000002 Architecture 0: cputype = 0x01000007 cpusubtype = 0x80000003 offset = 0x00001000 size = 0x00009ab0 align = 0x0000000c Architecture 1: cputype = 0x00000007 cpusubtype = 0x00000003 offset = 0x0000b000 size = 0x00008b30 align = 0x0000000c
Please refer to rdoc, the samples/ directory, and unit tests for more information.
Copyright¶ ↑
Copyright © 2011 Eric Monti. See LICENSE.txt for further details.