Class: Tros::Schema
- Inherits:
-
Object
- Object
- Tros::Schema
- Defined in:
- lib/tros/schema.rb
Direct Known Subclasses
ArraySchema, Field, MapSchema, NamedSchema, PrimitiveSchema, UnionSchema
Defined Under Namespace
Classes: ArraySchema, EnumSchema, Field, FixedSchema, MapSchema, NamedSchema, PrimitiveSchema, RecordSchema, UnionSchema
Constant Summary collapse
- PRIMITIVE_TYPES =
Sets of strings, for backwards compatibility. See below for sets of symbols, for better performance.
Set.new(%w[null boolean string bytes int long float double])
- NAMED_TYPES =
Set.new(%w[fixed enum record error])
- VALID_TYPES =
PRIMITIVE_TYPES + NAMED_TYPES + Set.new(%w[array map union request])
- PRIMITIVE_TYPES_SYM =
Set.new(PRIMITIVE_TYPES.map(&:to_sym))
- NAMED_TYPES_SYM =
Set.new(NAMED_TYPES.map(&:to_sym))
- VALID_TYPES_SYM =
Set.new(VALID_TYPES.map(&:to_sym))
- INT_MIN_VALUE =
-(1 << 31)
- INT_MAX_VALUE =
(1 << 31) - 1
- LONG_MIN_VALUE =
-(1 << 63)
- LONG_MAX_VALUE =
(1 << 63) - 1
Instance Attribute Summary collapse
-
#type_sym ⇒ Object
readonly
Returns the value of attribute type_sym.
Class Method Summary collapse
- .parse(json_string) ⇒ Object
-
.real_parse(json_obj, names = nil, default_namespace = nil) ⇒ Object
Build Tros Schema from data parsed out of JSON string.
-
.validate(expected_schema, datum, validator_method = :validate) ⇒ Object
Determine if a ruby datum is an instance of a schema.
-
.validate_strictly(expected_schema, datum, validator_method = :validate_strictly) ⇒ Object
Determine if a ruby datum is an instance of a schema.
Instance Method Summary collapse
- #==(other, seen = nil) ⇒ Object
- #hash(seen = nil) ⇒ Object
-
#initialize(type) ⇒ Schema
constructor
A new instance of Schema.
- #subparse(json_obj, names = nil, namespace = nil) ⇒ Object
- #to_avro(names = nil) ⇒ Object
- #to_s ⇒ Object
-
#type ⇒ Object
Returns the type as a string (rather than a symbol), for backwards compatibility.
Constructor Details
#initialize(type) ⇒ Schema
Returns a new instance of Schema.
140 141 142 |
# File 'lib/tros/schema.rb', line 140 def initialize(type) @type_sym = type.is_a?(Symbol) ? type : type.to_sym end |
Instance Attribute Details
#type_sym ⇒ Object (readonly)
Returns the value of attribute type_sym.
144 145 146 |
# File 'lib/tros/schema.rb', line 144 def type_sym @type_sym end |
Class Method Details
.parse(json_string) ⇒ Object
35 36 37 |
# File 'lib/tros/schema.rb', line 35 def self.parse(json_string) real_parse(JSON.load("[#{json_string}]").first, {}) end |
.real_parse(json_obj, names = nil, default_namespace = nil) ⇒ Object
Build Tros Schema from data parsed out of JSON string.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/tros/schema.rb', line 40 def self.real_parse(json_obj, names=nil, default_namespace=nil) if json_obj.is_a? Hash type = json_obj['type'] raise SchemaParseError, %Q(No "type" property: #{json_obj}) if type.nil? # Check that the type is valid before calling #to_sym, since symbols are never garbage # collected (important to avoid DoS if we're accepting schemas from untrusted clients) unless VALID_TYPES.include?(type) raise SchemaParseError, "Unknown type: #{type}" end type_sym = type.to_sym if PRIMITIVE_TYPES_SYM.include?(type_sym) return PrimitiveSchema.new(type_sym) elsif NAMED_TYPES_SYM.include? type_sym name = json_obj['name'] namespace = json_obj.include?('namespace') ? json_obj['namespace'] : default_namespace case type_sym when :fixed size = json_obj['size'] return FixedSchema.new(name, namespace, size, names) when :enum symbols = json_obj['symbols'] return EnumSchema.new(name, namespace, symbols, names) when :record, :error fields = json_obj['fields'] return RecordSchema.new(name, namespace, fields, names, type_sym) else raise SchemaParseError.new("Unknown named type: #{type}") end else case type_sym when :array return ArraySchema.new(json_obj['items'], names, default_namespace) when :map return MapSchema.new(json_obj['values'], names, default_namespace) else raise SchemaParseError.new("Unknown Valid Type: #{type}") end end elsif json_obj.is_a? Array # JSON array (union) return UnionSchema.new(json_obj, names, default_namespace) elsif PRIMITIVE_TYPES.include? json_obj return PrimitiveSchema.new(json_obj) else msg = "#{json_obj.inspect} is not a schema we know about." raise SchemaParseError.new(msg) end end |
.validate(expected_schema, datum, validator_method = :validate) ⇒ Object
Determine if a ruby datum is an instance of a schema
95 96 97 98 99 100 101 102 103 |
# File 'lib/tros/schema.rb', line 95 def self.validate(expected_schema, datum, validator_method = :validate) return true if validate_strictly(expected_schema, datum, validator_method) case expected_schema.type_sym when :float, :double datum.is_a?(Numeric) else return false end end |
.validate_strictly(expected_schema, datum, validator_method = :validate_strictly) ⇒ Object
Determine if a ruby datum is an instance of a schema
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/tros/schema.rb', line 106 def self.validate_strictly(expected_schema, datum, validator_method = :validate_strictly) case expected_schema.type_sym when :null datum.nil? when :boolean datum == true || datum == false when :string, :bytes datum.is_a? String when :int datum.is_a?(Integer) && (INT_MIN_VALUE <= datum) && (datum <= INT_MAX_VALUE) when :long datum.is_a?(Integer) && (LONG_MIN_VALUE <= datum) && (datum <= LONG_MAX_VALUE) when :float, :double datum.is_a?(Float) || datum.is_a?(BigDecimal) when :fixed datum.is_a?(String) && datum.size == expected_schema.size when :enum expected_schema.symbols.include? datum when :array datum.is_a?(Array) && datum.all?{|d| send(validator_method, expected_schema.items, d) } when :map datum.keys.all?{|k| k.is_a? String } && datum.values.all?{|v| send(validator_method, expected_schema.values, v) } when :union expected_schema.schemas.any? { |s| send(validator_method, s, datum) } when :record, :error, :request datum.is_a?(Hash) && expected_schema.fields.all? { |f| send(validator_method, f.type, datum[f.name]) } else raise TypeError, "#{expected_schema.inspect} is not recognized as type." end end |
Instance Method Details
#==(other, seen = nil) ⇒ Object
150 151 152 |
# File 'lib/tros/schema.rb', line 150 def ==(other, seen=nil) other.is_a?(Schema) && type_sym == other.type_sym end |
#hash(seen = nil) ⇒ Object
154 155 156 |
# File 'lib/tros/schema.rb', line 154 def hash(seen=nil) type_sym.hash end |
#subparse(json_obj, names = nil, namespace = nil) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/tros/schema.rb', line 158 def subparse(json_obj, names=nil, namespace=nil) if json_obj.is_a?(String) && names fullname = Name.make_fullname(json_obj, namespace) return names[fullname] if names.include?(fullname) end begin Schema.real_parse(json_obj, names, namespace) rescue => e raise e if e.is_a? SchemaParseError raise SchemaParseError, "Sub-schema for #{self.class.name} not a valid Tros schema. Bad schema: #{json_obj}" end end |
#to_avro(names = nil) ⇒ Object
172 173 174 |
# File 'lib/tros/schema.rb', line 172 def to_avro(names=nil) {'type' => type} end |
#to_s ⇒ Object
176 177 178 |
# File 'lib/tros/schema.rb', line 176 def to_s to_avro.to_json end |
#type ⇒ Object
Returns the type as a string (rather than a symbol), for backwards compatibility. Deprecated in favor of #type_sym.
148 |
# File 'lib/tros/schema.rb', line 148 def type; @type_sym.to_s; end |