LINUX.ORG.RU

Удобная упаковка/распаковка бинарных форматов по описанию?

 , ,


1

1

Нужно, чтобы по описанию структуры данных в духе: «поле hostid - целое 32 бита, поле trigger_value - целое беззнаковое один байт, поле groups - вектор из целых беззнаковых 32-х битных, поле description - строка в C-стиле, терминированная нулевым байтом» - можно было передавать в функцию запаковки структуру и получать на выходе компактное бинарное представление, ну и наоборот - совать компактное бинарное представление в функцию распаковки и получать на выходе структуру.

Суть в том, что BJSON'ы и CBOR'ы не подходят, поскольку хранят названия поле. Нужен вариант простой бинарной упаковки, когда назначение поля определяется порядком расположения его в бинарном представлении («первым идёт поле hostid, вторым - поле trigger_value, третьим - ... etc»).

Может, кто сталкивался с подобным готовым пакетом, а то колхозить не хочется.

★★★★★
Ответ на: комментарий от moot
my %struct_descr=(
  'hostid'=>{
    'index'=>0,
    'type'=>'unsigned int 32'
  },
  'triggerid'=>{
    'index'=>1,
    'type'=>'unsigned int 32'
  },
  'trigger_val'=>{
    'index'=>2,
    'type'=>'unsigned byte'      
  },
  'description'=>{
    'index'=>3,
    'type'=>'lpfx32 string' 
  }   
); 

Мне бы распаковку/упаковку по такого рода описанию. Накостылить конечно не сложно, но мало ли, вдруг внезапно уже есть.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

ну это protobuf и есть. там тоже поля пронумерованы и имеют тип. можно скомпилять, чтобы не парсить каждый раз.

https://developers.google.com/protocol-buffers/

на главной пример синтаксиса:

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}
moot ★★★★
()
Ответ на: комментарий от Olegymous

И что, pack чудесным образом знает, что у меня поле hostid - это integer? По-моему нет, не знает. Безусловно, всё можно наваять прямо ручками в коде, но хотелось бы декларативное описание преобразования из структуры данных в бинарь и обёртку pack/unpack'а, умеющую читать это описание. Так-то всегда можно сказать: чего мы вообще дурью маемся, если есть Asm или вот даже C...

DRVTiny ★★★★★
() автор топика
unpack(Scheme, Data) -> unpack(Scheme, Data, []).

unpack([], Rest, A) -> {ok, lists:reverse(A), Rest};
unpack([i32be|T], <<V:32, R/binary>>, A) -> unpack(T, R, [{i32be, V}|A]);
unpack([i32le|T], <<V:32/little, R/binary>>, A) -> unpack(T, R, [{i32le, V}|A]);
unpack([f32|T], <<V:32/float, R/binary>>, A) -> unpack(T, R, [{f32, V}|A]).
1> m:unpack([i32be,i32le,f32], <<0,0,0,1,0,0,0,1,63,128,0,0>>) .
{ok,[{i32be,1},{i32le,16777216},{f32,1.0}],<<>>}

при желании можно и unpack([{any, L, F}|T].... [F(V)|A] прикрутить и вапще песня будет

anonymous
()
Ответ на: комментарий от anonymous

Это какой-то катастрофически ужасный язык для общения биороботов, я на таком Г не пишу.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от moot

Упаковал Google::ProtoBuffers'ами:

#!/usr/bin/perl
use strict;
use warnings;

use utf8;   
use lib '.';
use Alert;
use Encode;
use Data::Dumper;

binmode *STDOUT, ':utf8';

my $bStr=Alert->encode({
  'hostid'=>2037,
  'triggerid'=>51143,
  'value'=>'PROBLEM',
  'description'=>do { open my $fh, '<', 'descr.txt'; local $/; encode('cp1251',decode('utf8',<$fh>)) }
});

use bytes;
print 'L='.length($bStr),"\n";
no bytes;

my $res=Alert->decode($bStr);
$res->{'description'}=(decode('cp1251', $res->{'description'}));

print $res->{'description'};

А в descr.txt лежит строка:

На {HOST.NAME} заканчивается место на диске C:

Слушайте, ну офигеть, мне нравится!

Получилось жалких 57 байт на всю эту мега-запись!

Я бы упаковал сам чуть компактнее, но, собственно, экономить совсем уж на спичках - тоже странно.

Спасибо за совет!!

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Правда, оказалось, что приём бинарных данных через Mojo::Redis2::subscribe после отправки через Mojo::Redis2::publish приводит к поломке этих данных по неизвестным причинам...

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от utf8nowhere

Там какой-то глупый наезд на Perl, а сама идея да, правильная.

DRVTiny ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.