steamd 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +51 -0
- data/Rakefile +22 -0
- data/bin/console +6 -0
- data/bin/setup +6 -0
- data/bin/steamd +6 -0
- data/grammar/class.treetop +63 -0
- data/grammar/enums.treetop +44 -0
- data/grammar/import.treetop +11 -0
- data/grammar/shared.treetop +62 -0
- data/grammar/steamd.treetop +15 -0
- data/language/emsg.steamd +1802 -0
- data/language/enums.steamd +989 -0
- data/language/eresult.steamd +119 -0
- data/language/gamecoordinator.steamd +17 -0
- data/language/header.steamd +37 -0
- data/language/netheader.steamd +62 -0
- data/language/steammsg.steamd +357 -0
- data/lib/ext/string.rb +33 -0
- data/lib/steamd.rb +40 -0
- data/lib/steamd/cli.rb +24 -0
- data/lib/steamd/cli_options.rb +58 -0
- data/lib/steamd/code_generator.rb +41 -0
- data/lib/steamd/generated/emsg.rb +3464 -0
- data/lib/steamd/generated/enums.rb +1750 -0
- data/lib/steamd/generated/eresult.rb +236 -0
- data/lib/steamd/generated/gamecoordinator.rb +119 -0
- data/lib/steamd/generated/header.rb +261 -0
- data/lib/steamd/generated/netheader.rb +315 -0
- data/lib/steamd/generated/steammsg.rb +2527 -0
- data/lib/steamd/generator.rb +6 -0
- data/lib/steamd/generator/generated_class.rb +128 -0
- data/lib/steamd/generator/generated_enum.rb +60 -0
- data/lib/steamd/generator/generated_import.rb +21 -0
- data/lib/steamd/generator/implementation.rb +83 -0
- data/lib/steamd/generator/ruby/class.erb +39 -0
- data/lib/steamd/generator/ruby/enum.erb +14 -0
- data/lib/steamd/generator/ruby/import.erb +1 -0
- data/lib/steamd/generator/ruby/ruby.rb +54 -0
- data/lib/steamd/generator/ruby/serializable_constant.rb +20 -0
- data/lib/steamd/generator/ruby/serializable_type.rb +93 -0
- data/lib/steamd/generator/ruby/serializable_variable.rb +85 -0
- data/lib/steamd/generator/ruby/steam_serializable.rb +89 -0
- data/lib/steamd/nodes/block_node.rb +14 -0
- data/lib/steamd/nodes/class_statement_node.rb +46 -0
- data/lib/steamd/nodes/class_type_node.rb +12 -0
- data/lib/steamd/nodes/enum_statement_node.rb +50 -0
- data/lib/steamd/nodes/enum_variable_node.rb +24 -0
- data/lib/steamd/nodes/import_statement_node.rb +26 -0
- data/lib/steamd/nodes/node.rb +3 -0
- data/lib/steamd/nodes/nodes.rb +10 -0
- data/lib/steamd/nodes/variable_node.rb +106 -0
- data/lib/steamd/parser.rb +157 -0
- data/lib/steamd/version.rb +14 -0
- data/steamd.gemspec +38 -0
- data/tasks/language.rake +11 -0
- metadata +220 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'ostruct'
|
3
|
+
module Steamd
|
4
|
+
module Generator
|
5
|
+
# Represents an class variable from the Generator
|
6
|
+
class Variable
|
7
|
+
# The name of the Variable
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# The variable Type
|
11
|
+
attr_reader :type
|
12
|
+
|
13
|
+
# The variable size
|
14
|
+
attr_reader :size
|
15
|
+
|
16
|
+
# The variable modifier
|
17
|
+
attr_reader :modifier
|
18
|
+
|
19
|
+
# The variable modifier size
|
20
|
+
attr_reader :modifier_size
|
21
|
+
|
22
|
+
# The variable value
|
23
|
+
attr_reader :value
|
24
|
+
|
25
|
+
# Create a new GeneratedClass
|
26
|
+
def initialize(opts)
|
27
|
+
@name = opts[:name]
|
28
|
+
@value = opts[:value]
|
29
|
+
@type = opts[:type]
|
30
|
+
@modifier = opts[:modifier]
|
31
|
+
@modifier_size = opts[:modifier_size]
|
32
|
+
end
|
33
|
+
|
34
|
+
# The name of the Variable
|
35
|
+
#
|
36
|
+
# @return [String] variable name, underscored
|
37
|
+
def name
|
38
|
+
@name.underscore
|
39
|
+
end
|
40
|
+
|
41
|
+
# The size of the variable modifier
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
def modifier_size
|
45
|
+
if @modifier_size.is_a?(String)
|
46
|
+
@modifier_size.underscore
|
47
|
+
else
|
48
|
+
@modifier_size
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# The type of the variable
|
53
|
+
def type
|
54
|
+
case @type
|
55
|
+
when 'SteamKit2.Internal.CMsgProtoBufHeader'
|
56
|
+
'Steamclient::CMsgProtoBufHeader'
|
57
|
+
when 'SteamKit2.GC.Internal.CMsgProtoBufHeader'
|
58
|
+
'Gc::CMsgProtoBufHeader'
|
59
|
+
else
|
60
|
+
@type
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def value
|
65
|
+
if @value.is_a?(String)
|
66
|
+
parts = @value.split('::')
|
67
|
+
name = parts.last.underscore.upcase
|
68
|
+
[parts.first, name].join('::')
|
69
|
+
else
|
70
|
+
@value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return the variable as a hash
|
75
|
+
def to_hash
|
76
|
+
{
|
77
|
+
name: name,
|
78
|
+
type: type,
|
79
|
+
modifier: modifier,
|
80
|
+
value: value,
|
81
|
+
size: size,
|
82
|
+
modifier_size: modifier_size
|
83
|
+
}
|
84
|
+
end
|
85
|
+
alias to_h to_hash
|
86
|
+
end
|
87
|
+
|
88
|
+
# Class constant
|
89
|
+
class Constant < Variable
|
90
|
+
attr_reader :name, :value
|
91
|
+
def name
|
92
|
+
@name.underscore.upcase
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Represents an Class from the Generator
|
97
|
+
class GeneratedClass
|
98
|
+
# Create a Generated Class
|
99
|
+
def initialize(klass)
|
100
|
+
@klass = klass
|
101
|
+
end
|
102
|
+
|
103
|
+
# List of variables to be used in the class
|
104
|
+
def variables
|
105
|
+
@klass[:variables].select { |v| v[:modifier] != 'const' }.map do |var|
|
106
|
+
Variable.new(var)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# List of constants to be used in the class
|
111
|
+
def constants
|
112
|
+
@klass[:variables].select { |v| v[:modifier] == 'const' }.map do |const|
|
113
|
+
Constant.new(const)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# The class name
|
118
|
+
def name
|
119
|
+
@klass[:name]
|
120
|
+
end
|
121
|
+
|
122
|
+
# Binding for ERB
|
123
|
+
def erb_binding
|
124
|
+
binding
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Steamd
|
3
|
+
module Generator
|
4
|
+
# Enum variable
|
5
|
+
class EnumVariable
|
6
|
+
attr_reader :name, :value, :flags
|
7
|
+
def initialize(name, value, flags)
|
8
|
+
@name = name
|
9
|
+
@value = value
|
10
|
+
@flags = flags
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
@name.underscore.upcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
if flags && @value.is_a?(String)
|
19
|
+
@value
|
20
|
+
.split('|')
|
21
|
+
.map(&:strip)
|
22
|
+
.map(&:underscore)
|
23
|
+
.map(&:upcase)
|
24
|
+
.join(' | ')
|
25
|
+
else
|
26
|
+
@value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Represents an Enum from the Generator
|
32
|
+
class GeneratedEnum
|
33
|
+
def initialize(enum)
|
34
|
+
@enum = enum
|
35
|
+
end
|
36
|
+
|
37
|
+
# Type of Enum
|
38
|
+
def type
|
39
|
+
@enum[:type]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Entries of enum
|
43
|
+
def variables
|
44
|
+
@enum[:variables].map do |v|
|
45
|
+
EnumVariable.new(v[:name], v[:value], @enum[:flags])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Name of enum
|
50
|
+
def name
|
51
|
+
@enum[:name]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Binding for ERB
|
55
|
+
def erb_binding
|
56
|
+
binding
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Steamd
|
3
|
+
module Generator
|
4
|
+
# Represents an import from the Generator
|
5
|
+
class GeneratedImport
|
6
|
+
def initialize(import)
|
7
|
+
@import = import
|
8
|
+
end
|
9
|
+
|
10
|
+
# Import filename
|
11
|
+
def filename
|
12
|
+
@import[:filename]
|
13
|
+
end
|
14
|
+
|
15
|
+
# ERB Binding
|
16
|
+
def erb_binding
|
17
|
+
binding
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'erb'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
require 'steamd/generator/generated_class'
|
6
|
+
require 'steamd/generator/generated_enum'
|
7
|
+
require 'steamd/generator/generated_import'
|
8
|
+
|
9
|
+
module Steamd
|
10
|
+
module Generator
|
11
|
+
# The underlying Implementation of a generator.
|
12
|
+
#
|
13
|
+
# @example Making a generate
|
14
|
+
# class MyGenerator
|
15
|
+
# include Generator::Implementation
|
16
|
+
#
|
17
|
+
# def generate
|
18
|
+
# classes.each { |c| puts c.name }
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
module Implementation
|
22
|
+
# Instantiate the object with a given IO stream.
|
23
|
+
#
|
24
|
+
# @param io The IO object
|
25
|
+
def initialize(io)
|
26
|
+
@parser = Steamd::Parser.new
|
27
|
+
@buffer = ''
|
28
|
+
@io = io
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
# Run the generator. Load the parser, and parse the IO object.
|
33
|
+
#
|
34
|
+
# @return The parsed code
|
35
|
+
def run
|
36
|
+
@parser.load!
|
37
|
+
@parser.parse(@io)
|
38
|
+
generate
|
39
|
+
@buffer
|
40
|
+
end
|
41
|
+
|
42
|
+
# The classes parsed from the lanaguage
|
43
|
+
def classes
|
44
|
+
@parser.classes.map do |klass|
|
45
|
+
GeneratedClass.new(klass)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# The imports parsed from the language
|
50
|
+
def imports
|
51
|
+
@parser.imports.map do |import|
|
52
|
+
GeneratedImport.new(import)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# The enums parsed from the language
|
57
|
+
def enums
|
58
|
+
@parser.enums.map do |enum|
|
59
|
+
GeneratedEnum.new(enum)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Generates the code
|
66
|
+
def generate(_io)
|
67
|
+
raise NotImplementedError
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
def erb(template, vars)
|
72
|
+
ERB.new(template, nil, '-').result(vars.erb_binding)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Append a string to the internal buffer
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
def append(str)
|
79
|
+
@buffer += str
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Class for the <%= name %> in the Steam Language.
|
2
|
+
class <%= name %>
|
3
|
+
# Allows serialization and deserialization of the class
|
4
|
+
include SteamSerializable
|
5
|
+
|
6
|
+
<% constants.each do |const| -%>
|
7
|
+
# <%= const.name -%> constant
|
8
|
+
<%= const.name -%> = <%= const.value %>
|
9
|
+
<% end -%>
|
10
|
+
# Instantiate a <%= name -%> object
|
11
|
+
def initialize
|
12
|
+
super(<%= variables.map(&:to_h) -%>, <%= constants.map(&:to_h) -%>)
|
13
|
+
<% variables.each do |var| -%>
|
14
|
+
<% if var.value != nil -%>
|
15
|
+
self.<%= var.name -%> = <%= var.value %>
|
16
|
+
<% end -%>
|
17
|
+
<% if var.type.include?('CMsg') -%>
|
18
|
+
self.<%= var.name -%> = <%= var.type %>.new
|
19
|
+
<% end -%>
|
20
|
+
<% end -%>
|
21
|
+
end
|
22
|
+
<% variables.each do |var| %>
|
23
|
+
# Gets the <%= var.name -%> variable.
|
24
|
+
#
|
25
|
+
# @note defaults to <%= var.value %>
|
26
|
+
# @return [<%= var.type -%>] the value of <%= var.name %>
|
27
|
+
def <%= var.name %>
|
28
|
+
@variables['<%= var.name -%>'][:value]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets the <%= var.name -%> variable.
|
32
|
+
#
|
33
|
+
# @param value [<%= var.type -%>] the new value
|
34
|
+
def <%= var.name -%>=(value)
|
35
|
+
@variables['<%= var.name -%>'][:value] = value
|
36
|
+
end
|
37
|
+
<% end %>
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Represents the <%= name -%> enum
|
2
|
+
class <%= name %>
|
3
|
+
# Data type of <%= name %>
|
4
|
+
<% if type -%>
|
5
|
+
DATA_TYPE = '<%= type %>'
|
6
|
+
<% else -%>
|
7
|
+
DATA_TYPE = 'int'
|
8
|
+
<% end -%>
|
9
|
+
<% variables.each do |var| -%>
|
10
|
+
# Constant <%= var.name -%> for <%= name %>
|
11
|
+
<%= var.name %> = <%= var.value %>
|
12
|
+
<% end -%>
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative '<%= filename %>'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'steamd/generator/implementation'
|
3
|
+
|
4
|
+
# frozen_string_literal: true
|
5
|
+
module Steamd
|
6
|
+
module Generator
|
7
|
+
# Generates Ruby code
|
8
|
+
class Ruby
|
9
|
+
include Implementation
|
10
|
+
|
11
|
+
# Generate Ruby code for the Steam Language
|
12
|
+
def generate
|
13
|
+
classes.each do |klass|
|
14
|
+
append(erb(klass_template, klass))
|
15
|
+
end
|
16
|
+
|
17
|
+
imports.each do |import|
|
18
|
+
append(erb(import_template, import))
|
19
|
+
end
|
20
|
+
|
21
|
+
enums.each do |enum|
|
22
|
+
append(erb(enum_template, enum))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def import_template
|
30
|
+
erb_file('import.erb').read
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
def enum_template
|
35
|
+
erb_file('enum.erb').read
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
def klass_template
|
40
|
+
erb_file('class.erb').read
|
41
|
+
end
|
42
|
+
|
43
|
+
# @api private
|
44
|
+
def erb_file(file)
|
45
|
+
File.open(File.expand_path("#{erb_template_root}/#{file}"))
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
def erb_template_root
|
50
|
+
File.dirname(__FILE__)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Serializable const
|
3
|
+
class SerizableConstant < SerizableVariable
|
4
|
+
# Override the type for constants, always integer
|
5
|
+
#
|
6
|
+
# @return [Type]
|
7
|
+
def type
|
8
|
+
Type.new('int')
|
9
|
+
end
|
10
|
+
|
11
|
+
# Serialize the constant
|
12
|
+
def serialize
|
13
|
+
serialize_primitive
|
14
|
+
end
|
15
|
+
|
16
|
+
# Deserialize the constant
|
17
|
+
def deserialize
|
18
|
+
@value = deserialize_primitive
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Serializable type
|
3
|
+
class Type
|
4
|
+
attr_reader :type
|
5
|
+
|
6
|
+
# Instantiate a Type
|
7
|
+
#
|
8
|
+
# @example Instantiate a Type
|
9
|
+
# type = Type.new('int')
|
10
|
+
def initialize(type)
|
11
|
+
@type = type
|
12
|
+
end
|
13
|
+
|
14
|
+
# The String representation of the Type. If it is a SteamKit Internal type,
|
15
|
+
# the type is transformed into namespaces from the `steam-proto` repo.
|
16
|
+
#
|
17
|
+
# @return [String] the type
|
18
|
+
def type
|
19
|
+
case @type
|
20
|
+
when 'SteamKit2.Internal.CMsgProtoBufHeader'
|
21
|
+
'Steamclient::CMsgProtoBufHeader'
|
22
|
+
when 'SteamKit2.GC.Internal.CMsgProtoBufHeader'
|
23
|
+
'Gc::CMsgProtoBufHeader'
|
24
|
+
when *primitives
|
25
|
+
@type
|
26
|
+
else
|
27
|
+
Object.const_get(@type.to_s).to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Is this type an encodable type?
|
32
|
+
#
|
33
|
+
# @return [Bool]
|
34
|
+
def encodable?
|
35
|
+
encodables.include?(type)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Is this type an primitive type?
|
39
|
+
#
|
40
|
+
# @return [Bool]
|
41
|
+
def primitive?
|
42
|
+
primitives.include?(type)
|
43
|
+
end
|
44
|
+
|
45
|
+
# The byte directive for this type
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
def bytedirective
|
49
|
+
{
|
50
|
+
'int' => 'l<',
|
51
|
+
'ushort' => 'S<',
|
52
|
+
'short' => 's<',
|
53
|
+
'byte' => 'c',
|
54
|
+
'uint' => 'L<',
|
55
|
+
'ulong' => 'Q<'
|
56
|
+
}[type]
|
57
|
+
end
|
58
|
+
|
59
|
+
# The size in bytes of this type
|
60
|
+
#
|
61
|
+
# @return [Integer]
|
62
|
+
def bytesize
|
63
|
+
case type
|
64
|
+
when 'uint', 'int'
|
65
|
+
4
|
66
|
+
when 'ushort', 'short'
|
67
|
+
2
|
68
|
+
when 'ulong', 'long'
|
69
|
+
8
|
70
|
+
when 'byte'
|
71
|
+
1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# The Class represented by this Type
|
76
|
+
#
|
77
|
+
# @return [Object]
|
78
|
+
def klass
|
79
|
+
type.constantize
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
def primitives
|
86
|
+
%w(int short uint long ulong byte ushort)
|
87
|
+
end
|
88
|
+
|
89
|
+
# @api private
|
90
|
+
def encodables
|
91
|
+
['Steamclient::CMsgProtoBufHeader', 'Gc::CMsgProtoBufHeader']
|
92
|
+
end
|
93
|
+
end
|