Affix
view release on metacpan or search on metacpan
t/999_marshaller_2.t view on Meta::CPAN
# Set with int
$task->{status} = 2;
is "$task->{status}", 'SUCCESS', 'Enum set by integer matches string SUCCESS';
# Make sure it's a dualvar
ok( $task->{status} == 2 && $task->{status} eq 'SUCCESS', 'Enum is a proper Dualvar' );
};
subtest auto => sub {
my $mem = alloc_owned( sizeof( AutoTask() ) );
my $task = cast( $mem, AutoTask() );
# Write to Enum by String Name
$task->{status} = 'RUNNING';
# Internal representation validation (No off-by-one)
is int $task->{status}, 1, 'Enum written by name resolves to exact integer 1';
# Dualvar retrieval check (SVt_PVIV upgrade successful in C)
is "$task->{status}", 'RUNNING', 'Enum read back retains string mapping (Dualvar SV Upgrade successful)';
# VTable Shadowing verification (C interception is correctly scoped to vtbl_enum)
$task->{status} = 2;
is "$task->{status}", 'SUCCESS', 'Enum written by integer successfully stringifies to mapped name';
ok( $task->{status} == 2 && $task->{status} eq 'SUCCESS', 'Dualvar operations work symmetrically in Perl' );
# Auto-enumerated Enums verification
$task->{auto} = 'PROCESSED';
is int( $task->{auto} ), 1, 'Implicit enum correctly evaluated next index as integer 1';
# VTable scoping / memory boundaries
is is_pin($task), T(), 'Task pointer is natively tracked as a v2 FFI Pin';
}
};
subtest 'Feature: Signed Bitfields' => sub {
# 4-bit signed bitfield (range: -8 to 7)
typedef Bits => Struct [ low => SInt8 | 4, high => SInt8 | 4 ];
my $mem = alloc_owned( sizeof( Bits() ) );
my $b = cast( $mem, Bits() );
$b->{low} = 3;
is $b->{low}, 3, 'Positive bitfield value is correct';
# Assign -3 to the 4-bit signed field
$b->{high} = -3;
# Due to sign extension, -3 (1101 in 4-bit two's complement) should read back as -3
is $b->{high}, -3, 'Negative signed bitfield is correctly sign-extended on read';
$b->{low} = -8;
is $b->{low}, -8, 'Min bounds of 4-bit signed field is -8';
};
subtest 'Feature: Pointer-to-Pointer / StringList (char**)' => sub {
typedef Cmd => Struct [ argc => Int, argv => Pointer [ Pointer [Char] ] ];
my $mem = alloc_owned( sizeof( Cmd() ) );
my $cmd = cast( $mem, Cmd() );
# Native assignment of an ArrayRef to a char** field
$cmd->{argv} = [ "hello", "world", "ffi" ];
$cmd->{argc} = 3;
# FFI-intercept read: Pointer to Pointer converts seamlessly back to ArrayRef
my $read_back = $cmd->{argv};
is ref($read_back), 'ARRAY', 'StringList reads back as a native Perl ArrayRef';
is scalar(@$read_back), 3, 'ArrayRef has correct element count';
is $read_back->[0], 'hello', 'Element 0 matches';
is $read_back->[1], 'world', 'Element 1 matches';
is $read_back->[2], 'ffi', 'Element 2 matches';
};
subtest 'Feature: Const-Correctness / Readonly Pins' => sub {
typedef Info => Struct [ version => Float, author => String ];
my $mem = alloc_owned( sizeof( Info() ) );
my $info = cast( $mem, Info() );
$info->{version} = 1.0;
# Apply readonly state
ok !Affix::readonly($info), 'Pin defaults to mutable';
Affix::readonly( $info, 1 );
ok Affix::readonly($info), 'Pin is now marked readonly';
# Attempting to assign should croak
like dies {
$info->{version} = 2.0;
}, qr/Modification of a read-only C value attempted/, 'Caught illegal write to readonly pin';
is $info->{version}, 1.0, 'Value remained unmodified after exception';
# Unlock
Affix::readonly( $info, 0 );
$info->{version} = 2.0;
is $info->{version}, 2.0, 'Value successfully modified after unlocking';
};
subtest 'Feature: SIMD Vectors' => sub {
# 4-element single-precision float vector
typedef SimdType => Vector [ 4, Float32 ];
my $mem = alloc_owned( sizeof( SimdType() ) );
my $vec = cast( $mem, SimdType() );
# Vectors map to arrayrefs natively during bind
$vec->[0] = 1.1;
$vec->[1] = 2.2;
$vec->[2] = 3.3;
$vec->[3] = 4.4;
is int( $vec->[0] ), 1, 'SIMD element 0 read OK';
is int( $vec->[3] ), 4, 'SIMD element 3 read OK';
};
subtest varargs => sub {
affix libc, [ 'sprintf' => 'my_sprintf' ], [ Pointer [SChar], Pointer [SChar], VarArgs ], Int;
typedef Vec => Struct [ x => Int, y => Int ];
my $mem = alloc_owned( sizeof( Vec() ) );
my $v = cast( $mem, Vec() );
$v->{x} = 100;
$v->{y} = 200;
# Test 1: Pass v2 members to variadic
my $out = " " x 100;
# sprintf(buf, "%d %d", v->x, v->y)
# Affix must extract the integers from the magical scalars
my_sprintf( $out, "%d and %d", $v->{x}, $v->{y} );
like $out, qr/100 and 200/, 'Variadic correctly marshalled V2 magical members';
( run in 0.284 second using v1.01-cache-2.11-cpan-aadc1410aed )