Affix

 view release on metacpan or  search on metacpan

t/035_magic_struct.t  view on Meta::CPAN

use v5.40;
use Test2::V0;
use blib;
use Affix qw[:all];

# Define our structure
typedef Point => Struct [ x => Int, y => Int ];
typedef Transform => Struct [ origin => Point(), scale => Float ];
#
subtest 'Direct memory write-back' => sub {

    # Allocate raw memory
    my $ptr = Affix::malloc( sizeof( Point() ) );

    # Initialize memory to zeros manually
    memset( $ptr, 0, sizeof( Point() ) );

    # BIND the hash to the pointer (The new system)
    my $struct = cast $ptr, Point();

    # ACT: Modify the hash
    $struct->{x} = 123;
    $struct->{y} = 456;

    # ASSERT: Read raw memory back using cast (bypassing the hash magic)
    my $raw_x = cast $ptr, Int;
    my $raw_y = cast ptr_add( $ptr, 4 ), Int;    # offset of 'y' is 4
    is $raw_x, 123, 'C memory for x updated immediately';
    is $raw_y, 456, 'C memory for y updated immediately';
};
subtest 'Reference counting and persistence' => sub {
    my $sub_hash;
    {
        my $root_ptr = Affix::malloc( sizeof( Transform() ) );
        my $tx       = cast $root_ptr, Transform();

        # Grab a reference to a nested struct
        $sub_hash = $tx->{origin};
    }

    # Attempt to write to the sub-hash after parent is technically "gone"
    $sub_hash->{y} = 77;

    # If we are here and haven't crashed, success.
    # We can verify by re-pinning a pointer to see if the value is there.
    is $sub_hash->{y}, 77, 'Sub-struct remains valid and writable after parent scope ends';
};
subtest 'Magical Array Indexing (Primitives)' => sub {

    # 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 );



( run in 2.284 seconds using v1.01-cache-2.11-cpan-bbc515a03b3 )