icss 0.0.2

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.
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