active_model_serializers_binary 0.0.10 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -1
- data/lib/active_model_serializers_binary/active_model_serializers_binary.rb +119 -62
- data/lib/active_model_serializers_binary/base_type.rb +136 -0
- data/lib/active_model_serializers_binary/data_types.rb +102 -133
- data/lib/active_model_serializers_binary/version.rb +1 -1
- data/test/dummy/lib/test_parser.rb +29 -28
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f3830d0d3a2a18ae95bb47c427e1af2ea6d2d86
|
4
|
+
data.tar.gz: 546aff445bb2ec63c9734955c762f3a87029b4b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92274b86db2b91c5085e29e659279428d0221b1bd3bcfd4c9f650de4d32db55800887e22919261fea282960ac87efed344844da28a3955386848ece83e2c4509
|
7
|
+
data.tar.gz: 272721accba6bd385c4b1c967afd42af2a155e132c4c807d69752bb4673e05cbb6d72da8f64cf0f3767cbbfc0e5ea9797c12db564d655fed3d29436b944976de
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -15,11 +15,59 @@ module ActiveModel
|
|
15
15
|
|
16
16
|
class_attribute :attr_config
|
17
17
|
self.attr_config = {}
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
self.attr_config.each do |key, options|
|
22
|
+
options[:parent] = self
|
23
|
+
end
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
module ClassMethods
|
21
|
-
|
22
|
-
|
28
|
+
# todo: agrupar parametros en hash (rompe la compatibilidad hacia atras)
|
29
|
+
def serialize_options(attr_name, coder, count=1, length=1, &block )
|
30
|
+
self.attr_config.merge!(attr_name.to_s => {:coder => coder, :count => count, :length => length, :block => block, :name => attr_name})
|
31
|
+
end
|
32
|
+
|
33
|
+
def int8( attr_name, options = {}, &block )
|
34
|
+
serialize_options attr_name, DataTypes::Int8, options[:count], options[:length], &block
|
35
|
+
end
|
36
|
+
|
37
|
+
def int16( attr_name, options = {}, &block )
|
38
|
+
serialize_options attr_name, DataTypes::Int16, options[:count], options[:length], &block
|
39
|
+
end
|
40
|
+
|
41
|
+
def int32( attr_name, options = {}, &block )
|
42
|
+
serialize_options attr_name, DataTypes::Int32, options[:count], options[:length], &block
|
43
|
+
end
|
44
|
+
|
45
|
+
def uint8( attr_name, options = {}, &block )
|
46
|
+
serialize_options attr_name, DataTypes::UInt8, options[:count], options[:length], &block
|
47
|
+
end
|
48
|
+
|
49
|
+
def uint16( attr_name, options = {}, &block )
|
50
|
+
serialize_options attr_name, DataTypes::UInt16, options[:count], options[:length], &block
|
51
|
+
end
|
52
|
+
|
53
|
+
def uint32( attr_name, options = {}, &block )
|
54
|
+
serialize_options attr_name, DataTypes::UInt32, options[:count], options[:length], &block
|
55
|
+
end
|
56
|
+
|
57
|
+
def bitfield( attr_name, options = {}, &block )
|
58
|
+
serialize_options attr_name, DataTypes::BitField, options[:count], options[:length], &block
|
59
|
+
end
|
60
|
+
|
61
|
+
def float32( attr_name, options = {}, &block )
|
62
|
+
serialize_options attr_name, DataTypes::Float32, options[:count], options[:length], &block
|
63
|
+
end
|
64
|
+
|
65
|
+
def char( attr_name, options = {}, &block )
|
66
|
+
serialize_options attr_name, DataTypes::Char, options[:count], options[:length], &block
|
67
|
+
end
|
68
|
+
|
69
|
+
def bool( attr_name, options = {}, &block )
|
70
|
+
serialize_options attr_name, DataTypes::Bool, options[:count], options[:length], &block
|
23
71
|
end
|
24
72
|
end
|
25
73
|
|
@@ -39,8 +87,8 @@ module ActiveModel
|
|
39
87
|
tmp_buffer = [] # Buffer temporal en bytes
|
40
88
|
current_address = start_address*2 + 0.0 # Dirección en bytes
|
41
89
|
|
42
|
-
@serializable.attr_config.each do |key,
|
43
|
-
var =
|
90
|
+
@serializable.attr_config.each do |key, options|
|
91
|
+
var = options[:coder].new(options)
|
44
92
|
# Busca el valor del atributo y si no existe devuelve nil
|
45
93
|
var.value = serializable_values[key] rescue nil
|
46
94
|
|
@@ -50,20 +98,28 @@ module ActiveModel
|
|
50
98
|
tmp_buffer = var.dump
|
51
99
|
|
52
100
|
if @options[:align]
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
101
|
+
if !var.type.in? [:bitfield, :bool]
|
102
|
+
# Se posiciona al principio de un byte
|
103
|
+
if bit != 0
|
104
|
+
byte += 1
|
105
|
+
bit = 0
|
106
|
+
current_address = (byte+bit/8.0)
|
107
|
+
end
|
108
|
+
# Si el dato es una palabra simple, alinea los datos en el siguiente byte par
|
109
|
+
if var.bit_length > 8 and current_address.modulo(2) != 0
|
110
|
+
byte += 1
|
111
|
+
bit = 0
|
112
|
+
end
|
113
|
+
# Si el dato es una palabra doble, alinea los datos en la siguiente palabra par
|
114
|
+
if var.bit_length > 16 and (current_address + start_address*2).modulo(4) != 0
|
115
|
+
byte += 4-byte%4
|
116
|
+
bit = 0
|
117
|
+
end
|
62
118
|
end
|
63
119
|
end
|
64
120
|
|
65
121
|
# Si los datos ocupan mas de un byte concatena los arrays
|
66
|
-
if var.
|
122
|
+
if !var.type.in? [:bitfield, :bool] and @options[:align]
|
67
123
|
buffer.insert(byte, tmp_buffer).flatten!
|
68
124
|
else # En caso de ser bits
|
69
125
|
tmp_buffer.flatten!
|
@@ -90,23 +146,31 @@ module ActiveModel
|
|
90
146
|
|
91
147
|
current_address = start_address*2 + 0.0 # Dirección en bytes
|
92
148
|
|
93
|
-
@serializable.attr_config.each do |key,
|
94
|
-
#puts "#{key} - #{
|
149
|
+
@serializable.attr_config.each do |key, options|
|
150
|
+
#puts "#{key} - #{options}"
|
95
151
|
byte = current_address.floor
|
96
152
|
bit = (current_address.modulo(1)*8).round
|
97
153
|
|
98
|
-
var =
|
154
|
+
var = options[:coder].new(options) #creo objeto del tipo de dato pasado
|
99
155
|
|
100
156
|
if @options[:align]
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
157
|
+
if !var.type.in? [:bitfield, :bool]
|
158
|
+
# Se posiciona al principio de un byte
|
159
|
+
if bit != 0
|
160
|
+
byte += 1
|
161
|
+
bit = 0
|
162
|
+
current_address = (byte+bit/8.0)
|
163
|
+
end
|
164
|
+
# Si el dato es una palabra simple, alinea los datos en el siguiente byte par
|
165
|
+
if var.bit_length > 8 and current_address.modulo(2) != 0
|
166
|
+
byte += 1
|
167
|
+
bit = 0
|
168
|
+
end
|
169
|
+
# Si el dato es una palabra doble, alinea los datos en la siguiente palabra par
|
170
|
+
if var.bit_length > 16 and (current_address + start_address*2).modulo(4) != 0
|
171
|
+
byte += 4-byte%4
|
172
|
+
bit = 0
|
173
|
+
end
|
110
174
|
end
|
111
175
|
end
|
112
176
|
|
@@ -114,7 +178,7 @@ module ActiveModel
|
|
114
178
|
if var.bit_length >= 8 and @options[:align]
|
115
179
|
result_deserialized=var.load(buffer.slice(byte, var.size))
|
116
180
|
else # En caso de ser bits
|
117
|
-
tmp_buffer = buffer.slice(byte, var.size.ceil)
|
181
|
+
tmp_buffer = buffer.slice(byte, (var.size+bit/8.0).ceil)
|
118
182
|
result_deserialized=var.load([tmp_buffer.pack('C*').unpack('b*').first.slice(bit,var.size*8)].pack('b*').unpack('C*'))
|
119
183
|
end
|
120
184
|
# puts result_deserialized.inspect
|
@@ -138,47 +202,29 @@ module ActiveModel
|
|
138
202
|
|
139
203
|
end #close class serializer
|
140
204
|
|
141
|
-
# Returns
|
205
|
+
# Returns a binary array representing the model. Configuration can be
|
142
206
|
# passed through +options+.
|
143
207
|
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
# user = User.find(1)
|
148
|
-
# user.to_xml
|
208
|
+
# person = Person.find(1)
|
209
|
+
# person.to_bytes
|
149
210
|
#
|
150
|
-
#
|
151
|
-
# <user>
|
152
|
-
# <id type="integer">1</id>
|
153
|
-
# <name>David</name>
|
154
|
-
# <age type="integer">16</age>
|
155
|
-
# <created-at type="dateTime">2011-01-30T22:29:23Z</created-at>
|
156
|
-
# </user>
|
211
|
+
# => [98, 111, 98, 0, 0, 0, 0, 0, 0, 0, 22, 0, 1]
|
157
212
|
#
|
158
|
-
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the
|
159
|
-
# attributes included, and work similar to the +attributes+ method.
|
160
|
-
#
|
161
|
-
# To include the result of some method calls on the model use <tt>:methods</tt>.
|
162
|
-
#
|
163
|
-
# To include associations use <tt>:include</tt>.
|
164
|
-
#
|
165
|
-
# For further documentation, see <tt>ActiveRecord::Serialization#to_xml</tt>
|
166
213
|
def to_bytes(options = {}, &block)
|
167
214
|
default_options = {
|
168
215
|
:align => true,
|
169
|
-
:block => block
|
170
216
|
}
|
171
217
|
options = default_options.deep_merge(options)
|
172
|
-
if
|
173
|
-
|
218
|
+
if block_given?
|
219
|
+
yield self
|
174
220
|
end
|
175
221
|
Serializer.new(self, options).dump
|
176
222
|
end
|
177
223
|
|
178
|
-
# Sets the model +attributes+ from an
|
224
|
+
# Sets the model +attributes+ from an Binary string. Returns +self+.
|
179
225
|
#
|
180
226
|
# class Person
|
181
|
-
# include ActiveModel::Serializers::
|
227
|
+
# include ActiveModel::Serializers::Binary
|
182
228
|
#
|
183
229
|
# attr_accessor :name, :age, :awesome
|
184
230
|
#
|
@@ -191,24 +237,35 @@ module ActiveModel
|
|
191
237
|
# def attributes
|
192
238
|
# instance_values
|
193
239
|
# end
|
240
|
+
#
|
241
|
+
# char :name, count: 1, length: 10
|
242
|
+
# int16 :age
|
243
|
+
# bool :awesome
|
194
244
|
# end
|
195
245
|
#
|
196
|
-
#
|
246
|
+
# bytes = [98, 111, 98, 0, 0, 0, 0, 0, 0, 0, 22, 0, 1]
|
197
247
|
# person = Person.new
|
198
|
-
# person.
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
248
|
+
# person.from_bytes(bytes) do |p|
|
249
|
+
# p.name.upcase!
|
250
|
+
# end
|
251
|
+
# => #<Person:0x007fec5e3b3c40 @age=22, @awesome=true, @name="bob">
|
252
|
+
#
|
253
|
+
# @param [Array] buffer byte array with model data to deserialize
|
254
|
+
# @param [Hash] options deserealization options
|
255
|
+
#
|
256
|
+
# @return [Object] Deserialized object
|
257
|
+
#
|
258
|
+
# @yield code block to execute after deserialization
|
259
|
+
#
|
202
260
|
def from_bytes(buffer, options = {}, &block)
|
203
261
|
default_options = {
|
204
|
-
:align => true
|
205
|
-
:block => block
|
262
|
+
:align => true
|
206
263
|
}
|
207
264
|
options = default_options.deep_merge(options)
|
208
265
|
retVal = Serializer.new(self, options).load buffer
|
209
266
|
|
210
|
-
if
|
211
|
-
|
267
|
+
if block_given?
|
268
|
+
yield self
|
212
269
|
end
|
213
270
|
retVal
|
214
271
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module DataTypes
|
2
|
+
|
3
|
+
class Type
|
4
|
+
|
5
|
+
attr_accessor :raw_value, :bit_length, :type, :sign, :count, :length, :value, :name, :parent
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@default_value = options[:default_value] || 0
|
9
|
+
@raw_value = nil
|
10
|
+
@bit_length = options[:bit_length] # Cantidad de bits del tipo de dato
|
11
|
+
@type = type
|
12
|
+
@sign = options[:sign] # :signed / :unsigned
|
13
|
+
@count = options[:count] || 1 # Cantidad de elementos del array
|
14
|
+
@length = options[:length] || 1 # En char y bitfield especifica la longitud del campo. Ignorado para el resto de los tipos
|
15
|
+
@value = check_value( @default_value )
|
16
|
+
@block = options[:block]
|
17
|
+
@name = options[:name]
|
18
|
+
@parent = options[:parent]
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
@value.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def type
|
26
|
+
self.class.to_s.split('::').last.downcase.to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return size of object in bytes
|
30
|
+
def size
|
31
|
+
((@bit_length*@length*@count)/8.0).ceil
|
32
|
+
end
|
33
|
+
|
34
|
+
def check( value, options = {} )
|
35
|
+
type = options[:type]
|
36
|
+
count = options[:count]
|
37
|
+
length = options[:length]
|
38
|
+
bit_length = options[:bit_length]
|
39
|
+
sign = options[:sign]
|
40
|
+
default_value = options[:default_value]
|
41
|
+
|
42
|
+
value = Array(value) # Se asegura de que sea un array
|
43
|
+
value = value[0...count] # Corta el array según la cantidad de elementos especificados en la declaración
|
44
|
+
# Lo convierte al tipo especificado
|
45
|
+
value.map! do |v|
|
46
|
+
if v.nil?
|
47
|
+
default_value
|
48
|
+
else
|
49
|
+
case type
|
50
|
+
when :float32
|
51
|
+
v.to_f
|
52
|
+
when :char
|
53
|
+
v.to_s[0...length]
|
54
|
+
when :bool
|
55
|
+
(v.in? [0, false]) ? false : true
|
56
|
+
else
|
57
|
+
v.to_i
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
trim(value, bit_length, sign) # Se asegura de que los valores esten dentro de los rangos permitidos pra el tipo de dato declarado
|
63
|
+
value.fill(default_value, value.length...count) # Completa los elementos faltantes del array con default_value
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_value(value)
|
67
|
+
check(value, {
|
68
|
+
:type => @type,
|
69
|
+
:count => @count,
|
70
|
+
:length => @length,
|
71
|
+
:bit_length => @bit_length,
|
72
|
+
:sign => @sign,
|
73
|
+
:default_value => @default_value,
|
74
|
+
})
|
75
|
+
end
|
76
|
+
|
77
|
+
# Los datos siempre vienen en bytes
|
78
|
+
def check_raw_value(value)
|
79
|
+
check(value, {
|
80
|
+
:type => :uint8,
|
81
|
+
:count => size,
|
82
|
+
:length => 1,
|
83
|
+
:bit_length => 8,
|
84
|
+
:sign => :unsigned,
|
85
|
+
:default_value => 0,
|
86
|
+
})
|
87
|
+
end
|
88
|
+
|
89
|
+
def trim(value, bit_length, sign)
|
90
|
+
# Recorta los valores según el bit_length
|
91
|
+
value.map! do |v|
|
92
|
+
if sign == :signed
|
93
|
+
[-2**(bit_length-1),[v.to_i,2**(bit_length-1)-1].min].max
|
94
|
+
elsif sign == :unsigned
|
95
|
+
[0,[v.to_i,2**(bit_length)-1].min].max
|
96
|
+
else
|
97
|
+
v
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def value=(value)
|
103
|
+
@value = check_value(value)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#
|
108
|
+
# Se ejecuta antes de serializar los datos
|
109
|
+
#
|
110
|
+
# @param [Object] value valor del objeto a serializar original
|
111
|
+
#
|
112
|
+
# @return [Array] nuevo valor del objeto a serializar
|
113
|
+
#
|
114
|
+
def before_dump(value)
|
115
|
+
self.value = value if !value.nil?
|
116
|
+
if !@block.nil?
|
117
|
+
value = @parent.instance_exec( self, :dump, &@block )
|
118
|
+
self.value = value if !value.nil?
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Se ejecuta después de deserializar los datos. @value contiene los datos deserializados
|
124
|
+
#
|
125
|
+
#
|
126
|
+
# @return [Array] Array con los datos deserializados
|
127
|
+
#
|
128
|
+
def after_load
|
129
|
+
if !@block.nil?
|
130
|
+
value = @parent.instance_exec( self, :load, &@block )
|
131
|
+
self.value = value if !value.nil?
|
132
|
+
end
|
133
|
+
@value
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,218 +1,187 @@
|
|
1
|
+
require_relative 'base_type.rb'
|
2
|
+
|
1
3
|
module DataTypes
|
2
|
-
class Type
|
3
|
-
attr_accessor :value, :bit_length
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@count = count
|
9
|
-
@length = length
|
10
|
-
@default_value = 0
|
5
|
+
class Int8 < Type
|
6
|
+
def initialize(options = {})
|
7
|
+
super options.merge :bit_length => 8, :sign => :signed
|
11
8
|
end
|
12
9
|
|
13
|
-
def
|
14
|
-
|
10
|
+
def dump(value=nil)
|
11
|
+
before_dump( value )
|
12
|
+
@raw_value = @value
|
15
13
|
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def load(raw_value)
|
16
|
+
self.value = check_raw_value(raw_value)
|
17
|
+
after_load
|
20
18
|
end
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
value=(value.is_a? Array) ? value : [value]
|
27
|
-
end
|
28
|
-
|
29
|
-
value.map!{|v| v.nil? ? @default_value : v}
|
30
|
-
value.map! do |v|
|
31
|
-
case @default_value.class.name
|
32
|
-
when "Float"
|
33
|
-
v.to_f
|
34
|
-
when "String"
|
35
|
-
v.to_s[0...@length]
|
36
|
-
else
|
37
|
-
v.to_i
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
value=value[0...@count]
|
42
|
-
value.fill(@default_value, value.length...@count)
|
21
|
+
class Int16 < Type
|
22
|
+
def initialize(options = {})
|
23
|
+
super options.merge :bit_length => 16, :sign => :signed
|
43
24
|
end
|
44
25
|
|
45
|
-
def value=
|
46
|
-
value
|
26
|
+
def dump(value=nil)
|
27
|
+
before_dump( value )
|
28
|
+
@raw_value = @value.pack('v*').unpack('C*')
|
29
|
+
end
|
47
30
|
|
48
|
-
|
49
|
-
value
|
50
|
-
|
51
|
-
((@sign == :unsigned)? [0,[v.to_i,2**(@bit_length)-1].min].max : v )
|
52
|
-
end
|
53
|
-
@value=value
|
31
|
+
def load(raw_value)
|
32
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('v*')
|
33
|
+
after_load
|
54
34
|
end
|
55
35
|
end
|
56
36
|
|
57
|
-
class
|
58
|
-
def initialize(
|
59
|
-
super
|
60
|
-
self.value = @default_value
|
37
|
+
class Int32 < Type
|
38
|
+
def initialize(options = {})
|
39
|
+
super options.merge :bit_length => 32, :sign => :signed
|
61
40
|
end
|
62
41
|
|
63
42
|
def dump(value=nil)
|
64
|
-
|
65
|
-
@value
|
43
|
+
before_dump( value )
|
44
|
+
@raw_value = @value.pack('V*').unpack('C*')
|
66
45
|
end
|
67
46
|
|
68
|
-
def load(
|
69
|
-
self.value =
|
70
|
-
|
47
|
+
def load(raw_value)
|
48
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('V*') if !value.nil?
|
49
|
+
after_load
|
71
50
|
end
|
72
51
|
end
|
73
52
|
|
74
|
-
class
|
75
|
-
def initialize(
|
76
|
-
super 16, :
|
77
|
-
self.value = @default_value
|
53
|
+
class UInt16 < Type
|
54
|
+
def initialize(options = {})
|
55
|
+
super options.merge :bit_length => 16, :sign => :unsigned
|
78
56
|
end
|
79
57
|
|
80
58
|
def dump(value=nil)
|
81
|
-
|
82
|
-
@value.pack('v*').unpack('C*')
|
59
|
+
before_dump( value )
|
60
|
+
@raw_value = @value.pack('v*').unpack('C*')
|
83
61
|
end
|
84
62
|
|
85
|
-
def load(
|
86
|
-
|
87
|
-
@
|
63
|
+
def load(raw_value)
|
64
|
+
@raw_value = check_raw_value(raw_value)
|
65
|
+
self.value = @raw_value.pack('C*').unpack('v*')
|
66
|
+
after_load
|
88
67
|
end
|
89
68
|
end
|
90
69
|
|
91
|
-
class
|
92
|
-
def initialize(
|
93
|
-
super 32, :
|
94
|
-
self.value = @default_value
|
70
|
+
class UInt32 < Type
|
71
|
+
def initialize(options = {})
|
72
|
+
super options.merge :bit_length => 32, :sign => :unsigned
|
95
73
|
end
|
96
74
|
|
97
75
|
def dump(value=nil)
|
98
|
-
|
99
|
-
@value.pack('
|
76
|
+
before_dump( value )
|
77
|
+
@raw_value = @value.pack('l*').unpack('C*')
|
100
78
|
end
|
101
79
|
|
102
|
-
def load(
|
103
|
-
self.value =
|
104
|
-
|
80
|
+
def load(raw_value)
|
81
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('l*') if !value.nil?
|
82
|
+
after_load
|
105
83
|
end
|
106
84
|
end
|
107
85
|
|
108
|
-
class
|
109
|
-
def initialize(
|
110
|
-
super
|
111
|
-
self.value = @default_value
|
86
|
+
class UInt8 < Type
|
87
|
+
def initialize(options = {})
|
88
|
+
super options.merge :bit_length => 8, :sign => :unsigned
|
112
89
|
end
|
113
90
|
|
114
91
|
def dump(value=nil)
|
115
|
-
|
116
|
-
@value
|
92
|
+
before_dump( value )
|
93
|
+
@raw_value = @value
|
117
94
|
end
|
118
95
|
|
119
|
-
def load(
|
120
|
-
self.value =
|
121
|
-
|
96
|
+
def load(raw_value)
|
97
|
+
self.value = check_raw_value(raw_value)
|
98
|
+
after_load
|
122
99
|
end
|
123
100
|
end
|
124
101
|
|
125
|
-
class
|
126
|
-
def initialize(
|
127
|
-
|
128
|
-
|
102
|
+
class BitField < Type
|
103
|
+
def initialize(options = {})
|
104
|
+
length = 32 if length > 32
|
105
|
+
super options.merge :bit_length => length, :sign => :unsigned
|
129
106
|
end
|
130
107
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
108
|
+
def format
|
109
|
+
if bit_length <= 8 # 8 bits
|
110
|
+
'C*'
|
111
|
+
elsif bit_length <= 16 # 16 bits
|
112
|
+
'v*'
|
113
|
+
else # 32 bits
|
114
|
+
'l*'
|
115
|
+
end
|
139
116
|
end
|
140
|
-
end
|
141
117
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
118
|
+
def word_length
|
119
|
+
if bit_length <= 8 # 8 bits
|
120
|
+
8
|
121
|
+
elsif bit_length <= 16 # 16 bits
|
122
|
+
16
|
123
|
+
else # 32 bits
|
124
|
+
32
|
125
|
+
end
|
146
126
|
end
|
147
127
|
|
148
128
|
def dump(value=nil)
|
149
|
-
|
150
|
-
@value
|
129
|
+
before_dump( value )
|
130
|
+
data = @value.pack(format).unpack('b*').first.chars.each_slice(word_length).map(&:join).map{|n| n.slice(0,bit_length)}
|
131
|
+
@raw_value = [data.join].pack('b*').unpack('C*')
|
151
132
|
end
|
152
133
|
|
153
|
-
def load(
|
154
|
-
self.value =
|
155
|
-
|
134
|
+
def load(raw_value)
|
135
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('b*').first.chars.slice(0,@bit_length*@count).each_slice(bit_length).map(&:join).map{|n| [n].pack('b*').unpack('C*').first}
|
136
|
+
after_load
|
156
137
|
end
|
157
138
|
end
|
158
139
|
|
159
140
|
class Char < Type
|
160
|
-
def initialize(
|
161
|
-
super 8, nil,
|
162
|
-
@default_value = "\x0"
|
163
|
-
self.value = @default_value
|
164
|
-
end
|
165
|
-
|
166
|
-
#@todo: corregir lo de abajo:
|
167
|
-
def self.serialize(value)
|
168
|
-
var = Char.new
|
169
|
-
var.value = value
|
170
|
-
var.serialize
|
141
|
+
def initialize(options = {})
|
142
|
+
super options.merge :bit_length => 8, :sign => nil, :default_value => "\x0"
|
171
143
|
end
|
172
144
|
|
173
145
|
def dump(value=nil)
|
174
|
-
|
175
|
-
@value.map{|v| v.ljust(@length, @default_value).slice(0,@length).unpack('C*')}
|
146
|
+
before_dump( value )
|
147
|
+
@raw_value = @value.map{|v| v.ljust(@length, @default_value).slice(0,@length).unpack('C*')}
|
176
148
|
end
|
177
149
|
|
178
|
-
def load(
|
179
|
-
self.value =
|
180
|
-
|
150
|
+
def load(raw_value)
|
151
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack("Z#{@length}") if !value.nil?
|
152
|
+
after_load
|
181
153
|
end
|
182
154
|
end
|
183
155
|
|
184
156
|
class Bool < Type
|
185
|
-
def initialize(
|
186
|
-
super 1, :
|
187
|
-
self.value = 0
|
157
|
+
def initialize(options = {})
|
158
|
+
super options.merge :bit_length => 1, :default_value => false
|
188
159
|
end
|
189
160
|
|
190
161
|
def dump(value=nil)
|
191
|
-
|
192
|
-
|
162
|
+
before_dump( value )
|
163
|
+
@raw_value = Array(@value.map{|v| v ? 1 : 0}.join).pack('b*').unpack('C*')
|
193
164
|
end
|
194
165
|
|
195
|
-
def load(
|
196
|
-
self.value =
|
197
|
-
|
166
|
+
def load(raw_value)
|
167
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('b*').first.slice(0,size*8).split('').map(&:to_i) if !value.nil?
|
168
|
+
after_load
|
198
169
|
end
|
199
170
|
end
|
200
171
|
|
201
172
|
class Float32 < Type
|
202
|
-
def initialize(
|
203
|
-
super 32, nil,
|
204
|
-
@default_value = 0.0
|
205
|
-
self.value = @default_value
|
173
|
+
def initialize(options = {})
|
174
|
+
super options.merge :bit_length => 32, :sign => nil, :default_value => 0.0
|
206
175
|
end
|
207
176
|
|
208
177
|
def dump(value=nil)
|
209
|
-
|
210
|
-
@value.pack('e*').unpack('C*')
|
178
|
+
before_dump( value )
|
179
|
+
@raw_value = @value.pack('e*').unpack('C*')
|
211
180
|
end
|
212
181
|
|
213
|
-
def load(
|
214
|
-
self.value =
|
215
|
-
|
182
|
+
def load(raw_value)
|
183
|
+
self.value = check_raw_value(raw_value).pack('C*').unpack('e*') if !value.nil?
|
184
|
+
after_load
|
216
185
|
end
|
217
186
|
end
|
218
187
|
end
|
@@ -16,6 +16,12 @@ class Producto
|
|
16
16
|
instance_values
|
17
17
|
end
|
18
18
|
|
19
|
+
def attributes=(hash)
|
20
|
+
hash.each do |key, value|
|
21
|
+
instance_variable_set("@#{key}", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
19
25
|
# def metodo
|
20
26
|
# self.instance_variable_get("@variable")
|
21
27
|
# end
|
@@ -24,49 +30,44 @@ class Producto
|
|
24
30
|
# self.instance_variable_set("@variable", value)
|
25
31
|
# end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def initialize
|
39
|
-
@start_address = 0
|
40
|
-
@id = 1
|
41
|
-
@silo = 0
|
42
|
-
@nombre = "MAIZ"
|
43
|
-
@total_acumulado = 50
|
44
|
-
@bits1 = 1
|
45
|
-
@bits2 = 1
|
46
|
-
@total_acumulado_1 = 20
|
47
|
-
@float= 1.2345678
|
48
|
-
@variable = '012345678901234567890123456789'
|
33
|
+
int16 :id
|
34
|
+
int16 :silo
|
35
|
+
char :nombre, count: 1, length: 20
|
36
|
+
int32 :total_acumulado
|
37
|
+
bool :bits1
|
38
|
+
bool :bits2
|
39
|
+
int32 :total_acumulado_1
|
40
|
+
float32 :float
|
41
|
+
char :variable, count: 1, length: 20 do |field, mode|
|
42
|
+
puts (mode.to_s + ': variable block').blue
|
49
43
|
end
|
50
44
|
end
|
51
45
|
|
46
|
+
|
52
47
|
orig = Producto.new
|
48
|
+
orig.start_address = 0
|
49
|
+
orig.id = 1
|
50
|
+
orig.silo = 0
|
51
|
+
orig.nombre = "MAIZ"
|
52
|
+
orig.total_acumulado = 50
|
53
|
+
orig.bits1 = 1
|
54
|
+
orig.bits2 = 1
|
55
|
+
orig.total_acumulado_1 = 20
|
56
|
+
orig.float= 1.2345678
|
57
|
+
orig.variable = '012345678901234567890123456789'
|
53
58
|
|
54
59
|
puts 'Datos originales...'
|
55
60
|
puts orig.inspect.green
|
56
61
|
|
57
62
|
puts 'serializando...'
|
58
63
|
serial = orig.to_bytes do |b|
|
59
|
-
puts '
|
60
|
-
b.variable = b.variable.map {|c| (c.ord+10).chr}
|
61
|
-
puts '@variable modificada: ', b.variable
|
64
|
+
puts 'to_bytes block'.blue
|
62
65
|
end
|
63
66
|
|
64
67
|
puts serial.inspect.yellow
|
65
68
|
|
66
69
|
puts 'deserializando...'
|
67
70
|
deser = Producto.new.from_bytes serial do |b|
|
68
|
-
puts '
|
69
|
-
b.variable = b.variable.map {|c| (c.ord-10).chr}
|
70
|
-
puts 'datos modificados: ', b.variable
|
71
|
+
puts 'from_bytes block'.blue
|
71
72
|
end
|
72
73
|
puts deser.inspect.green
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_model_serializers_binary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ByS Sistemas de Control
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -237,6 +237,7 @@ files:
|
|
237
237
|
- active_model_serializers_binary.gemspec
|
238
238
|
- lib/active_model_serializers_binary.rb
|
239
239
|
- lib/active_model_serializers_binary/active_model_serializers_binary.rb
|
240
|
+
- lib/active_model_serializers_binary/base_type.rb
|
240
241
|
- lib/active_model_serializers_binary/data_types.rb
|
241
242
|
- lib/active_model_serializers_binary/version.rb
|
242
243
|
- lib/tasks/active_model_serializers_binary_tasks.rake
|