Class: BSV::Wallet::Wire::Reader
- Inherits:
-
Object
- Object
- BSV::Wallet::Wire::Reader
- Defined in:
- lib/bsv/wallet/wire/reader_writer.rb
Overview
Reader reads sequentially from a binary string.
Instance Method Summary collapse
-
#initialize(data) ⇒ Reader
constructor
A new instance of Reader.
-
#next_negative_one? ⇒ Boolean
Whether the next varint is the NegativeOne sentinel (0xFFFF…).
-
#peek_byte ⇒ Integer
Look at the next byte without consuming it.
-
#read_base64_int ⇒ String
Read a binary value and return it Base64-encoded.
-
#read_byte ⇒ Integer
Read a single byte.
-
#read_bytes(n) ⇒ String
Read
nraw bytes. -
#read_int_bytes ⇒ String
Read a varint-length-prefixed byte array (ReadIntBytes in Go).
-
#read_optional_bool ⇒ Boolean?
Read an optional boolean byte (Go/BRC-103 convention).
-
#read_optional_bytes_with_flag(fixed_size: nil) ⇒ String?
Read optional bytes with a 1-byte flag prefix (Go BytesOptionWithFlag).
-
#read_optional_string ⇒ String?
Read an optional string: NegativeOne sentinel → nil; else varint len + bytes.
-
#read_optional_uint32 ⇒ Integer?
Read an optional uint32: NegativeOne sentinel → nil; else varint → Integer.
-
#read_outpoint ⇒ Hash
Read an outpoint: 32-byte display-order txid + varint vout.
-
#read_privileged_params ⇒ Array(Boolean|nil, String|nil)
Read privileged params (Go decodePrivilegedParams).
-
#read_remaining ⇒ String
Read all remaining bytes.
-
#read_satoshis ⇒ Integer
Read 8-byte little-endian uint64 satoshi amount.
-
#read_str_with_varint_len ⇒ String
Read a varint-prefixed UTF-8 string.
-
#read_string ⇒ String
Read a varint-len string (always present, 0-length = empty string).
-
#read_string_map ⇒ Hash<String,String>
Read a string map: varint count + key/value pairs (each varint-len-prefixed).
-
#read_string_slice ⇒ Array<String>?
Read an array of strings encoded as varint count + each optional string.
-
#read_txid_slice ⇒ Array<String>?
Read a txid slice: NegativeOne → nil; else varint count + 32 bytes per txid.
-
#read_varint ⇒ Integer
Read a Bitcoin varint.
-
#remaining ⇒ Object
Remaining bytes.
Constructor Details
#initialize(data) ⇒ Reader
Returns a new instance of Reader.
202 203 204 205 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 202 def initialize(data) @data = data.b @pos = 0 end |
Instance Method Details
#next_negative_one? ⇒ Boolean
Whether the next varint is the NegativeOne sentinel (0xFFFF…). Peeks at the next byte without consuming it.
293 294 295 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 293 def next_negative_one? @pos < @data.bytesize && @data.getbyte(@pos) == 0xFF end |
#peek_byte ⇒ Integer
Look at the next byte without consuming it.
219 220 221 222 223 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 219 def peek_byte raise ArgumentError, 'unexpected end of data peeking byte' if @pos >= @data.bytesize @data.getbyte(@pos) end |
#read_base64_int ⇒ String
Read a binary value and return it Base64-encoded.
345 346 347 348 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 345 def read_base64_int raw = read_int_bytes Base64.strict_encode64(raw) end |
#read_byte ⇒ Integer
Read a single byte.
209 210 211 212 213 214 215 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 209 def read_byte raise ArgumentError, 'unexpected end of data reading byte' if @pos >= @data.bytesize byte = @data.getbyte(@pos) @pos += 1 byte end |
#read_bytes(n) ⇒ String
Read n raw bytes.
227 228 229 230 231 232 233 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 227 def read_bytes(n) raise ArgumentError, "need #{n} bytes at offset #{@pos}, got #{remaining}" if remaining < n slice = @data.byteslice(@pos, n) @pos += n slice end |
#read_int_bytes ⇒ String
Read a varint-length-prefixed byte array (ReadIntBytes in Go).
299 300 301 302 303 304 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 299 def read_int_bytes len = read_varint return ''.b if len == 0xFFFF_FFFF_FFFF_FFFF || len.zero? read_bytes(len) end |
#read_optional_bool ⇒ Boolean?
Read an optional boolean byte (Go/BRC-103 convention). 0xFF → nil, 0x00 → false, 0x01 → true
257 258 259 260 261 262 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 257 def read_optional_bool byte = read_byte return nil if byte == 0xFF byte == 0x01 end |
#read_optional_bytes_with_flag(fixed_size: nil) ⇒ String?
Read optional bytes with a 1-byte flag prefix (Go BytesOptionWithFlag). 0x00 → nil; 0x01 → read varint_len + bytes (or fixed_size bytes).
379 380 381 382 383 384 385 386 387 388 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 379 def read_optional_bytes_with_flag(fixed_size: nil) flag = read_byte return nil if flag.zero? if fixed_size read_bytes(fixed_size) else read_int_bytes end end |
#read_optional_string ⇒ String?
Read an optional string: NegativeOne sentinel → nil; else varint len + bytes.
315 316 317 318 319 320 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 315 def read_optional_string val = read_varint return nil if val == 0xFFFF_FFFF_FFFF_FFFF read_bytes(val).force_encoding('UTF-8') end |
#read_optional_uint32 ⇒ Integer?
Read an optional uint32: NegativeOne sentinel → nil; else varint → Integer.
308 309 310 311 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 308 def read_optional_uint32 val = read_varint val == 0xFFFF_FFFF_FFFF_FFFF ? nil : val end |
#read_outpoint ⇒ Hash
Read an outpoint: 32-byte display-order txid + varint vout.
272 273 274 275 276 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 272 def read_outpoint txid_bytes = read_bytes(32) vout = read_varint { txid_hex: txid_bytes.unpack1('H*'), vout: vout } end |
#read_privileged_params ⇒ Array(Boolean|nil, String|nil)
Read privileged params (Go decodePrivilegedParams).
352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 352 def read_privileged_params privileged = read_optional_bool first_byte = read_byte if first_byte == 0xFF [privileged, nil] else # Back up one byte and read as varint-prefixed string @pos -= 1 reason = read_str_with_varint_len [privileged, reason] end end |
#read_remaining ⇒ String
Read all remaining bytes.
285 286 287 288 289 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 285 def read_remaining slice = @data.byteslice(@pos, @data.bytesize - @pos) || ''.b @pos = @data.bytesize slice end |
#read_satoshis ⇒ Integer
Read 8-byte little-endian uint64 satoshi amount.
266 267 268 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 266 def read_satoshis read_bytes(8).unpack1('Q<') end |
#read_str_with_varint_len ⇒ String
Read a varint-prefixed UTF-8 string.
246 247 248 249 250 251 252 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 246 def read_str_with_varint_len len = read_varint str = read_bytes(len).force_encoding('UTF-8') raise ArgumentError, 'varint-prefixed string is not valid UTF-8' unless str.valid_encoding? str end |
#read_string ⇒ String
Read a varint-len string (always present, 0-length = empty string). Matches Go ReadString which returns “” for length 0 or NegativeOne.
393 394 395 396 397 398 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 393 def read_string len = read_varint return '' if len.zero? || len == 0xFFFF_FFFF_FFFF_FFFF read_bytes(len).force_encoding('UTF-8') end |
#read_string_map ⇒ Hash<String,String>
Read a string map: varint count + key/value pairs (each varint-len-prefixed).
334 335 336 337 338 339 340 341 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 334 def read_string_map count = read_varint count.times.each_with_object({}) do |_, h| k = read_str_with_varint_len v = read_str_with_varint_len h[k] = v end end |
#read_string_slice ⇒ Array<String>?
Read an array of strings encoded as varint count + each optional string. NegativeOne sentinel count → nil.
325 326 327 328 329 330 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 325 def read_string_slice count = read_varint return nil if count == 0xFFFF_FFFF_FFFF_FFFF count.times.map { read_optional_string || '' } end |
#read_txid_slice ⇒ Array<String>?
Read a txid slice: NegativeOne → nil; else varint count + 32 bytes per txid. Go stores txids in wire order (txID) — returned as hex without reversal.
368 369 370 371 372 373 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 368 def read_txid_slice count = read_varint return nil if count == 0xFFFF_FFFF_FFFF_FFFF count.times.map { read_bytes(32).unpack1('H*') } end |
#read_varint ⇒ Integer
Read a Bitcoin varint.
237 238 239 240 241 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 237 def read_varint value, consumed = BSV::Transaction::VarInt.decode(@data, @pos) @pos += consumed value end |
#remaining ⇒ Object
Remaining bytes.
279 280 281 |
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 279 def remaining @data.bytesize - @pos end |