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