package Net::AMQP::Frame;

=head1 NAME

Net::AMQP::Frame - AMQP wire-level Frame object


use strict;
use warnings;
use base qw(Class::Data::Inheritable Class::Accessor::Fast);
use Net::AMQP::Common qw(:all);
use Carp;


# Use all the subclasses
use Net::AMQP::Frame::Method;
use Net::AMQP::Frame::Header;
use Net::AMQP::Frame::Body;
use Net::AMQP::Frame::OOBMethod;
use Net::AMQP::Frame::OOBHeader;
use Net::AMQP::Frame::OOBBody;
use Net::AMQP::Frame::Trace;
use Net::AMQP::Frame::Heartbeat;


=head2 new

Takes an arbitrary list of key/value pairs and casts it into this class.  Nothing special here.


sub new {
    my ($class, %self) = @_;
    return bless \%self, $class;

=head2 factory

    type_id => 1,
    channel => 1,
    payload => '',

Will attempt to identify a L<Net::AMQP::Frame> subclass for further parsing, and will croak on failure.  Returns a L<Net::AMQP::Frame> subclass object.


sub factory {
    my ($class, %args) = @_;

    unless (exists $args{type_id}) { croak "Mandatory parameter 'type_id' missing in call to Net::AMQP::Frame::factory"; }
    unless (exists $args{channel}) { croak "Mandatory parameter 'channel' missing in call to Net::AMQP::Frame::factory"; }
    unless (exists $args{payload}) { croak "Mandatory parameter 'payload' missing in call to Net::AMQP::Frame::factory"; }
    unless (keys %args == 3)       { croak "Invalid parameter passed in call to Net::AMQP::Frame::factory"; }

    my $subclass;
    if ($args{type_id} == 1) {
        $subclass = 'Method';
    elsif ($args{type_id} == 2) {
        $subclass = 'Header';
    elsif ($args{type_id} == 3) {
        $subclass = 'Body';
    elsif ($args{type_id} == 8) {
        $subclass = 'Heartbeat';
    else {
        croak "Unknown type_id $args{type_id}";

    $subclass = 'Net::AMQP::Frame::' . $subclass;
    my $object = bless \%args, $subclass;
    return $object;


=head2 Field accessors

Each subclass extends these accessors, but they share in common the following:

=over 4

=item I<type_id>

=item I<channel>

=item I<size>

=item I<payload>


=head2 parse_payload

Performs the parsing of the 'payload' binary data.

=head2 to_raw_payload

Returns the binary data the represents this frame's payload.

=head2 to_raw_frame

Returns a raw binary string representing this frame on the wire.


sub to_raw_frame {
    my $self = shift;
    my $class = ref $self;

    if (! defined $self->channel) {

    return pack('Cn', $self->type_id, $self->channel)
        . pack_long_string($self->to_raw_payload())
        . pack('C', 206);

=head2 type_string

Returns a string that uniquely represents this frame type, such as 'Method Basic.Consume', 'Header Basic' or 'Body'


sub type_string {
    my $self = shift;

    my ($type) = ref($self) =~ m{::([^:]+)$};

    my $subtype;
    if ($self->can('method_frame')) {
        ($subtype) = ref($self->method_frame) =~ m{^Net::AMQP::Protocol::(.+)$};
        my ($class, $method) = split /::/, $subtype;
        $subtype = join '.', $class, $method;
    elsif ($self->can('header_frame')) {
        ($subtype) = ref($self->header_frame) =~ m{^Net::AMQP::Protocol::(.+)::ContentHeader$};

    return $type . ($subtype ? " $subtype" : '');

=head1 SEE ALSO



Copyright (c) 2009 Eric Waters and XMission LLC (  All rights reserved.  This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the LICENSE file included with this module.

=head1 AUTHOR

Eric Waters <>