sparsam 0.1.4

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.
@@ -0,0 +1,10 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'sparsam_native'
3
+
4
+ require 'sparsam/types'
5
+ require 'sparsam/exceptions'
6
+ require 'sparsam/struct'
7
+ require 'sparsam/union'
8
+ require 'sparsam/deserializer'
9
+
10
+ Sparsam.init!
@@ -0,0 +1,97 @@
1
+ require 'set'
2
+ require 'sparsam/types'
3
+
4
+ module Sparsam
5
+ class BaseClass
6
+ class AccessorNames < Struct.new(:reader, :writer); end
7
+
8
+ def self.generate_field_syms(klass)
9
+ field_syms = {}
10
+ klass::FIELDS.each do |_, field_info|
11
+ name = field_info[:name].to_sym
12
+ accessors = AccessorNames.new(name, :"#{name}=")
13
+ field_syms[name] = accessors
14
+ field_syms[name.to_s] = accessors
15
+ end
16
+
17
+ klass.const_set(
18
+ :FIELD_SYMS,
19
+ field_syms
20
+ )
21
+ end
22
+
23
+ def self.generate_accessors(klass)
24
+ klass::FIELDS.each do |field_key, field_info|
25
+ field_accessor(klass, field_key, field_info)
26
+ qmark_isset_method(klass, field_info)
27
+ end
28
+ end
29
+
30
+ # TODO(Ben Hughes): Do we ever use those, these are an unexpected
31
+ # definition of predicate accessors
32
+ def self.qmark_isset_method(klass, field_info)
33
+ field_name = field_info[:name]
34
+
35
+ klass.class_eval(<<-EOF, __FILE__, __LINE__)
36
+ def #{field_name}?
37
+ !#{field_name}.nil?
38
+ end
39
+ EOF
40
+ end
41
+
42
+ def self.generate_default_values(klass)
43
+ fields_with_default_values = {}
44
+ klass::FIELDS.each do |fid, field_def|
45
+ unless field_def[:default].nil?
46
+ fields_with_default_values[field_def[:name]] = field_def[:default].freeze
47
+ end
48
+ end
49
+
50
+ if fields_with_default_values.empty?
51
+ klass.const_set(
52
+ :DEFAULT_VALUES,
53
+ nil
54
+ )
55
+ else
56
+ klass.const_set(
57
+ :DEFAULT_VALUES,
58
+ fields_with_default_values
59
+ )
60
+ end
61
+ end
62
+
63
+ def self.init_thrift_struct(klass)
64
+ generate_accessors(klass)
65
+ generate_field_syms(klass)
66
+ Sparsam.cache_fields(klass)
67
+ generate_default_values(klass)
68
+ klass.class_eval(<<-EOF, __FILE__, __LINE__)
69
+ def struct_fields
70
+ FIELDS
71
+ end
72
+ EOF
73
+ end
74
+
75
+ def serialize(prot = Sparsam::CompactProtocol)
76
+ validate
77
+ s = Sparsam::Serializer.new(prot, "")
78
+ s.serialize(self.class, self)
79
+ end
80
+
81
+ def validate(mode = Sparsam::NORMAL)
82
+ Sparsam.validate(self.class, self, mode)
83
+ end
84
+
85
+ private
86
+
87
+ def name_to_accessors(name)
88
+ self.class::FIELD_SYMS[name]
89
+ end
90
+
91
+ def each_field
92
+ struct_fields.each do |fid, data|
93
+ yield fid, data
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,8 @@
1
+ module Sparsam
2
+ module Deserializer
3
+ def self.deserialize(klass, serialized_string, prot = Sparsam::CompactProtocol)
4
+ s = Sparsam::Serializer.new(prot, serialized_string)
5
+ s.deserialize(klass)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ module Sparsam
4
+ class Exception < StandardError
5
+ def initialize(msg)
6
+ super
7
+ end
8
+ end
9
+
10
+ class MissingMandatory < Exception
11
+ def initialize(msg)
12
+ super
13
+ end
14
+ end
15
+
16
+ class TypeMismatch < Exception
17
+ def initialize(msg)
18
+ super
19
+ end
20
+ end
21
+
22
+ class UnionException < Exception
23
+ def initialize(msg)
24
+ super
25
+ end
26
+ end
27
+
28
+ class UnknownTypeException < Exception
29
+ def initialize(msg)
30
+ super
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'sparsam/base_class'
3
+
4
+ module Sparsam
5
+ class Struct < ::Sparsam::BaseClass
6
+ include ::Sparsam::StructInitialization
7
+
8
+ def ==(other)
9
+ return true if other.equal?(self)
10
+ return false unless other.instance_of?(self.class)
11
+
12
+ each_field do |fid, info|
13
+ reader = name_to_accessors(info[:name]).reader
14
+ return false unless send(reader) == other.send(reader)
15
+ end
16
+ end
17
+ alias_method :eql?, :==
18
+
19
+ def self.field_accessor(klass, field_key, field_info)
20
+ field_name = field_info[:name]
21
+ klass.class_eval(<<-EOF, __FILE__, __LINE__)
22
+ attr_accessor :'#{field_name}'
23
+ EOF
24
+ end
25
+
26
+ private
27
+
28
+ def assign_defaults(defaults)
29
+ defaults.each do |name, default_value|
30
+ accessors = name_to_accessors(name)
31
+ send(accessors.writer, default_value)
32
+ end
33
+ end
34
+
35
+ def assign_from_arg(d)
36
+ d.each do |name, value|
37
+ accessors = name_to_accessors(name)
38
+ unless accessors
39
+ raise Sparsam::Exception, "Unknown key given to #{self.class}.new: #{name}"
40
+ end
41
+ send(accessors.writer, value)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,108 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'set'
3
+ require 'sparsam/exceptions'
4
+
5
+ module Sparsam
6
+ module Types
7
+ STOP = 0
8
+ VOID = 1
9
+ BOOL = 2
10
+ BYTE = 3
11
+ DOUBLE = 4
12
+ I16 = 6
13
+ I32 = 8
14
+ I64 = 10
15
+ STRING = 11
16
+ STRUCT = 12
17
+ MAP = 13
18
+ SET = 14
19
+ LIST = 15
20
+
21
+ COLLECTIONS = Set.new([
22
+ SET,
23
+ LIST,
24
+ MAP,
25
+ ]).freeze
26
+ end
27
+
28
+ # Deprecated type checking
29
+
30
+ def self.check_type(value, field, name, skip_nil = true)
31
+ return if value.nil? && skip_nil
32
+
33
+ valid =
34
+ case field[:type]
35
+ when Types::VOID
36
+ nil === value
37
+ when Types::BOOL
38
+ true === value || false === value
39
+ when Types::BYTE, Types::I16, Types::I32, Types::I64
40
+ Integer === value
41
+ when Types::DOUBLE
42
+ Float === value
43
+ when Types::STRING
44
+ String === value
45
+ when Types::STRUCT
46
+ Struct === value || Union === value
47
+ when Types::MAP
48
+ Hash === value
49
+ when Types::SET
50
+ Set === value
51
+ when Types::LIST
52
+ Array === value
53
+ else
54
+ false
55
+ end
56
+
57
+ unless valid
58
+ raise TypeMismatch, "Expected #{type_name(field[:type])}, " \
59
+ "received #{value.class} for field #{name}"
60
+ end
61
+
62
+ # check elements now
63
+ case field[:type]
64
+ when Types::MAP
65
+ # This is still allocations per MAP, but better than per map entry
66
+ key_str = "#{name}.key"
67
+ value_str = "#{name}.value"
68
+
69
+ value.each_pair do |k, v|
70
+ check_type(k, field[:key], key_str, false)
71
+ check_type(v, field[:value], value_str, false)
72
+ end
73
+ when Types::SET, Types::LIST
74
+ element_str = "#{name}.element"
75
+
76
+ value.each do |el|
77
+ check_type(el, field[:element], element_str, false)
78
+ end
79
+ when Types::STRUCT
80
+ unless field[:class] == value.class
81
+ raise TypeMismatch, "Expected #{field[:class]}, received #{value.class} for field #{name}"
82
+ end
83
+ end
84
+ end
85
+
86
+ TYPE_NAME_SYM_MAPPING = Types.constants.each_with_object({}) do |const, h|
87
+ h[Types.const_get(const)] = const.to_sym
88
+ end
89
+
90
+ TYPE_NAME_MAPPING = TYPE_NAME_SYM_MAPPING.each_with_object({}) do |(k, const), h|
91
+ h[k] = "Types::#{const}".freeze
92
+ end.freeze
93
+
94
+ def self.type_name_sym(type)
95
+ TYPE_NAME_SYM_MAPPING[type]
96
+ end
97
+
98
+ def self.type_name(type)
99
+ TYPE_NAME_MAPPING[type]
100
+ end
101
+
102
+ module MessageTypes
103
+ CALL = 1
104
+ REPLY = 2
105
+ EXCEPTION = 3
106
+ ONEWAY = 4
107
+ end
108
+ end
@@ -0,0 +1,72 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'sparsam/base_class'
3
+
4
+ module Sparsam
5
+ class Union < ::Sparsam::BaseClass
6
+ def initialize(name = nil, value = nil)
7
+ if name
8
+ if name.is_a? Hash
9
+ if name.size > 1
10
+ raise ::Sparsam::UnionException,
11
+ "#{self.class} cannot be instantiated with more than one field!"
12
+ end
13
+ value = name.values.first
14
+ name = name.keys.first
15
+ end
16
+ end
17
+
18
+ if name
19
+ accessors = name_to_accessors(name)
20
+ unless accessors
21
+ raise Sparsam::Exception, "Unknown key given to #{self.class}.new: #{name}"
22
+ end
23
+
24
+ send(accessors.writer, value)
25
+ end
26
+ end
27
+
28
+ def ==(other)
29
+ other.equal?(self) ||
30
+ other.instance_of?(self.class) &&
31
+ @setfield == other.get_set_field &&
32
+ get_value == other.get_value
33
+ end
34
+ alias_method :eql?, :==
35
+
36
+ def hash
37
+ [self.class.name, @setfield, get_value].hash
38
+ end
39
+
40
+ def get_set_field
41
+ @setfield
42
+ end
43
+
44
+ def get_value
45
+ if @setfield
46
+ send(name_to_accessors(@setfield).reader)
47
+ end
48
+ end
49
+
50
+ def self.field_accessor(klass, field_key, field_info)
51
+ field_name = field_info[:name]
52
+ klass.class_eval(<<-EOF, __FILE__, __LINE__)
53
+ def #{field_name}
54
+ if :'#{field_name}' == @setfield
55
+ instance_variable_get(:'@#{field_name}')
56
+ else
57
+ raise ::Sparsam::UnionException, "#{field_name} is not union's set field"
58
+ end
59
+ end
60
+
61
+ def #{field_name}=(value)
62
+ if @setfield
63
+ remove_instance_variable(:"@\#{@setfield}")
64
+ end
65
+
66
+ @setfield = :'#{field_name}'
67
+ instance_variable_set(:'@#{field_name}', value)
68
+ end
69
+ EOF
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,9 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.1.0)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'sparsam'
8
+ require 'user_types'
9
+
@@ -0,0 +1,106 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.1.0)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'sparsam'
8
+
9
+ module Magic
10
+ Black = 0
11
+ White = 1
12
+ Red = 2
13
+ Blue = 3
14
+ Green = 4
15
+ VALUE_MAP = {0 => "Black", 1 => "White", 2 => "Red", 3 => "Blue", 4 => "Green"}
16
+ VALID_VALUES = Set.new([Black, White, Red, Blue, Green]).freeze
17
+ end
18
+
19
+ class US < ::Sparsam::Struct
20
+ FIELDS = {
21
+ 1 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true},
22
+ 2 => {:type => ::Sparsam::Types::STRING, :name => 'id_s', :default => %q"id_s default", :binary => true, :optional => true},
23
+ 3 => {:type => ::Sparsam::Types::SET, :name => 'string_set', :element => {:type => ::Sparsam::Types::STRING}, :optional => true},
24
+ 4 => {:type => ::Sparsam::Types::SET, :name => 'int_set', :element => {:type => ::Sparsam::Types::I32}, :optional => true}
25
+ }
26
+
27
+ init_thrift_struct(self)
28
+ end
29
+
30
+ class UN < ::Sparsam::Union
31
+ FIELDS = {
32
+ 1 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true},
33
+ 2 => {:type => ::Sparsam::Types::STRING, :name => 'id_s', :optional => true}
34
+ }
35
+
36
+ init_thrift_struct(self)
37
+ end
38
+
39
+ class SS < ::Sparsam::Struct
40
+ FIELDS = {
41
+ 1 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true},
42
+ 2 => {:type => ::Sparsam::Types::STRING, :name => 'id_s', :optional => true},
43
+ 3 => {:type => ::Sparsam::Types::STRUCT, :name => 'us_i', :class => ::US, :optional => true},
44
+ 4 => {:type => ::Sparsam::Types::SET, :name => 'us_s', :element => {:type => ::Sparsam::Types::STRUCT, :class => ::US}, :optional => true},
45
+ 5 => {:type => ::Sparsam::Types::LIST, :name => 's_l', :element => {:type => ::Sparsam::Types::STRING}, :optional => true},
46
+ 6 => {:type => ::Sparsam::Types::MAP, :name => 'mappy', :key => {:type => ::Sparsam::Types::I32}, :value => {:type => ::Sparsam::Types::STRING}, :optional => true},
47
+ 7 => {:type => ::Sparsam::Types::BYTE, :name => 'byte_field', :optional => true},
48
+ 8 => {:type => ::Sparsam::Types::STRUCT, :name => 'un_field', :class => ::UN, :optional => true},
49
+ 9 => {:type => ::Sparsam::Types::I32, :name => 'magic_field', :optional => true, :enum_class => ::Magic},
50
+ 10 => {:type => ::Sparsam::Types::MAP, :name => 'troll', :key => {:type => ::Sparsam::Types::I32}, :value => {:type => ::Sparsam::Types::MAP, :key => {:type => ::Sparsam::Types::I32}, :value => {:type => ::Sparsam::Types::I32}}, :optional => true}
51
+ }
52
+
53
+ init_thrift_struct(self)
54
+ end
55
+
56
+ class MiniRequired < ::Sparsam::Struct
57
+ FIELDS = {
58
+ 1 => {:type => ::Sparsam::Types::I32, :name => 'id_i32'}
59
+ }
60
+
61
+ init_thrift_struct(self)
62
+ end
63
+
64
+ class EasilyInvalid < ::Sparsam::Struct
65
+ FIELDS = {
66
+ 1 => {:type => ::Sparsam::Types::STRUCT, :name => 'tail', :class => ::EasilyInvalid, :optional => true},
67
+ 2 => {:type => ::Sparsam::Types::SET, :name => 's_self', :element => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :optional => true},
68
+ 3 => {:type => ::Sparsam::Types::LIST, :name => 'l_self', :element => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :optional => true},
69
+ 4 => {:type => ::Sparsam::Types::MAP, :name => 'mappy1', :key => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :value => {:type => ::Sparsam::Types::I32}, :optional => true},
70
+ 5 => {:type => ::Sparsam::Types::MAP, :name => 'mappy2', :key => {:type => ::Sparsam::Types::I32}, :value => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :optional => true},
71
+ 6 => {:type => ::Sparsam::Types::MAP, :name => 'mappy3', :key => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :value => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :optional => true},
72
+ 7 => {:type => ::Sparsam::Types::LIST, :name => 'sure', :element => {:type => ::Sparsam::Types::MAP, :key => {:type => ::Sparsam::Types::SET, :element => {:type => ::Sparsam::Types::I32}}, :value => {:type => ::Sparsam::Types::MAP, :key => {:type => ::Sparsam::Types::I32}, :value => {:type => ::Sparsam::Types::SET, :element => {:type => ::Sparsam::Types::LIST, :element => {:type => ::Sparsam::Types::MAP, :key => {:type => ::Sparsam::Types::STRUCT, :class => ::EasilyInvalid}, :value => {:type => ::Sparsam::Types::STRING}}}}}}, :optional => true},
73
+ 8 => {:type => ::Sparsam::Types::STRUCT, :name => 'required_stuff', :class => ::MiniRequired, :optional => true},
74
+ 9 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true}
75
+ }
76
+
77
+ init_thrift_struct(self)
78
+ end
79
+
80
+ class NotSS < ::Sparsam::Struct
81
+ FIELDS = {
82
+ 1 => {:type => ::Sparsam::Types::STRING, :name => 'id_s', :optional => true},
83
+ 3 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true}
84
+ }
85
+
86
+ init_thrift_struct(self)
87
+ end
88
+
89
+ class NotSS_plus < ::Sparsam::Struct
90
+ FIELDS = {
91
+ 1 => {:type => ::Sparsam::Types::STRING, :name => 'id_s', :optional => true},
92
+ 2 => {:type => ::Sparsam::Types::STRING, :name => 'id_s2', :optional => true},
93
+ 3 => {:type => ::Sparsam::Types::I32, :name => 'id_i32', :optional => true}
94
+ }
95
+
96
+ init_thrift_struct(self)
97
+ end
98
+
99
+ class Nothing < ::Sparsam::Struct
100
+ FIELDS = {
101
+
102
+ }
103
+
104
+ init_thrift_struct(self)
105
+ end
106
+