icss 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.document +5 -0
  2. data/.rspec +3 -0
  3. data/.watchr +20 -0
  4. data/CHANGELOG.textile +8 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +34 -0
  7. data/LICENSE.textile +20 -0
  8. data/README.textile +19 -0
  9. data/Rakefile +43 -0
  10. data/VERSION +1 -0
  11. data/examples/BulkData.avpr +21 -0
  12. data/examples/complicated.icss.yaml +158 -0
  13. data/examples/interop.avsc +32 -0
  14. data/examples/mail.avpr +20 -0
  15. data/examples/namespace.avpr +28 -0
  16. data/examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
  17. data/examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
  18. data/examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
  19. data/examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
  20. data/examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
  21. data/examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
  22. data/examples/simple.avpr +70 -0
  23. data/examples/weather.avsc +9 -0
  24. data/icss.gemspec +104 -0
  25. data/icss_specification.textile +370 -0
  26. data/init.rb +3 -0
  27. data/lib/icss.rb +19 -0
  28. data/lib/icss/brevity.rb +136 -0
  29. data/lib/icss/code_asset.rb +16 -0
  30. data/lib/icss/core_ext.rb +4 -0
  31. data/lib/icss/data_asset.rb +22 -0
  32. data/lib/icss/message.rb +72 -0
  33. data/lib/icss/old.rb +96 -0
  34. data/lib/icss/protocol.rb +138 -0
  35. data/lib/icss/protocol_set.rb +48 -0
  36. data/lib/icss/sample_message_call.rb +140 -0
  37. data/lib/icss/target.rb +71 -0
  38. data/lib/icss/type.rb +517 -0
  39. data/lib/icss/type/factory.rb +196 -0
  40. data/lib/icss/validations.rb +16 -0
  41. data/lib/icss/view_helper.rb +28 -0
  42. data/spec/icss_spec.rb +7 -0
  43. data/spec/spec_helper.rb +31 -0
  44. metadata +218 -0
@@ -0,0 +1,71 @@
1
+ module Icss
2
+
3
+ #
4
+ # Instantiates an array of target objects
5
+ #
6
+ class TargetListFactory
7
+ def self.receive target_name, target_info_list
8
+ klass = ("Icss::"+target_name.camelize+"Target").constantize
9
+ target_info_list.map{|target_info| klass.receive(target_info)}
10
+ end
11
+ end
12
+
13
+ class Target
14
+ include Receiver
15
+ include Receiver::ActsAsHash
16
+ #
17
+ # Name should not be something like 'default', it should be something
18
+ # that 'appeals' to the message name.
19
+ #
20
+ rcvr_accessor :name, String
21
+ end
22
+
23
+ class MysqlTarget < Target
24
+ rcvr_accessor :data_assets, Array, :of => String
25
+ rcvr_accessor :database, String
26
+ rcvr_accessor :table_name, String
27
+ end
28
+
29
+ class ApeyeyeTarget < Target
30
+ rcvr_accessor :code_assets, Array, :of => String
31
+ end
32
+
33
+ class HbaseTarget < Target
34
+ rcvr_accessor :data_assets, Array, :of => String
35
+ rcvr_accessor :table_name, String
36
+ rcvr_accessor :column_families, Array, :of => String
37
+ rcvr_accessor :column_family, String
38
+ rcvr_accessor :loader, String
39
+ rcvr_accessor :id_field, String
40
+ end
41
+
42
+ class ElasticSearchTarget < Target
43
+ rcvr_accessor :data_assets, Array, :of => String
44
+ rcvr_accessor :index_name, String
45
+ rcvr_accessor :id_field, String
46
+ rcvr_accessor :object_type, String
47
+ rcvr_accessor :loader, String
48
+ end
49
+
50
+ class GeoIndexTarget < Target
51
+ rcvr_accessor :data_assets, Array, :of => String
52
+ rcvr_accessor :table_name, String
53
+ rcvr_accessor :min_zoom, Integer
54
+ rcvr_accessor :max_zoom, Integer
55
+ rcvr_accessor :chars_per_page, Integer
56
+ rcvr_accessor :sort_field, String
57
+ end
58
+
59
+ class CatalogTarget < Target
60
+ rcvr_accessor :name, String
61
+ rcvr_accessor :license, String
62
+ rcvr_accessor :title, String
63
+ rcvr_accessor :link, String
64
+ rcvr_accessor :description, String
65
+ rcvr_accessor :owner, String
66
+ rcvr_accessor :price, Float
67
+ rcvr_accessor :tags, Array, :of => String
68
+ rcvr_accessor :messages, Array, :of => String
69
+ rcvr_accessor :packages, Array, :of => Hash
70
+ end
71
+ end
data/lib/icss/type.rb ADDED
@@ -0,0 +1,517 @@
1
+ module Icss
2
+ #
3
+ # Describes an avro type
4
+ #
5
+ # A Schema is represented in JSON by one of:
6
+ #
7
+ # * A JSON string, naming a defined type.
8
+ # * A JSON object, of the form:
9
+ # {"type": "typeName" ...attributes...}
10
+ # where typeName is either a primitive or derived type name, as defined
11
+ # in the Icss::Type class
12
+ # * A JSON array, representing a union of embedded types.
13
+ #
14
+ #
15
+ class Type
16
+ include Receiver
17
+ rcvr_accessor :name, String
18
+ rcvr_accessor :doc, String
19
+ # Schema factory
20
+ rcvr_accessor :ruby_klass, Object
21
+ rcvr_accessor :pig_name, String
22
+ rcvr_accessor :mysql_name, String
23
+
24
+ #
25
+ # Factory methods
26
+ #
27
+
28
+ # Registry for synthesized types (eg the result of a type record definition)
29
+ Icss::Type::DERIVED_TYPES = {} unless defined?(Icss::Type::DERIVED_TYPES)
30
+
31
+ # VALID_TYPES, PRIMITIVE_TYPES, etc are way down below (the klasses need to
32
+ # be defined first)
33
+
34
+ #
35
+ def self.find type_name
36
+ if type_name.to_s.include?('.')
37
+ warn "crap. can't properly do namespaced types yet."
38
+ type_name = type_name.to_s.gsub(/(.*)\./, "")
39
+ end
40
+ VALID_TYPES[type_name.to_sym] || DERIVED_TYPES[type_name.to_sym]
41
+ end
42
+
43
+ def self.primitive? name
44
+ PRIMITIVE_TYPES.include?(name.to_sym)
45
+ end
46
+ def primitive?
47
+ false
48
+ end
49
+
50
+ def title
51
+ self.name
52
+ end
53
+
54
+ #
55
+ # Schema Translation
56
+ #
57
+ def self.pig_name
58
+ "undefined_#{self.to_s.underscore}"
59
+ end
60
+ #
61
+ # Conversion
62
+ #
63
+
64
+ def to_hash()
65
+ {:name => name, :doc => doc }.reject{|k,v| v.nil? }
66
+ end
67
+ # This will cause funny errors when it is an element of something that's to_json'ed
68
+ def to_json() to_hash.to_json ; end
69
+ end
70
+
71
+ # ---------------------------------------------------------------------------
72
+ #
73
+ # Primitive Types
74
+ #
75
+
76
+ class PrimitiveType < Type
77
+ def to_hash
78
+ name.to_s
79
+ end
80
+ def primitive?
81
+ true
82
+ end
83
+ end
84
+
85
+ # Registry for primitive types
86
+ unless defined?(::Icss::Type::PRIMITIVE_TYPES)
87
+ ::Icss::Type::PRIMITIVE_TYPES = {}
88
+ ::Icss::Type::PRIMITIVE_TYPES[:null] = PrimitiveType.receive(:ruby_klass => NilClass, :pig_name => 'FIXME WHAT GOES HERE' )
89
+ ::Icss::Type::PRIMITIVE_TYPES[:boolean] = PrimitiveType.receive(:ruby_klass => Boolean, :pig_name => 'FIXME WHAT GOES HERE')
90
+ ::Icss::Type::PRIMITIVE_TYPES[:string] = PrimitiveType.receive(:ruby_klass => String, :pig_name => 'chararray',:mysql_name => 'VARCHAR')
91
+ ::Icss::Type::PRIMITIVE_TYPES[:bytes] = PrimitiveType.receive(:ruby_klass => String, :pig_name => 'bytearray',:mysql_name => 'VARCHAR')
92
+ ::Icss::Type::PRIMITIVE_TYPES[:int] = PrimitiveType.receive(:ruby_klass => Integer, :pig_name => 'int',:mysql_name => 'INT')
93
+ ::Icss::Type::PRIMITIVE_TYPES[:long] = PrimitiveType.receive(:ruby_klass => Integer, :pig_name => 'long',:mysql_name => 'BIGINT')
94
+ ::Icss::Type::PRIMITIVE_TYPES[:float] = PrimitiveType.receive(:ruby_klass => Float, :pig_name => 'float',:mysql_name => 'FLOAT')
95
+ ::Icss::Type::PRIMITIVE_TYPES[:double] = PrimitiveType.receive(:ruby_klass => Float, :pig_name => 'double',:mysql_name => 'DOUBLE')
96
+ #
97
+ ::Icss::Type::PRIMITIVE_TYPES[:symbol] = PrimitiveType.receive(:ruby_klass => Symbol, :pig_name => 'chararray')
98
+ ::Icss::Type::PRIMITIVE_TYPES[:time] = PrimitiveType.receive(:ruby_klass => Time, :pig_name => 'chararray')
99
+ ::Icss::Type::PRIMITIVE_TYPES[:date] = PrimitiveType.receive(:ruby_klass => Date, :pig_name => 'chararray')
100
+ ::Icss::Type::PRIMITIVE_TYPES.freeze
101
+ end
102
+
103
+ # ---------------------------------------------------------------------------
104
+ #
105
+ # Complex Types
106
+ #
107
+
108
+ #
109
+ # Record, enums and fixed are named types. Each has a fullname that is
110
+ # composed of two parts; a name and a namespace. Equality of names is defined
111
+ # on the fullname.
112
+ #
113
+ # The name portion of a fullname, and record field names must:
114
+ # * start with [A-Za-z_]
115
+ # * subsequently contain only [A-Za-z0-9_]
116
+ # * A namespace is a dot-separated sequence of such names.
117
+ #
118
+ # References to previously defined names are as in the latter two cases above:
119
+ # if they contain a dot they are a fullname, if they do not contain a dot, the
120
+ # namespace is the namespace of the enclosing definition.
121
+ #
122
+ # Primitive type names have no namespace and their names may not be defined in
123
+ # any namespace. A schema may only contain multiple definitions of a fullname
124
+ # if the definitions are equivalent.
125
+ #
126
+ #
127
+ class NamedType < Type
128
+ rcvr_accessor :namespace, String
129
+ attr_accessor :parent
130
+ # the avro base type name
131
+ class_attribute :type
132
+ include Icss::Validations
133
+
134
+ # In named types, the namespace and name are determined in one of the following ways:
135
+ #
136
+ # * A name and namespace are both specified. For example, one might use
137
+ # "name": "X", "namespace": "org.foo" to indicate the fullname org.foo.X.
138
+ #
139
+ # * A fullname is specified. If the name specified contains a dot, then it is
140
+ # assumed to be a fullname, and any namespace also specified is ignored. For
141
+ # example, use "name": "org.foo.X" to indicate the fullname org.foo.X.
142
+ #
143
+ # * A name only is specified, i.e., a name that contains no dots. In this case
144
+ # the namespace is taken from the most tightly enclosing schema or
145
+ # protocol. For example, if "name": "X" is specified, and this occurs within
146
+ # a field of the record definition of org.foo.Y, then the fullname is
147
+ # org.foo.X.
148
+ #
149
+ def name= nm
150
+ if nm.include?('.')
151
+ split_name = nm.split('.')
152
+ @use_fullname = true
153
+ @name = split_name.pop
154
+ @namespace = split_name.join('.')
155
+ else
156
+ @name = nm
157
+ end
158
+ ::Icss::Type::DERIVED_TYPES[@name.to_sym] = self
159
+ @name
160
+ end
161
+
162
+ def receive_namespace nmsp
163
+ # If the namespace is given in the name (using a dotted name string) then
164
+ # any namespace also specified is ignored.
165
+ if @namespace then warn "Warning: namespace already set, ignoring" and return ; end
166
+ @namespace = nmsp
167
+ end
168
+
169
+ def namespace
170
+ @namespace || (parent ? parent.namespace : "")
171
+ end
172
+
173
+ #
174
+ # If no explicit namespace is specified, the namespace is taken from the
175
+ # most tightly enclosing schema or protocol. For example, if "name": "X" is
176
+ # specified, and this occurs within a field of the record definition of
177
+ # org.foo.Y, then the fullname is org.foo.X.
178
+ #
179
+ def fullname
180
+ [namespace, name].reject(&:blank?).join('.')
181
+ end
182
+
183
+ def to_hash
184
+ hsh = super
185
+ if @use_fullname then hsh[:name] = fullname
186
+ elsif @namespace then hsh.merge!( :namespace => @namespace ) ; end
187
+ hsh.merge( :type => self.class.type )
188
+ end
189
+ end
190
+
191
+ #
192
+ # Avro Schema Declaration
193
+ #
194
+ # A Schema is represented in JSON by one of:
195
+ #
196
+ # * A JSON string, naming a defined type.
197
+ # * A JSON object, of the form:
198
+ # {"type": "typeName" ...attributes...}
199
+ # where typeName is either a primitive or derived type name, as defined
200
+ # in the Icss::Type class
201
+ # * A JSON array, representing a union of embedded types.
202
+ #
203
+ #
204
+ class TypeFactory
205
+ def self.receive type_info
206
+ # p ['----------', self, 'receive', type_info] # , Icss::Type::DERIVED_TYPES]
207
+ case
208
+ when type_info.is_a?(Icss::Type)
209
+ type_info
210
+ when type_info.is_a?(String) || type_info.is_a?(Symbol)
211
+ Icss::Type.find(type_info)
212
+ when type_info.is_a?(Array)
213
+ UnionType.receive(type_info)
214
+ else
215
+ type_info = type_info.symbolize_keys
216
+ raise "No type was given in #{type_info.inspect}" if type_info[:type].blank?
217
+ type_name = type_info[:type].to_sym
218
+ type = Icss::Type.find(type_name)
219
+ obj = type.receive(type_info)
220
+ end
221
+ end
222
+ end
223
+
224
+ #
225
+ # Describes a field in an Avro Record object.
226
+ #
227
+ # Each field has the following attributes:
228
+ # * name: a string providing the name of the field (required), and
229
+ # * doc: a string describing this field for users (optional).
230
+ # * type: a schema, or a string or symbol naming a record definition (required).
231
+ #
232
+ # avro type json type ruby type example
233
+ # null null NilClass nil
234
+ # boolean boolean Boolean true
235
+ # int,long integer Integer 1
236
+ # float,double number Float 1.1
237
+ # bytes string String "\u00FF"
238
+ # string string String "foo"
239
+ # record object RecordType {"a": 1}
240
+ # enum string Enum "FOO"
241
+ # array array Array [1]
242
+ # map object Hash { "a": 1 }
243
+ # fixed string String "\u00ff"
244
+ #
245
+ # * default: a default value for this field, used when reading instances that
246
+ # lack this field (optional). Permitted values depend on the
247
+ # field's schema type, according to the table below. Default
248
+ # values for union fields correspond to the first schema in the
249
+ # union. Default values for bytes and fixed fields are JSON
250
+ # strings, where Unicode code points 0-255 are mapped to unsigned
251
+ # 8-bit byte values 0-255.
252
+ #
253
+ # * order: specifies how this field impacts sort ordering of this record
254
+ # (optional). Valid values are "ascending" (the default),
255
+ # "descending", or "ignore". For more details on how this is used,
256
+ # see the the sort order section below.
257
+ #
258
+ # * required: raises an error if the field is unset when validate! is called
259
+ #
260
+ # See RecordType for examples.
261
+ #
262
+ class RecordField
263
+ include Receiver
264
+ include Receiver::ActsAsHash
265
+ rcvr_accessor :name, String, :required => true
266
+ rcvr_accessor :doc, String
267
+ attr_accessor :type # work around a bug in ruby 1.8, which has defined (and deprecated) type
268
+ rcvr_accessor :type, Icss::Type, :required => true
269
+ rcvr_accessor :default, Object
270
+ rcvr :order, String
271
+ rcvr_accessor :required, Boolean
272
+
273
+ # is_reference is true if the type is a named reference to a defined type;
274
+ # false if the type was defined right here in the schema.
275
+ attr_accessor :is_reference
276
+ def is_reference?() is_reference ; end
277
+
278
+ def receive_type type_info
279
+ self.is_reference = type_info.is_a?(String) || type_info.is_a?(Symbol)
280
+ self.type = TypeFactory.receive(type_info)
281
+ end
282
+
283
+ ALLOWED_ORDERS = %w[ascending descending ignore].freeze unless defined?(ALLOWED_ORDERS)
284
+ def order
285
+ @order || 'ascending'
286
+ end
287
+ def order_direction
288
+ case order when 'ascending' then 1 when 'descending' then -1 else 0 ; end
289
+ end
290
+ # QUESTION: should this be an override of order=, or of receive_order?
291
+ def order= v
292
+ raise "'order' may only take the values ascending (the default), descending, or ignore." unless v.nil? || ALLOWED_ORDERS.include?(v)
293
+ @order = v
294
+ end
295
+
296
+ def record?() type.is_a? Icss::RecordType end
297
+ def union?() type.is_a? Array end
298
+ def enum?() type.is_a? Icss::EnumType end
299
+
300
+ def to_hash()
301
+ { :name => name,
302
+ :type => expand_type,
303
+ :default => default,
304
+ :order => @order,
305
+ :doc => doc,
306
+ }.reject{|k,v| v.nil? }
307
+ end
308
+
309
+ def expand_type
310
+ case
311
+ when is_reference? && type.respond_to?(:name) then type.name
312
+ when is_reference? then '(_unspecified_)'
313
+ when type.is_a?(Array) then type.map{|t| t.to_hash }
314
+ when type.respond_to?(:to_hash) then type.to_hash
315
+ else type.to_s
316
+ end
317
+ end
318
+ end
319
+
320
+ #
321
+ # Icss/Avro Record type
322
+ #
323
+ # Records use the type name "record" and support these attributes:
324
+ #
325
+ # * name: a string providing the name of the record (required).
326
+ # * namespace: a string that qualifies the name;
327
+ # * doc: a string providing documentation to the user of this schema (optional).
328
+ # * fields: an array of RecordField's (required).
329
+ #
330
+ # For example, a linked-list of 64-bit values may be defined with:
331
+ #
332
+ # {
333
+ # "type": "record",
334
+ # "name": "LongList",
335
+ # "fields" : [
336
+ # {"name": "value", "type": "long"}, // each element has a long
337
+ # {"name": "next", "type": ["LongList", "null"]} // optional next element
338
+ # ]
339
+ # }
340
+ #
341
+ class RecordType < NamedType
342
+ rcvr_accessor :fields, Array, :of => Icss::RecordField, :required => true
343
+ self.type = :record
344
+
345
+ def to_hash
346
+ super.merge( :fields => (fields||[]).map{|field| field.to_hash} )
347
+ end
348
+ end
349
+
350
+ # An error definition is just like a record definition except it uses "error" instead of "record".
351
+ class ErrorType < RecordType
352
+ self.type = :error
353
+ end
354
+
355
+ #
356
+ # Describes an Avro Enum type.
357
+ #
358
+ # Enums use the type name "enum" and support the following attributes:
359
+ #
360
+ # name: a string providing the name of the enum (required).
361
+ # namespace: a string that qualifies the name;
362
+ # doc: a string providing documentation to the user of this schema (optional).
363
+ # symbols: an array, listing symbols, as strings or ruby symbols (required). All
364
+ # symbols in an enum must be unique; duplicates are prohibited.
365
+ #
366
+ # For example, playing card suits might be defined with:
367
+ #
368
+ # { "type": "enum",
369
+ # "name": "Suit",
370
+ # "symbols" : ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
371
+ # }
372
+ #
373
+ class EnumType < NamedType
374
+ rcvr_accessor :symbols, Array, :of => String, :required => true
375
+ self.type = :enum
376
+
377
+ def to_hash
378
+ super.merge( :symbols => symbols )
379
+ end
380
+ end
381
+
382
+ #
383
+ # base class for Avro enumerable types (array, map and union)
384
+ #
385
+ # (do not confuse with EnumType, which is not an EnumerableType. sigh).
386
+ #
387
+ class EnumerableType < Type
388
+ class_attribute :type
389
+ class_attribute :ruby_klass
390
+ def to_hash
391
+ super.merge( :type => type.to_s )
392
+ end
393
+ end
394
+
395
+ #
396
+ # ArrayType describes an Avro Array type.
397
+ #
398
+ # Arrays use the type name "array" and support a single attribute:
399
+ #
400
+ # * items: the schema of the array's items.
401
+ #
402
+ # @example, an array of strings is declared with:
403
+ #
404
+ # {"type": "array", "items": "string"}
405
+ #
406
+ class ArrayType < EnumerableType
407
+ # FIXME: is items required? The schema doesn't say so.
408
+ rcvr_accessor :items, TypeFactory, :required => true
409
+ self.type = :array
410
+ self.ruby_klass = Array
411
+
412
+ def title
413
+ "array of #{items.title}"
414
+ end
415
+
416
+ def to_hash
417
+ super.merge( :items => (items && items.name) )
418
+ end
419
+ end
420
+
421
+ #
422
+ # MapType describes an Avro Map type (which corresponds to a Ruby
423
+ # Hash). HashType is a synonym for MapType.
424
+ #
425
+ # Maps use the type name "map" and support one attribute:
426
+ #
427
+ # * values: the schema of the map's values. Avro Map keys are assumed to be strings.
428
+ #
429
+ # @example, a map from string to long is declared with:
430
+ #
431
+ # {"type": "map", "values": "long"}
432
+ #
433
+ class MapType < EnumerableType
434
+ # FIXME: is items required? The schema doesn't say so.
435
+ rcvr_accessor :values, TypeFactory, :required => true
436
+ self.type = :map
437
+ self.ruby_klass = Hash
438
+
439
+ def to_hash
440
+ super.merge( :values => values.to_hash )
441
+ end
442
+ end
443
+ HashType = MapType unless defined?(HashType)
444
+
445
+ #
446
+ # Describes an Avro Union type.
447
+ #
448
+ # Unions are represented using JSON arrays. For example, ["string", "null"]
449
+ # declares a schema which may be either a string or null.
450
+ #
451
+ # Unions may not contain more than one schema with the same type, except for
452
+ # the named types record, fixed and enum. For example, unions containing two
453
+ # array types or two map types are not permitted, but two types with different
454
+ # names are permitted. (Names permit efficient resolution when reading and
455
+ # writing unions.)
456
+ #
457
+ # Unions may not immediately contain other unions.
458
+ #
459
+ class UnionType < EnumerableType
460
+ attr_accessor :available_types
461
+ attr_accessor :referenced_types
462
+ self.type = :union
463
+
464
+ def receive! type_list
465
+ self.available_types = type_list.map do |type_info|
466
+ type = TypeFactory.receive(type_info)
467
+ (referenced_types||=[]) << type if (type_info.is_a?(String) || type_info.is_a?(Symbol))
468
+ type
469
+ end
470
+ end
471
+
472
+ def to_hash
473
+ available_types.map{|t| t.name } # (referenced_types||=[]).include?(t) ? t.name : t.to_hash }
474
+ end
475
+ end
476
+
477
+ #
478
+ # Describes an Avro Fixed type.
479
+ #
480
+ # Fixed uses the type name "fixed" and supports the attributes:
481
+ #
482
+ # * name: a string naming this fixed (required).
483
+ # * namespace, a string that qualifies the name;
484
+ # * size: an integer, specifying the number of bytes per value (required).
485
+ #
486
+ # For example, 16-byte quantity may be declared with:
487
+ #
488
+ # {"type": "fixed", "size": 16, "name": "md5"}
489
+ #
490
+ class FixedType < NamedType
491
+ rcvr_accessor :size, Integer, :required => true
492
+ class_attribute :ruby_klass
493
+ self.type = :fixed
494
+ self.ruby_klass = String
495
+
496
+ def to_hash
497
+ super.merge( :size => size )
498
+ end
499
+ end
500
+
501
+ Type.class_eval do
502
+ Icss::Type::NAMED_TYPES = {
503
+ :fixed => FixedType,
504
+ :enum => EnumType,
505
+ :record => RecordType,
506
+ :error => ErrorType
507
+ }.freeze unless defined?(Icss::Type::NAMED_TYPES)
508
+ Icss::Type::ENUMERABLE_TYPES = {
509
+ :array => ArrayType,
510
+ :map => MapType,
511
+ :union => UnionType,
512
+ # :request => RequestType,
513
+ }.freeze unless defined?(Icss::Type::ENUMERABLE_TYPES)
514
+ Icss::Type::VALID_TYPES = (Icss::Type::PRIMITIVE_TYPES.merge(Icss::Type::NAMED_TYPES.merge(Icss::Type::ENUMERABLE_TYPES))).freeze unless defined?(Icss::Type::VALID_TYPES)
515
+ Icss::Type::VALID_TYPES.each{|n, t| t.name = n if t.is_a?(Icss::Type) }
516
+ end
517
+ end