packed_struct 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README.md +33 -0
- data/lib/packed_struct.rb +25 -0
- data/lib/packed_struct/directive.rb +355 -0
- data/lib/packed_struct/package.rb +127 -0
- data/lib/packed_struct/version.rb +5 -0
- metadata +54 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Jeremy Rodi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# PackedStruct
|
2
|
+
|
3
|
+
`PackedStruct` is a way to define packing strings (see [`Array#pack`](http://ruby-doc.org/core-2.0/Array.html#method-i-pack)).
|
4
|
+
It was created after @charliesome suggested [a format](https://gist.github.com/redjazz96/6dda0554f62e4f77253a) for defining these strings, but never finished it.
|
5
|
+
|
6
|
+
The basic way of defining a packed struct is such:
|
7
|
+
|
8
|
+
```Ruby
|
9
|
+
class RconPacket
|
10
|
+
include PackedStruct
|
11
|
+
struct_layout :packet do
|
12
|
+
little_endian signed size[32] # defaults to a number of size 32.
|
13
|
+
little_endian signed id[32]
|
14
|
+
little_endian signed type[32]
|
15
|
+
string body[size]
|
16
|
+
null
|
17
|
+
end
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
This can be accessed as:
|
22
|
+
|
23
|
+
```Ruby
|
24
|
+
RconPacket.structs[:packet].pack(size: 11, id: 1, type: 0, body: "hello world")
|
25
|
+
# => "\v\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00hello world\x00"
|
26
|
+
```
|
27
|
+
|
28
|
+
You can also unpack strings.
|
29
|
+
|
30
|
+
```Ruby
|
31
|
+
RconPacket.structs[:packet].unpack("\v\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00hello world\x00")
|
32
|
+
# => {:size => 11, :id => 1, :type => 0, :body => "hello world"}
|
33
|
+
```
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'packed_struct/package'
|
2
|
+
require 'packed_struct/directive'
|
3
|
+
|
4
|
+
module PackedStruct
|
5
|
+
|
6
|
+
def structs
|
7
|
+
@structs ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def struct_layout(name = nil, &block)
|
11
|
+
structs[name] = Package.new
|
12
|
+
structs[name].instance_exec &block
|
13
|
+
|
14
|
+
if name == nil
|
15
|
+
@structs = structs[name]
|
16
|
+
end
|
17
|
+
|
18
|
+
structs
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included(reciever)
|
22
|
+
reciever.extend self
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
module PackedStruct
|
2
|
+
|
3
|
+
# Contains information about a directive. A directive can be a name
|
4
|
+
# of the type, the endian(ness) of the type, the type of the type
|
5
|
+
# (short, int, long, etc.), and the signed(ness) of the type.
|
6
|
+
class Directive
|
7
|
+
|
8
|
+
# The name of the directive. This is passed as the first value of
|
9
|
+
# the directive; from {Package}, it is the name of the method call.
|
10
|
+
#
|
11
|
+
# @return [Symbol]
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# The arguments passed to the directive.
|
15
|
+
#
|
16
|
+
# @return [Array<Object>]
|
17
|
+
attr_reader :options
|
18
|
+
|
19
|
+
# The tags the directive has, such as type, signed(ness),
|
20
|
+
# endian(ness), and size. Not filled until {#to_s} is called.
|
21
|
+
#
|
22
|
+
# @return [Hash]
|
23
|
+
attr_accessor :tags
|
24
|
+
|
25
|
+
# The children of this directive. If this directive has a parent,
|
26
|
+
# this is nil.
|
27
|
+
#
|
28
|
+
# @return [nil, Array<Directive>]
|
29
|
+
attr_reader :subs
|
30
|
+
|
31
|
+
# The parent of this directive. The relationship is such that
|
32
|
+
# +parent.subs.include?(self)+ is true. If this has a parent, it
|
33
|
+
# is nil.
|
34
|
+
#
|
35
|
+
# @return [nil, Directive]
|
36
|
+
attr_accessor :parent
|
37
|
+
|
38
|
+
# The value this directive holds. Only for use when packing.
|
39
|
+
#
|
40
|
+
# @return [nil, Object]
|
41
|
+
attr_writer :value
|
42
|
+
|
43
|
+
# @!parse
|
44
|
+
# attr_reader :value
|
45
|
+
def value
|
46
|
+
@value || (@tags[:original].value if @tags[:original])
|
47
|
+
end
|
48
|
+
|
49
|
+
# Initialize the directive.
|
50
|
+
#
|
51
|
+
# @param name [Symbol] the name of the directive.
|
52
|
+
def initialize(name, *arguments)
|
53
|
+
@name = name
|
54
|
+
|
55
|
+
@options = arguments
|
56
|
+
@tags = {}
|
57
|
+
@subs = []
|
58
|
+
@parent = nil
|
59
|
+
@value = nil
|
60
|
+
|
61
|
+
if arguments.first.is_a? Directive
|
62
|
+
arguments.first.add_child(self)
|
63
|
+
@subs = nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Add a child to this (or its parent's) directive. If this is a
|
68
|
+
# child itself, it adds it to the parent of this. Invalidates the
|
69
|
+
# caches for {#sub_names} and {#to_s}
|
70
|
+
#
|
71
|
+
# @param child [Directive] the child to add.
|
72
|
+
# @return [Directive] the child.
|
73
|
+
def add_child(child)
|
74
|
+
if @parent
|
75
|
+
@parent.add_child(child)
|
76
|
+
else
|
77
|
+
@_str = nil
|
78
|
+
@_sub_types = nil
|
79
|
+
@subs << child
|
80
|
+
child.parent = self
|
81
|
+
child
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Set the size of this directive.
|
86
|
+
#
|
87
|
+
# @return [self]
|
88
|
+
def [](size)
|
89
|
+
@tags[:size] = size
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
# Turn the directive into a string. Analyzes the subs before
|
94
|
+
# determining information, then outputs that. Caches the value
|
95
|
+
# until {#add_child} is next called.
|
96
|
+
#
|
97
|
+
# @return [String]
|
98
|
+
def to_s
|
99
|
+
return "" unless @subs
|
100
|
+
@subs.compact!
|
101
|
+
@tags[:signed] = determine_signed
|
102
|
+
@tags[:type] = determine_type
|
103
|
+
@tags[:endian] = determine_endian
|
104
|
+
"#{make_directive}#{make_length}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Inspects the directive.
|
108
|
+
#
|
109
|
+
# @return [String]
|
110
|
+
def inspect
|
111
|
+
"#<#{self.class.name}:#{name}>"
|
112
|
+
end
|
113
|
+
|
114
|
+
# To show the size of something else, relative to this directive.
|
115
|
+
#
|
116
|
+
# @return [Directive]
|
117
|
+
def -(other)
|
118
|
+
dir = dup
|
119
|
+
dir.tags = tags.dup
|
120
|
+
dir.tags[:original ] = self
|
121
|
+
dir.tags[:size_modify] = -other
|
122
|
+
dir
|
123
|
+
end
|
124
|
+
|
125
|
+
# To show the size of something else, relative to this directive.
|
126
|
+
#
|
127
|
+
# @return [Directive]
|
128
|
+
def +(other)
|
129
|
+
dir = dup
|
130
|
+
dir.tags = tags.dup
|
131
|
+
dir.tags[:original ] = self
|
132
|
+
dir.tags[:size_modify] = +other
|
133
|
+
dir
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
# Returns all of the names of the subs, and caches it.
|
139
|
+
#
|
140
|
+
# @param force [Boolean] force reloading the names of the subs.
|
141
|
+
# @return [Array<Symbol>]
|
142
|
+
def sub_names(force = false)
|
143
|
+
if @_sub_types && !force
|
144
|
+
@_sub_types
|
145
|
+
else
|
146
|
+
@subs.map(&:name) + [@name]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Determines the size of the directive by checking if it's in the
|
151
|
+
# tags, or by searching the subs.
|
152
|
+
#
|
153
|
+
# @return [Numeric]
|
154
|
+
def size
|
155
|
+
case @tags[:size]
|
156
|
+
when Directive
|
157
|
+
(@tags[:size].value || 0) + (@tags[:size].tags[:size_modify] || 0)
|
158
|
+
when Numeric
|
159
|
+
@tags[:size]
|
160
|
+
when nil
|
161
|
+
@subs.select { |s| s && s.tags[:size] }.map { |s| s.tags[:size] }.last
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Determine the type of this directive. Uses {#sub_names} to
|
166
|
+
# search for matching types. Defaults to +nil+.
|
167
|
+
#
|
168
|
+
# @return [nil, Symbol] the return value can be any of +:short+,
|
169
|
+
# +:int+, +:long+, +:string+, +:float+, or +nil+.
|
170
|
+
def determine_type
|
171
|
+
case true
|
172
|
+
when sub_names.include?(:short)
|
173
|
+
:short
|
174
|
+
when sub_names.include?(:int)
|
175
|
+
:int
|
176
|
+
when sub_names.include?(:long)
|
177
|
+
:long
|
178
|
+
when sub_names.include?(:char), sub_names.include?(:string)
|
179
|
+
:string
|
180
|
+
when sub_names.include?(:float)
|
181
|
+
:float
|
182
|
+
when sub_names.include?(:null)
|
183
|
+
:null
|
184
|
+
else
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Determines the endianness of this directive. Uses {#sub_names}
|
190
|
+
# to search for matching names. Defaults to +:native+.
|
191
|
+
#
|
192
|
+
# @return [Symbol] the return value can be any of +:little+,
|
193
|
+
# +:big+, or +:native+.
|
194
|
+
def determine_endian
|
195
|
+
case true
|
196
|
+
when sub_names.include?(:little), sub_names.include?(:little_endian),
|
197
|
+
sub_names.include?(:lsb), sub_names.include?(:low)
|
198
|
+
:little
|
199
|
+
when sub_names.include?(:big), sub_names.include?(:big_endian),
|
200
|
+
sub_names.include?(:msb), sub_names.include?(:high),
|
201
|
+
sub_names.include?(:network)
|
202
|
+
:big
|
203
|
+
else
|
204
|
+
:native
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Determines the signedness of this directive. Uses {#sub_names}
|
209
|
+
# to search for matching names. Defaults to +:signed+.
|
210
|
+
#
|
211
|
+
# @return [Symbol] the return value can be any of +:unsigned+ or
|
212
|
+
# +:signed+.
|
213
|
+
def determine_signed
|
214
|
+
if sub_names.include?(:unsigned) && !sub_names.include?(:null)
|
215
|
+
:unsigned
|
216
|
+
else
|
217
|
+
:signed
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Determines the directive to be used in the pack string, using
|
222
|
+
# the type from {#determine_type} to manage it.
|
223
|
+
#
|
224
|
+
# @return [String] the directive for the pack string.
|
225
|
+
def make_directive
|
226
|
+
case @tags[:type]
|
227
|
+
when nil
|
228
|
+
handle_nil_type
|
229
|
+
when :short
|
230
|
+
modify_if_needed "S"
|
231
|
+
when :int
|
232
|
+
modify_if_needed "I"
|
233
|
+
when :long
|
234
|
+
modify_if_needed "L"
|
235
|
+
when :string
|
236
|
+
handle_string_type
|
237
|
+
when :float
|
238
|
+
handle_float_type
|
239
|
+
when :null
|
240
|
+
"x" * (size || 1)
|
241
|
+
else
|
242
|
+
nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Determines the length to be added to the pack string.
|
247
|
+
#
|
248
|
+
# @return [String]
|
249
|
+
def make_length
|
250
|
+
if size && ![:null, nil].include?(@tags[:type])
|
251
|
+
size.to_s
|
252
|
+
else
|
253
|
+
""
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Handles the nil type. Uses the size to match the type with
|
258
|
+
# the directive.
|
259
|
+
#
|
260
|
+
# @return [String]
|
261
|
+
def handle_nil_type
|
262
|
+
maps = {
|
263
|
+
8 => "C",
|
264
|
+
16 => "S",
|
265
|
+
32 => "L",
|
266
|
+
64 => "Q"
|
267
|
+
}
|
268
|
+
|
269
|
+
raise StandardError,
|
270
|
+
"Cannot make number of #{size} length" unless
|
271
|
+
maps.keys.include?(size)
|
272
|
+
|
273
|
+
modify_if_needed maps[size]
|
274
|
+
end
|
275
|
+
|
276
|
+
# Handles a string type. If the name of the directive is
|
277
|
+
# +:null+, returns a string containing a number of +x+s (nulls)
|
278
|
+
# exactly equal to the size (or 1, if it doesn't exist).
|
279
|
+
# Otherwise, determines the type of string from the sub names;
|
280
|
+
# types of strings can include +:hex+, +:base64+, +:bit+, or
|
281
|
+
# +:binary+ (defaults to binary).
|
282
|
+
#
|
283
|
+
# @return [String]
|
284
|
+
def handle_string_type
|
285
|
+
|
286
|
+
case true
|
287
|
+
when sub_names.include?(:hex)
|
288
|
+
modify_if_needed "H"
|
289
|
+
when sub_names.include?(:base64)
|
290
|
+
"m"
|
291
|
+
when sub_names.include?(:bit)
|
292
|
+
modify_if_needed "B", false
|
293
|
+
else
|
294
|
+
modify_if_needed "A", false
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Handles float types. Can handle double- or single- precision
|
299
|
+
# floats, and manage their byte order.
|
300
|
+
#
|
301
|
+
# @return [String]
|
302
|
+
def handle_float_type
|
303
|
+
double = sub_names.include?(:double)
|
304
|
+
|
305
|
+
case @tags[:endian]
|
306
|
+
when :native
|
307
|
+
if double
|
308
|
+
"D"
|
309
|
+
else
|
310
|
+
"F"
|
311
|
+
end
|
312
|
+
when :little
|
313
|
+
if double
|
314
|
+
"E"
|
315
|
+
else
|
316
|
+
"e"
|
317
|
+
end
|
318
|
+
when :big
|
319
|
+
if double
|
320
|
+
"G"
|
321
|
+
else
|
322
|
+
"g"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Modifies the given string as needed; it assumes that a lowercase
|
328
|
+
# letter stands for a signed type and the given string stands for
|
329
|
+
# an unsigned type. It also assumes that "<" added means little
|
330
|
+
# endian, and that ">" added means big endian (and that nothing
|
331
|
+
# added stands for native).
|
332
|
+
#
|
333
|
+
# @param str [String]
|
334
|
+
# @return [String]
|
335
|
+
def modify_if_needed(str, include_endian = true)
|
336
|
+
base = if @tags[:signed] == :signed
|
337
|
+
str.downcase
|
338
|
+
else
|
339
|
+
str
|
340
|
+
end
|
341
|
+
|
342
|
+
base += case @tags[:endian]
|
343
|
+
when :little
|
344
|
+
"<"
|
345
|
+
when :big
|
346
|
+
">"
|
347
|
+
else
|
348
|
+
""
|
349
|
+
end if include_endian
|
350
|
+
|
351
|
+
base
|
352
|
+
end
|
353
|
+
|
354
|
+
end
|
355
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module PackedStruct
|
2
|
+
|
3
|
+
# Manages the struct overall, and keeps track of the directives.
|
4
|
+
# Directives are packed in the order that they are joined, such
|
5
|
+
# that the first one defined is the first one on the string.
|
6
|
+
class Package
|
7
|
+
|
8
|
+
# The list of directives that the package has.
|
9
|
+
#
|
10
|
+
# @return [Array<Directive>]
|
11
|
+
def directives
|
12
|
+
@directives.select! { |x| x.parent.nil? }
|
13
|
+
@directives
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initialize the package.
|
17
|
+
def initialize
|
18
|
+
@directives = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# Turn the package into a string. Uses the directives (calls
|
22
|
+
# {Directive#to_s} on them), and joins the result.
|
23
|
+
#
|
24
|
+
# @return [String] the string ready for #pack.
|
25
|
+
def to_s
|
26
|
+
@_str ||= directives.map(&:to_s).join(' ')
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method :to_str, :to_s
|
30
|
+
|
31
|
+
# Packs the given data into a string. The keys of the data
|
32
|
+
# correspond to the names of the directives.
|
33
|
+
#
|
34
|
+
# @param [Hash<Symbol, Object>] the data.
|
35
|
+
# @return [String] the packed data.
|
36
|
+
def pack(data)
|
37
|
+
values = []
|
38
|
+
data.each do |k, v|
|
39
|
+
values.push([k, v])
|
40
|
+
end
|
41
|
+
|
42
|
+
mapped_directives = @directives.map(&:name)
|
43
|
+
|
44
|
+
values.sort do |a, b|
|
45
|
+
directives.index(a) <=> directives.index(b)
|
46
|
+
end
|
47
|
+
|
48
|
+
pack_with_array(values.map(&:last))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Packs the directives into a string. Uses an array.
|
52
|
+
# The parameters can either be an array, or a set of values.
|
53
|
+
#
|
54
|
+
# @return [String]
|
55
|
+
def pack_with_array(*array)
|
56
|
+
array.flatten!
|
57
|
+
|
58
|
+
directives.each_with_index { |e, i| e.value = array[i] }
|
59
|
+
out = array.pack(self.to_s)
|
60
|
+
directives.each { |x| x.value = nil }
|
61
|
+
out
|
62
|
+
end
|
63
|
+
|
64
|
+
# Unpacks the given string with the directives. Returns a hash
|
65
|
+
# containing the values, with the keys being the names of the
|
66
|
+
# directives.
|
67
|
+
#
|
68
|
+
# @param string [String] the packed string.
|
69
|
+
# @return [Hash<Symbol, Object>] the unpacked data.
|
70
|
+
def unpack(string)
|
71
|
+
total = ""
|
72
|
+
parts = {}
|
73
|
+
directives.each_with_index do |directive, i|
|
74
|
+
total << directive.to_s
|
75
|
+
value = string.unpack(total)[i]
|
76
|
+
directive.value = value
|
77
|
+
parts[directive.name] = value
|
78
|
+
end
|
79
|
+
|
80
|
+
directives.each { |x| x.value = nil }
|
81
|
+
|
82
|
+
parts.delete(:null) {}
|
83
|
+
parts
|
84
|
+
end
|
85
|
+
|
86
|
+
# This unpacks the entire string at once. It assumes that none of
|
87
|
+
# the directives will need the values of other directives. If
|
88
|
+
# you're not sure what this means, don't use it.
|
89
|
+
#
|
90
|
+
# @param string [String] the packed string.
|
91
|
+
# @return [Hash<Symbol, Object>] the unpacked data.
|
92
|
+
def fast_unpack(string)
|
93
|
+
out = string.unpack(to_s)
|
94
|
+
parts = {}
|
95
|
+
|
96
|
+
directives.each_with_index do |directive, i|
|
97
|
+
parts[directive.name] = out[i]
|
98
|
+
end
|
99
|
+
|
100
|
+
parts.delete(:null) {}
|
101
|
+
parts
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Inspects the package.
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
def inspect
|
109
|
+
"#<#{self.class.name}:#{"0x%014x" % directives.map(&:object_id).inject(&:+)}>"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates a new directive with the given method and arguments.
|
113
|
+
#
|
114
|
+
# @return [Directive] the new directive.
|
115
|
+
def method_missing(method, *arguments, &block)
|
116
|
+
if @directives.map(&:name).include?(method) && arguments.length == 0
|
117
|
+
@directives.select { |x| x.name == method }.first
|
118
|
+
else
|
119
|
+
@_str = nil
|
120
|
+
directive = Directive.new(method, *arguments)
|
121
|
+
@directives << directive
|
122
|
+
directive
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: packed_struct
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Rodi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-26 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! ' Cleans up the string mess when packing items (in Array#pack) and
|
15
|
+
unpacking items (in String#unpack).
|
16
|
+
|
17
|
+
'
|
18
|
+
email: redjazz96@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- README.md
|
24
|
+
- LICENSE
|
25
|
+
- lib/packed_struct/version.rb
|
26
|
+
- lib/packed_struct/package.rb
|
27
|
+
- lib/packed_struct/directive.rb
|
28
|
+
- lib/packed_struct.rb
|
29
|
+
homepage: http://github.com/redjazz96/packed_struct
|
30
|
+
licenses: []
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 1.8.25
|
50
|
+
signing_key:
|
51
|
+
specification_version: 3
|
52
|
+
summary: Cleans up the string mess when packing items.
|
53
|
+
test_files: []
|
54
|
+
has_rdoc: false
|