Class: Factorix::SerDes::Deserializer
- Inherits:
-
Object
- Object
- Factorix::SerDes::Deserializer
- Defined in:
- lib/factorix/ser_des/deserializer.rb
Overview
Deserialize data from binary format
This class provides methods to deserialize various data types from Factorio’s binary file format, following the specifications documented in the Factorio wiki.
Instance Method Summary collapse
-
#eof? ⇒ Boolean
Check if the stream is at EOF.
-
#initialize(stream, logger: nil) ⇒ Deserializer
constructor
Create a new Deserializer instance.
-
#read_bool ⇒ Boolean
Read a boolean value.
-
#read_bytes(length) ⇒ String
Read raw bytes from the stream.
-
#read_dictionary ⇒ Hash
(also: #read_list)
Read a dictionary.
-
#read_double ⇒ Float
Read a double-precision floating point number.
-
#read_game_version ⇒ GameVersion
Read a GameVersion object.
-
#read_long ⇒ Integer
Read a signed long integer (8 bytes).
-
#read_mod_version ⇒ MODVersion
Read a MODVersion object.
-
#read_optim_u16 ⇒ Integer
Read a space-optimized 16-bit unsigned integer.
-
#read_optim_u32 ⇒ Integer
Read a space-optimized 32-bit unsigned integer.
-
#read_property_tree ⇒ Object
Read a property tree.
-
#read_str ⇒ String
Read a string.
-
#read_str_property ⇒ String
Read a string property.
-
#read_u16 ⇒ Integer
Read an unsigned 16-bit integer.
-
#read_u16_tuple(length) ⇒ Array<Integer>
Read a tuple of 16-bit unsigned integers.
-
#read_u32 ⇒ Integer
Read an unsigned 32-bit integer.
-
#read_u8 ⇒ Integer
Read an unsigned 8-bit integer.
-
#read_unsigned_long ⇒ Integer
Read an unsigned long integer (8 bytes).
Constructor Details
#initialize(stream, logger: nil) ⇒ Deserializer
Create a new Deserializer instance
20 21 22 23 24 25 26 |
# File 'lib/factorix/ser_des/deserializer.rb', line 20 def initialize(stream, logger: nil) super(logger:) raise ArgumentError, "can't read from the given argument" unless stream.respond_to?(:read) @stream = stream logger.debug "Initializing Deserializer" end |
Instance Method Details
#eof? ⇒ Boolean
Check if the stream is at EOF
195 |
# File 'lib/factorix/ser_des/deserializer.rb', line 195 def eof? = @stream.eof? |
#read_bool ⇒ Boolean
Read a boolean value
90 |
# File 'lib/factorix/ser_des/deserializer.rb', line 90 def read_bool = read_u8 != 0 |
#read_bytes(length) ⇒ String
Read raw bytes from the stream
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/factorix/ser_des/deserializer.rb', line 34 def read_bytes(length) raise InvalidLengthError, "nil length" if length.nil? raise InvalidLengthError, "negative length #{length}" if length.negative? return +"" if length.zero? bytes = @stream.read(length) if bytes.nil? || bytes.size < length logger.debug("Unexpected EOF", requested_bytes: length) raise EOFError end bytes end |
#read_dictionary ⇒ Hash Also known as: read_list
Read a dictionary
136 137 138 139 140 141 142 143 |
# File 'lib/factorix/ser_des/deserializer.rb', line 136 def read_dictionary length = read_u32 logger.debug("Reading dictionary", length:) length.times.each_with_object({}) do |_i, dict| key = read_str_property dict[key] = read_property_tree end end |
#read_double ⇒ Float
Read a double-precision floating point number
110 |
# File 'lib/factorix/ser_des/deserializer.rb', line 110 def read_double = read_bytes(8).unpack1("d") |
#read_game_version ⇒ GameVersion
Read a GameVersion object
115 |
# File 'lib/factorix/ser_des/deserializer.rb', line 115 def read_game_version = GameVersion.from_numbers(read_u16, read_u16, read_u16, read_u16) |
#read_long ⇒ Integer
Read a signed long integer (8 bytes)
125 |
# File 'lib/factorix/ser_des/deserializer.rb', line 125 def read_long = read_bytes(8).unpack1("q<") |
#read_mod_version ⇒ MODVersion
Read a MODVersion object
120 |
# File 'lib/factorix/ser_des/deserializer.rb', line 120 def read_mod_version = MODVersion.from_numbers(read_optim_u16, read_optim_u16, read_optim_u16) |
#read_optim_u16 ⇒ Integer
Read a space-optimized 16-bit unsigned integer
67 68 69 70 |
# File 'lib/factorix/ser_des/deserializer.rb', line 67 def read_optim_u16 byte = read_u8 byte == 0xFF ? read_u16 : byte end |
#read_optim_u32 ⇒ Integer
Read a space-optimized 32-bit unsigned integer
76 77 78 79 |
# File 'lib/factorix/ser_des/deserializer.rb', line 76 def read_optim_u32 byte = read_u8 byte == 0xFF ? read_u32 : byte end |
#read_property_tree ⇒ Object
Read a property tree
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/factorix/ser_des/deserializer.rb', line 155 def read_property_tree type = read_u8 _any_type_flag = read_bool logger.debug("Reading property tree", type:) case type when 0 # Handle type 0 - None (null value) # # @see https://wiki.factorio.com/Property_tree nil when 1 read_bool when 2 read_double when 3 read_str_property when 4 read_list when 5 read_dictionary when 6 # Handle type 6 - Signed integer # # @see https://wiki.factorio.com/Property_tree SignedInteger.new(read_long) when 7 # Handle type 7 - Unsigned integer # # @see https://wiki.factorio.com/Property_tree UnsignedInteger.new(read_unsigned_long) else logger.debug("Unknown property type", type:) raise UnknownPropertyType, "Unknown property type: #{type}" end end |
#read_str ⇒ String
Read a string
95 96 97 98 |
# File 'lib/factorix/ser_des/deserializer.rb', line 95 def read_str length = read_optim_u32 read_bytes(length).force_encoding(Encoding::UTF_8) end |
#read_str_property ⇒ String
Read a string property
104 |
# File 'lib/factorix/ser_des/deserializer.rb', line 104 def read_str_property = read_bool ? "" : read_str |
#read_u16 ⇒ Integer
Read an unsigned 16-bit integer
56 |
# File 'lib/factorix/ser_des/deserializer.rb', line 56 def read_u16 = read_bytes(2).unpack1("v") |
#read_u16_tuple(length) ⇒ Array<Integer>
Read a tuple of 16-bit unsigned integers
85 |
# File 'lib/factorix/ser_des/deserializer.rb', line 85 def read_u16_tuple(length) = Array.new(length) { read_u16 } |
#read_u32 ⇒ Integer
Read an unsigned 32-bit integer
61 |
# File 'lib/factorix/ser_des/deserializer.rb', line 61 def read_u32 = read_bytes(4).unpack1("V") |
#read_u8 ⇒ Integer
Read an unsigned 8-bit integer
51 |
# File 'lib/factorix/ser_des/deserializer.rb', line 51 def read_u8 = read_bytes(1).unpack1("C") |
#read_unsigned_long ⇒ Integer
Read an unsigned long integer (8 bytes)
130 |
# File 'lib/factorix/ser_des/deserializer.rb', line 130 def read_unsigned_long = read_bytes(8).unpack1("Q<") |