steamd 0.1.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +4 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +6 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +21 -0
  9. data/README.md +51 -0
  10. data/Rakefile +22 -0
  11. data/bin/console +6 -0
  12. data/bin/setup +6 -0
  13. data/bin/steamd +6 -0
  14. data/grammar/class.treetop +63 -0
  15. data/grammar/enums.treetop +44 -0
  16. data/grammar/import.treetop +11 -0
  17. data/grammar/shared.treetop +62 -0
  18. data/grammar/steamd.treetop +15 -0
  19. data/language/emsg.steamd +1802 -0
  20. data/language/enums.steamd +989 -0
  21. data/language/eresult.steamd +119 -0
  22. data/language/gamecoordinator.steamd +17 -0
  23. data/language/header.steamd +37 -0
  24. data/language/netheader.steamd +62 -0
  25. data/language/steammsg.steamd +357 -0
  26. data/lib/ext/string.rb +33 -0
  27. data/lib/steamd.rb +40 -0
  28. data/lib/steamd/cli.rb +24 -0
  29. data/lib/steamd/cli_options.rb +58 -0
  30. data/lib/steamd/code_generator.rb +41 -0
  31. data/lib/steamd/generated/emsg.rb +3464 -0
  32. data/lib/steamd/generated/enums.rb +1750 -0
  33. data/lib/steamd/generated/eresult.rb +236 -0
  34. data/lib/steamd/generated/gamecoordinator.rb +119 -0
  35. data/lib/steamd/generated/header.rb +261 -0
  36. data/lib/steamd/generated/netheader.rb +315 -0
  37. data/lib/steamd/generated/steammsg.rb +2527 -0
  38. data/lib/steamd/generator.rb +6 -0
  39. data/lib/steamd/generator/generated_class.rb +128 -0
  40. data/lib/steamd/generator/generated_enum.rb +60 -0
  41. data/lib/steamd/generator/generated_import.rb +21 -0
  42. data/lib/steamd/generator/implementation.rb +83 -0
  43. data/lib/steamd/generator/ruby/class.erb +39 -0
  44. data/lib/steamd/generator/ruby/enum.erb +14 -0
  45. data/lib/steamd/generator/ruby/import.erb +1 -0
  46. data/lib/steamd/generator/ruby/ruby.rb +54 -0
  47. data/lib/steamd/generator/ruby/serializable_constant.rb +20 -0
  48. data/lib/steamd/generator/ruby/serializable_type.rb +93 -0
  49. data/lib/steamd/generator/ruby/serializable_variable.rb +85 -0
  50. data/lib/steamd/generator/ruby/steam_serializable.rb +89 -0
  51. data/lib/steamd/nodes/block_node.rb +14 -0
  52. data/lib/steamd/nodes/class_statement_node.rb +46 -0
  53. data/lib/steamd/nodes/class_type_node.rb +12 -0
  54. data/lib/steamd/nodes/enum_statement_node.rb +50 -0
  55. data/lib/steamd/nodes/enum_variable_node.rb +24 -0
  56. data/lib/steamd/nodes/import_statement_node.rb +26 -0
  57. data/lib/steamd/nodes/node.rb +3 -0
  58. data/lib/steamd/nodes/nodes.rb +10 -0
  59. data/lib/steamd/nodes/variable_node.rb +106 -0
  60. data/lib/steamd/parser.rb +157 -0
  61. data/lib/steamd/version.rb +14 -0
  62. data/steamd.gemspec +38 -0
  63. data/tasks/language.rake +11 -0
  64. metadata +220 -0
@@ -0,0 +1,85 @@
1
+
2
+ # frozen_string_literal: true
3
+ # Represents a Serialized var
4
+ class SerizableVariable
5
+ attr_reader :name, :type, :size, :modifier, :modifier_size, :value
6
+ attr_accessor :flag
7
+
8
+ # Initialize a SteamSerializable from a hash
9
+ def initialize(var)
10
+ @name = var[:name]
11
+ @value = var[:value]
12
+ @modifier = var[:modifier]
13
+ @modifier_size = var[:modifier_size]
14
+ @type = Type.new(var[:type])
15
+ end
16
+
17
+ # Serialize the object
18
+ def serialize
19
+ if type.primitive?
20
+ serialize_primitive
21
+ elsif type.encodable?
22
+ serialize_encodable
23
+ else
24
+ serialize_object
25
+ end
26
+ end
27
+
28
+ # Serialize the object
29
+ #
30
+ # @param io [:read]
31
+ def deserialize(io)
32
+ @value = if type.primitive?
33
+ deserialize_primitive(io)
34
+ elsif type.encodable?
35
+ deserialize_encodable(io)
36
+ else
37
+ deserialize_object(io)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # @api private
44
+ def deserialize_object(io)
45
+ type = Type.new(self.type.klass::DATA_TYPE)
46
+ io.read(type.bytesize).unpack(type.bytedirective).first
47
+ end
48
+
49
+ # @api private
50
+ def deserialize_encodable(io)
51
+ raise NotImplementedError if flag.nil? || modifier_size.nil?
52
+ type.klass.decode(io.read(flag.value))
53
+ end
54
+
55
+ # @api private
56
+ def deserialize_primitive(io)
57
+ io.read(type.bytesize).unpack(type.bytedirective).first
58
+ end
59
+
60
+ # @api private
61
+ def serialize_object
62
+ type = Type.new(self.type.klass::DATA_TYPE)
63
+ [value].pack(type.bytedirective)
64
+ end
65
+
66
+ # @api private
67
+ def serialize_encodable
68
+ raise NotImplementedError unless value.respond_to?(:encode)
69
+ value.encode
70
+ end
71
+
72
+ # @api private
73
+ def serialize_primitive
74
+ if flag
75
+ [flag.value.encode.length].pack('<l')
76
+ else
77
+ [value].pack(type.bytedirective)
78
+ end
79
+ end
80
+
81
+ # @api private
82
+ def validate
83
+ raise NotImplementedError unless @var[:size].nil?
84
+ end
85
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+ require 'steamd/generator/ruby/serializable_type'
3
+ require 'steamd/generator/ruby/serializable_variable'
4
+ require 'steamd/generator/ruby/serializable_constant'
5
+
6
+ # Included in each Generated Ruby class. Provides access to methods on the class
7
+ # as well as serialization options.
8
+ module SteamSerializable
9
+ # Variables in this class
10
+ attr_reader :variables
11
+
12
+ # Variables in this class
13
+ attr_reader :constants
14
+
15
+ # Sets the variables and constants of this Steam object
16
+ def initialize(vars, consts = [])
17
+ @variables = vars.each_with_object({}) { |v, m| m[v[:name]] = v }
18
+ @constants = consts.each_with_object({}) { |v, m| m[v[:name]] = v }
19
+ end
20
+
21
+ # Encode to a given IO stream
22
+ #
23
+ # @param io [:read]
24
+ def encode_to(io)
25
+ io.write(serialize)
26
+ end
27
+
28
+ # Serialize the constants and variables into a stream
29
+ #
30
+ # @return [String] the byte representation
31
+ def serialize
32
+ stream = StringIO.new
33
+ stream.set_encoding('BINARY')
34
+ stream.write((consts + vars).map(&:serialize).join)
35
+ stream.string
36
+ end
37
+ alias encode serialize
38
+
39
+ # Deserialize the object using an IO stream
40
+ #
41
+ # @param io [:read] The io stream to deserialize
42
+ def deserialize(io)
43
+ (consts + vars).each { |v| send("#{v.name}=", v.deserialize(io)) }
44
+ self
45
+ end
46
+ alias decode deserialize
47
+ alias decode_from deserialize
48
+
49
+ # Returns a list of SerizableConstant objects. Allowing you to
50
+ # serialize each constant
51
+ #
52
+ # @return [Array<SerizableConstant>] the constants
53
+ def consts
54
+ constants.values.map { |const| SerizableConstant.new(const) }
55
+ end
56
+
57
+ # Returns a list of SerializedVariable objects. Allowing you to
58
+ # serialize each constant
59
+ #
60
+ # @return [Array<SerializedVariable>] the constants
61
+ def vars
62
+ vars = variables.values.map do |v|
63
+ SerizableVariable.new(v)
64
+ end
65
+
66
+ vars.map do |var|
67
+ var.flag = flag(vars, var)
68
+ var
69
+ end
70
+ end
71
+
72
+ # Looks up the variable flag. This is used for when variables
73
+ # are of a defined length
74
+ #
75
+ # ie:
76
+ # int header_len;
77
+ # proto<header_len> ProtoBuf name;
78
+ #
79
+ # The flag in the case of serialization would be the "name" variable as it
80
+ # would need to write that before it can write header len.
81
+ #
82
+ # The flag in the case of deserialization would be the "header_len" variable
83
+ # because it defines how many bytes to read so we can read the "name"
84
+ # variable
85
+ def flag(vars, var)
86
+ (vars.select { |v| v.modifier_size == var.name } +
87
+ vars.select { |v| v.name == var.modifier_size }).first
88
+ end
89
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ # The root of the parsed tree
3
+ class Block < Node
4
+ # Gets the statements in a Steam Language block
5
+ #
6
+ # @see ClassStatement
7
+ # @see ImportStatement
8
+ # @see EnumStatement
9
+ #
10
+ # @return Array
11
+ def statements
12
+ elements.map(&:statement)
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ # A parsed class statement
3
+ #
4
+ # @example A class
5
+ # class Test { }
6
+ #
7
+ # Contains the variables, class name, type
8
+ class ClassStatement < Node
9
+ # Returns the class object as a hash
10
+ #
11
+ # @return [Hash] hash representation of the class
12
+ def to_hash
13
+ {
14
+ name: name,
15
+ type: type,
16
+ variables: variables
17
+ }
18
+ end
19
+
20
+ # The name of the class
21
+ def name
22
+ class_name.text_value
23
+ end
24
+
25
+ # The class type
26
+ #
27
+ # ie class Test<EMsg::Blah> {}
28
+ def type
29
+ types = elements.select { |el| el.is_a?(ClassType) }
30
+ type = types.first
31
+ type&.value
32
+ end
33
+
34
+ # Returns a list of variables
35
+ #
36
+ # @return [Array] variables
37
+ def variables
38
+ declerations = [first_var] + other.elements.map(&:decleration)
39
+
40
+ variables = declerations.select do |node|
41
+ node.is_a?(Variable)
42
+ end
43
+
44
+ variables.map!(&:to_hash)
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # Holds a class type, if it exists
3
+ # This node may not always be in the tree
4
+ class ClassType < Node
5
+ # The type of the class
6
+ #
7
+ # @return [String]
8
+ def value
9
+ type = text_value.strip
10
+ type.empty? ? nil : type
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ # Represents an Enum statement
3
+ #
4
+ # @example Enum Statement
5
+ # enum Test { Invalid = 1; }
6
+ class EnumStatement < Node
7
+ # The name of the enum
8
+ #
9
+ # @return [String]
10
+ def name
11
+ enum_name.text_value
12
+ end
13
+
14
+ # The type of the enum
15
+ #
16
+ # @return [String]
17
+ def type
18
+ enum_type.type.text_value if enum_type.respond_to?(:type)
19
+ end
20
+
21
+ # Returns true if this enum uses bitmask flags
22
+ #
23
+ # @return [Bool]
24
+ def flags?
25
+ type == 'flags'
26
+ end
27
+
28
+ # Returns a list of EnumVariable objects
29
+ #
30
+ # @return Array
31
+ def variables
32
+ declerations = [first_var] + other.elements.map(&:enum_decleration)
33
+
34
+ variables = declerations.select do |node|
35
+ node.is_a?(EnumVariable)
36
+ end
37
+
38
+ variables.map!(&:to_hash)
39
+ end
40
+
41
+ # Hash representation of this Enum
42
+ def to_hash
43
+ {
44
+ name: name,
45
+ type: type,
46
+ flags: flags?,
47
+ variables: variables
48
+ }
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ # Represents a variable declared in an Enum
3
+ #
4
+ # @example
5
+ # Invalid = 0
6
+ class EnumVariable < Node
7
+ # The name of the EnumVariable
8
+ def name
9
+ enum_variable_name.text_value
10
+ end
11
+
12
+ # The value of the EnumVariable
13
+ def value
14
+ enum_variable_value.value
15
+ end
16
+
17
+ # Hash representation of the EnumVariable
18
+ def to_hash
19
+ {
20
+ name: name,
21
+ value: value
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # Represents an import statement
3
+ #
4
+ # ie: #import "test.steamd"
5
+ class ImportStatement < Node
6
+ # The full name including the extension of the import file
7
+ #
8
+ # @return [String]
9
+ def name
10
+ filename.text_value
11
+ end
12
+
13
+ # The name not including the extension of the import file
14
+ #
15
+ # @return [String]
16
+ def filename_no_ext
17
+ File.basename(name, '.*')
18
+ end
19
+
20
+ # The hash representation
21
+ #
22
+ # @return [Hash]
23
+ def to_hash
24
+ { filename: filename_no_ext }
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ # Wrapper around a treetop node
3
+ Node = Class.new(Treetop::Runtime::SyntaxNode)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'steamd/nodes/node'
4
+ require 'steamd/nodes/block_node'
5
+ require 'steamd/nodes/class_type_node'
6
+ require 'steamd/nodes/class_statement_node'
7
+ require 'steamd/nodes/variable_node'
8
+ require 'steamd/nodes/enum_variable_node'
9
+ require 'steamd/nodes/enum_statement_node'
10
+ require 'steamd/nodes/import_statement_node'
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+ # Base variable, each variable has a type and a name at the very least.
3
+ class Variable < Node
4
+ # Returns the name of the variable
5
+ #
6
+ # @return [String] the variable name
7
+ def name
8
+ variable_name.text_value
9
+ end
10
+
11
+ # Returns the type of the variable
12
+ #
13
+ # @return [String] the variable type
14
+ def type
15
+ var_type.type.text_value
16
+ end
17
+
18
+ # Returns the size, if any of the variable. ie byte<6> y;
19
+ #
20
+ # @return [String/Integer/nil] the variable size
21
+ def size
22
+ return nil unless var_type && var_type.respond_to?(:size)
23
+
24
+ if var_type.size.text_value.empty?
25
+ nil
26
+ else
27
+ var_type.size.var_value.value
28
+ end
29
+ end
30
+
31
+ # Hash representation of this Variable Node
32
+ #
33
+ # @return [Hash]
34
+ def to_hash
35
+ {
36
+ name: name,
37
+ type: type,
38
+ modifier: nil,
39
+ value: nil,
40
+ size: size,
41
+ modifier_size: nil
42
+ }
43
+ end
44
+ end
45
+
46
+ # Variable with a modifier.
47
+ #
48
+ # ie: proto int x;
49
+ class VariableWithModifier < Variable
50
+ # Determins if the modifier of this variable is sized.
51
+ #
52
+ # ie: proto<len> CMsgHeaderProtobuf x;
53
+ def sized?
54
+ var_modifier.respond_to?(:size) &&
55
+ !var_modifier.size.text_value.empty?
56
+ end
57
+
58
+ # The size of the variable modifier
59
+ def modifier_size
60
+ return nil if var_type.nil?
61
+
62
+ var_modifier.size.value if sized?
63
+ end
64
+ end
65
+
66
+ # A variable with a modifier but no value
67
+ # ie: proto header hi;
68
+ class VariableWithModifierNoValue < VariableWithModifier
69
+ # Hash representation of the VariableWithModifierNoValue
70
+ #
71
+ # @return [Hash]
72
+ def to_hash
73
+ hsh = super
74
+
75
+ hsh.merge!(
76
+ modifier: var_modifier.word.text_value,
77
+ modifier_size: modifier_size
78
+ )
79
+ end
80
+ end
81
+
82
+ # A variable with a modifier and a default value
83
+ class VariableWithModifierWithValue < VariableWithModifierNoValue
84
+ # Hash representation of the VariableWithModifierWithValue
85
+ #
86
+ # @return [Hash]
87
+ def to_hash
88
+ hsh = super
89
+
90
+ hsh.merge!(
91
+ value: var_value.value
92
+ )
93
+ end
94
+ end
95
+
96
+ # Variable, no modifier with a value
97
+ # ie: int x = 1;
98
+ class VariableWithValue < Variable
99
+ # Hash representation of the VariableWithValue
100
+ #
101
+ # @return [Hash]
102
+ def to_hash
103
+ hsh = super
104
+ hsh.merge!(value: var_value.value)
105
+ end
106
+ end