active_model_serializers_binary 0.0.10 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|