Modules · Data · 0.09

Struct::Codec

A Perl structure to bytes and back, with nothing lost.

A cache holds bytes and a program holds structures, and on a small value the codec in between is most of the cost. Struct::Codec gives nothing up: strings stay strings, shared references stay shared, objects stay blessed. It publishes a C interface so another XS module encodes straight into memory it owns.

use Struct::Codec qw(struct_encode struct_decode);

my $roles = ['admin', 'ops'];
my $data  = { user => 'ada', zip => '007', n => 3, roles => $roles, again => $roles };

my $copy = struct_decode(struct_encode($data));

print "$copy->{zip}\n";                                       # 007, still a string
print $copy->{roles} == $copy->{again} ? "shared\n" : "two copies\n";   # shared

What you get

  • What comes back the same

    A string is a string and a number a number: "007" comes back "007". The UTF-8 flag survives, on strings and on hash keys, and on perl 5.36 and later a boolean comes back a boolean.

  • Shared, cyclic and blessed

    References that were shared are shared again and a cycle is a cycle again. A blessed referent comes back blessed, with nothing called on it: no FREEZE, no THAW.

  • What changes, said

    A weak reference comes back strong, a dualvar keeps its string, and before perl 5.36 a boolean comes back as 1 or the empty string.

  • Fast on small values

    Storable takes 1.7 microseconds to freeze and thaw a five-key hash. In its POD's measurement this is about three times faster, as JSON is, without giving up what JSON does.

In use

use Struct::Codec qw(struct_encode struct_decode);

package Point { sub new { my ($c, %a) = @_; bless {%a}, $c } }

my $p = Point->new(x => 1, y => 2);
my $loop = { name => 'loop' };
$loop->{self} = $loop;                         # a cycle

my ($p2, $loop2) = @{ struct_decode(struct_encode([$p, $loop])) };
print ref $p2, " at $p2->{x},$p2->{y}\n";      # Point at 1,2
print $loop2->{self} == $loop2 ? "a cycle again\n" : "broken\n";

For C

sc_abi.h, resolved at run time through Struct::Codec::_abi_ptr: another XS module encodes a value straight into memory it owns and decodes one straight out, with no Perl call in between and no link-time coupling.

Get it

cpanm Struct::Codec