XS(ffi_pl_record_accessor_[% ffi_type %])
{
  ffi_pl_record_member *member;
  SV *self;
  char *ptr1;
  [% c_type %] *ptr2;

  dVAR; dXSARGS;

  if(items == 0)
    croak("This is a method, you must provide at least the object");

  member = (ffi_pl_record_member*) CvXSUBANY(cv).any_ptr;

  self = ST(0);
  if(SvROK(self))
    self = SvRV(self);

  if(!SvOK(self))
    croak("Null record error");

  ptr1 = (char*) SvPV_nolen(self);
  ptr2 = ([% c_type %]*) &ptr1[member->offset];

  if(items > 1)
  {
    if(SvREADONLY(self))
    {
      croak("record is read-only");
    }
    else
    {
      *ptr2 = ([% c_type %]) Sv[% perl_type %](ST(1));
    }
  }

  if(GIMME_V == G_VOID)
    XSRETURN_EMPTY;

  XSRETURN_[% perl_type %](*ptr2);
}

XS(ffi_pl_record_accessor_[% ffi_type %]_array)
{
  ffi_pl_record_member *member;
  SV *self;
  SV *arg;
  SV **item;
  AV *av;
  char *ptr1;
  int i;
  [% c_type %] *ptr2;

  dVAR; dXSARGS;

  if(items == 0)
    croak("This is a method, you must provide at least the object");

  member = (ffi_pl_record_member*) CvXSUBANY(cv).any_ptr;

  self = ST(0);
  if(SvROK(self))
    self = SvRV(self);

  ptr1 = (char*) SvPV_nolen(self);
  ptr2 = ([% c_type %]*) &ptr1[member->offset];

  if(items > 1 && SvREADONLY(self))
  {
    croak("record is read-only");
  }

  if(items > 2)
  {
    i       = SvIV(ST(1));
    if(i >= 0 && i < member->count)
    {
      arg     = ST(2);
      ptr2[i] = Sv[% perl_type %](arg);
    }
    else
    {
      warn("illegal index %d", i);
    }
  }
  else if(items > 1)
  {
    arg = ST(1);
    if(SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVAV)
    {
      av = (AV*) SvRV(arg);
      for(i=0; i < member->count; i++)
      {
        item = av_fetch(av, i, 0);
        if(item != NULL && SvOK(*item))
        {
          ptr2[i] = Sv[% perl_type %](*item);
        }
        else
        {
          ptr2[i] = [% zero %];
        }
      }
    }
    else
    {
      i = SvIV(ST(1));
      if(i >= 0 && i < member->count)
      {
        XSRETURN_[% perl_type %](ptr2[i]);
      }
      else
      {
        warn("illegal index %d", i);
        XSRETURN_EMPTY;
      }
    }
  }

  if(GIMME_V == G_VOID)
    XSRETURN_EMPTY;

  av = newAV();
  av_fill(av, member->count-1);
  for(i=0; i < member->count; i++)
  {
    sv_set[% perl_type | lower %](*av_fetch(av, i, 1), ptr2[i]);
  }
  ST(0) = newRV_inc((SV*)av);
  XSRETURN(1);
}