Рубиновый эквивалент Node .toString ('ascii') - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь преобразовать приложение Node в Ruby.У меня есть буфер целых чисел, который мне нужно закодировать как строку ASCII.

В Node это делается так:

const a = Buffer([53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76])
const b = a.toString('hex')
// b = "357ff178398870d2a2c86f842e92d23e855850613a8beafcf613bf541e7ef84c"
const c = a.toString('ascii') 
// c = '5qx9\bpR"Ho\u0004.\u0012R>\u0005XPa:\u000bj|v\u0013?T\u001e~xL'

Я хочу получить тот же вывод в Ruby, но яне знаю, как конвертировать a в c.Я использовал b, чтобы проверить, что a анализируется одинаково в Ruby и Node, и похоже, что он работает.

a = [53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76].pack('C*')
b = a.unpack('H*') 
# ["357ff178398870d2a2c86f842e92d23e855850613a8beafcf613bf541e7ef84c"]
# c = ???

Я пробовал несколько вещей, практически все опции распаковки, и ятакже пытался использовать функцию кодирования, но мне не хватает понимания, в чем здесь проблема.

1 Ответ

0 голосов
/ 15 ноября 2018

Хорошо, я не очень хорошо знаком с Node.js, но вы можете довольно близко познакомиться с некоторыми основными понятиями:

Узел сообщает:

'ascii' - только для 7-битных данных ASCII. Это кодирование быстрое и, если оно установлено, удаляет старший бит.

Обновление После перечитывания описания nod.js, я думаю, это просто означает, что оно упадет 127 и сосредоточится только на первых 7 битах, поэтому это можно упростить до:

def node_js_ascii(bytes) 
  bytes.map {|b| b % 128 }
    .reject(&127.method(:==))
    .pack('C*')
    .encode(Encoding::UTF_8)
end
node_js_ascii(a)
#=>  #=> "5qx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"

Теперь единственное отличие состоит в том, что node.js использует «\ u000b» для представления вертикальной табуляции, а ruby ​​использует «\ v», а в ruby ​​используются символы в верхнем регистре вместо Юникода («\ u001E» против «\ u001e») ) (вы можете справиться с этим, если захотите)

Обратите внимание Эта форма кодирования необратима из-за того, что в вашем байтовом массиве есть символы размером более 8 бит.

TL; DR (предыдущее объяснение и решение работает только до 8 бит)

Хорошо, мы знаем, что максимальное поддерживаемое десятичное число составляет 127 ("1111111".to_i(2)), и этот узел будет отбрасывать старший бит, если установить значение [я предполагаю] 241 (8-битное число станет 113, если мы уберем старший бит)

С этим пониманием мы можем использовать:

a = [53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76].map do |b| 
    b < 128 ? b : b - 128
end.pack('C*')
#=> "5\x7Fqx9\bpR\"Ho\x04.\x12R>\x05XPa:\vj|v\x13?T\x1E~xL"

Тогда мы можем закодировать это как UTF-8 примерно так:

a.encode(Encoding::UTF_8)
#=> "5\u007Fqx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"

но здесь все еще есть проблема.

Кажется, Node.js также игнорирует Delete (127), когда он конвертирует в 'ascii' (я имею в виду, что старший бит установлен, но если мы удаляем его, то он равен 63 ("?"), Что не соответствует вывод) так что мы тоже можем это исправить

 a = [53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76].map do |b| 
    b < 127 ? b : b - 128
end.pack('C*')
#=> "5\xFFqx9\bpR\"Ho\x04.\x12R>\x05XPa:\vj|v\x13?T\x1E~xL"
a.encode(Encoding::UTF_8, undef: :replace, replace: '')
#=> "5qx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"

Теперь, поскольку 127 - 128 = -1 (отрицательный бит со знаком) становится "\ xFF" неопределенным символом в UTF-8, поэтому мы добавляем undef: :replace, что делать, если символ не определен, используйте replace и добавляем replace: '' заменить ничем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...