Affix
view release on metacpan or search on metacpan
t/035_magic_struct.t view on Meta::CPAN
# Allocate memory for 5 integers
my $ptr = Affix::malloc( sizeof( Array [ Int, 5 ] ) );
memset( $ptr, 0, sizeof( Array [ Int, 5 ] ) );
# Cast to Pointer[Int] so Affix knows the element size
$ptr = cast( $ptr, Array [ Int, 5 ] );
# ACT: Write to various indices
$ptr->[0] = 10;
$ptr->[4] = 50;
# ASSERT: Check raw memory via pointer arithmetic to confirm direct write
is cast( $ptr, Int ), 10, 'Index 0 wrote to base address';
is cast( ptr_add( $ptr, sizeof(Int) * 4 ), Int ), 50, 'Index 4 wrote to correct offset';
# ASSERT: Read back via indexing
is $ptr->[0], 10, 'Read back index 0';
is $ptr->[4], 50, 'Read back index 4';
};
subtest 'Magical Array Indexing (Nested Structs)' => sub {
# Allocate memory for 2 Points
my $ptr = Affix::malloc( sizeof( Array [ Point(), 2 ] ) );
memset( $ptr, 0, sizeof( Array [ Point(), 2 ] ) );
$ptr = cast( $ptr, Array [ Point(), 2 ] );
# ACT: Access second point and modify field
# This combines the Magical Array FETCH and Magical Hash BIND
$ptr->[1]{y} = 99;
# ASSERT: Verify offset calculation
# Point 0: 8 bytes, Point 1: starts at +8. 'y' is at +4. Total offset = 12.
my $raw_val = cast( ptr_add( $ptr, 12 ), Int );
is $raw_val, 99, 'Direct write through index and hash field worked';
is $ptr->[1]{y}, 99, 'Lazy read back through index and hash worked';
};
subtest 'Array Element Longevity' => sub {
my $element_ref;
{
my $root = Affix::malloc( sizeof(Int) * 10 );
$root = cast( $root, Array [Int] );
$root->[5] = 12345;
# Take a reference to a specific element's magical SV
$element_ref = \( $root->[5] );
# $root goes out of scope here.
# In the new system, $element_ref's magic keeps the root alive.
}
# ASSERT: We can still read and write to the element
is $$element_ref, 12345, 'Magical element SV kept root memory alive';
$$element_ref = 54321;
is $$element_ref, 54321, 'Magical element SV still writable after root object scope ended';
};
subtest 'Out of bounds (C-style)' => sub {
# In C, pointers don't have bounds. Our magical system should behave like C.
# To prevent ACTUAL heap corruption (which crashes the Perl allocator
# during global destruction), we allocate enough backing memory here.
my $ptr = Affix::malloc( 15 * sizeof(Int) );
$ptr = cast( $ptr, Pointer [Int] );
# This is "dangerous" but should work without a Perl exception
# because it's just pointer arithmetic.
#~ ok lives { $ptr->[10] = 0 }, 'Accessing out-of-bounds index does not throw Perl exception';
# Since pointers have no bounds and we avoid `tie`, pointer arithmetic
# is done explicitly via ptr_add.
my $p10 = ptr_add( $ptr, 10 * sizeof(Int) );
ok lives { $$p10 = 0 }, 'Accessing out-of-bounds memory via ptr_add does not throw Perl exception';
};
#
done_testing;
( run in 1.514 second using v1.01-cache-2.11-cpan-84de2e75c66 )