/ la condizione / ruby ​​restituisce nil invece di true / false - ruby, encoding, byte

la condizione di ruby ​​restituisce nil invece di true / false - ruby, encoding, byte

Sto usando Ruby 2.0.0p451 (2014-02-24) [x64-mingw32] e mi sono imbattuto in qualcosa che precedentemente funzionava nella versione 1.9.x che non funziona qui. Mi stavo chiedendo se hanno cambiato il comportamento, o se sto facendo qualcosa di sbagliato, o se questo è un bug.

Sto mandando un byte in un socket xFF e lo ricevo dall'altra parte, ma quando provo a confrontarlo con se stesso (che dovrebbe restituire true) non restituisce l'output atteso.

Esempio, invio la stringa xFFx50x00usernamex00555x00 e lo ricevo bene dall'altra parte, ma quando provo a confrontare il primo byte con se stesso, il condizionale si comporta in modo errato.

Ecco alcuni esempi di codice in modo da poter vedere come sto gestendo i dati (scremato al codice rilevante)

class PacketReceiver
def setpacket( buffer ); @buffer = buffer; end
def getbyte
byte = @buffer[0..0]
@buffer = @buffer[1..-1]
byte
end
end

def parsepacket(packet)
#@receiver = PacketReceiver.new #defined elsewhere in code
@receiver.setpacket packet

return false unless @reciever.getbyte.eql? "xFF" #the bugged line

#Everything works beyond this point
packet_id = @reciever.getbyte

case packet_id
when "x50"
return sid_requesting_config
when "x51"
sid_requesting_data_response
when "x52"
sid_keep_alive_response
else
puts "failed"
return false
end
return true
end

In 1.9.X Questo unless la dichiarazione stava funzionando bene. Durante il debug dei dati, i dati restituiti da @receiver.getbyte è davvero "xFF", ma per qualche motivo il eql? il confronto restituisce false anziché true causando il ritorno della funzione false. Se rimuovo questo byte dal messaggio e rimuovo il resto del codice chiamando anche il getbyte il metodo funziona bene.

Anche se cambio il byte in "x55" piuttosto che "xFF" il condizionale unless la dichiarazione funziona come dovrebbe

Non sono sicuro di cosa stia succedendo. XFF è riservato a qualcosa?

risposte:

0 per risposta № 1

Lo sto indovinando buffer è codificato in binario (ad es. buffer.encoding è ASCII-8BIT). Ciò significa che ciò sta accadendo:

c  = @receiver.getbyte # c also has binary encoding
ff = "xff"            # ff is probably utf-8
c.eql? ff              # comparing strings in different encodings gives you `false`

Invece, dovresti fare semplici confronti numerici:

@receiver.getbyte.getbyte(0) == 255

O ancora meglio, modificare getbyte per restituire un intero.

Penso che la tua versione 1.9.X funzionasse principalmente per sbaglio, avresti dovuto usare sempre un semplice confronto numerico.

Tieni presente che nel buffer sono presenti byte (come 0xFF e 0x00) che non sono validi nelle stringhe utf-8, pertanto è consigliabile mantenere il buffer in binario. Puoi usare force_encoding su sezioni del buffer per le parti che sono stringhe utf-8. Potresti voler dare un'occhiata String#unpack anche.


Nota che sto collegando i documenti specifici di Ruby 2.0.0 in modo che corrispondano alla versione di Ruby attualmente in uso.