The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Net::SPDY::Compressor;

=head1 NAME

Net::SPDY::Compressor - SPDY header compressor

=head1 ALPHA WARNING

B<Please read carefully:> This is an ALPHA stage software.
In particular this means that even though it probably won't kill your cat,
re-elect George W. Bush nor install Solaris 11 Express edition to your hard
drive, it is in active development, functionality is missing and no APIs are
stable.

See F<TODO> file in the distribution to learn about missing and planned
functionality. You are more than welcome to join the development and submit
patches with fixes or enhancements.  Bug reports are probably not very useful
at this point.

=head1 SYNOPSIS

  use Net::SPDY::Compressor;

  my $compr = new Net::SPDY::Compressor;
  print $compr->uncompress($compr->compress("Hello, World!\n"));

=head1 DESCRIPTION

B<Net::SPDY::Compressor> provides a convenient way to compress data
in a way used by the SPDY protocol.

This, in particular, means, that there are two separate streams (for input and
output), streams are synced after each message and the stream is initialized
with a dictionary of strings common to web communication.

=cut

use strict;
use warnings;

use Compress::Zlib qw/inflateInit deflateInit Z_SYNC_FLUSH/;

our $VERSION = '0.1';

=head1 CONSTANTS

For the actual values refer to the protocol specification.

=over 4

=item C<DICT>

The initial SPDY compression dictionary.

=back

=cut

use constant DICT =>
	"\x00\x00\x00\x07\x6f\x70\x74\x69". #----opti
	"\x6f\x6e\x73\x00\x00\x00\x04\x68". #ons----h
	"\x65\x61\x64\x00\x00\x00\x04\x70". #ead----p
	"\x6f\x73\x74\x00\x00\x00\x03\x70". #ost----p
	"\x75\x74\x00\x00\x00\x06\x64\x65". #ut----de
	"\x6c\x65\x74\x65\x00\x00\x00\x05". #lete----
	"\x74\x72\x61\x63\x65\x00\x00\x00". #trace---
	"\x06\x61\x63\x63\x65\x70\x74\x00". #-accept-
	"\x00\x00\x0e\x61\x63\x63\x65\x70". #---accep
	"\x74\x2d\x63\x68\x61\x72\x73\x65". #t-charse
	"\x74\x00\x00\x00\x0f\x61\x63\x63". #t----acc
	"\x65\x70\x74\x2d\x65\x6e\x63\x6f". #ept-enco
	"\x64\x69\x6e\x67\x00\x00\x00\x0f". #ding----
	"\x61\x63\x63\x65\x70\x74\x2d\x6c". #accept-l
	"\x61\x6e\x67\x75\x61\x67\x65\x00". #anguage-
	"\x00\x00\x0d\x61\x63\x63\x65\x70". #---accep
	"\x74\x2d\x72\x61\x6e\x67\x65\x73". #t-ranges
	"\x00\x00\x00\x03\x61\x67\x65\x00". #----age-
	"\x00\x00\x05\x61\x6c\x6c\x6f\x77". #---allow
	"\x00\x00\x00\x0d\x61\x75\x74\x68". #----auth
	"\x6f\x72\x69\x7a\x61\x74\x69\x6f". #orizatio
	"\x6e\x00\x00\x00\x0d\x63\x61\x63". #n----cac
	"\x68\x65\x2d\x63\x6f\x6e\x74\x72". #he-contr
	"\x6f\x6c\x00\x00\x00\x0a\x63\x6f". #ol----co
	"\x6e\x6e\x65\x63\x74\x69\x6f\x6e". #nnection
	"\x00\x00\x00\x0c\x63\x6f\x6e\x74". #----cont
	"\x65\x6e\x74\x2d\x62\x61\x73\x65". #ent-base
	"\x00\x00\x00\x10\x63\x6f\x6e\x74". #----cont
	"\x65\x6e\x74\x2d\x65\x6e\x63\x6f". #ent-enco
	"\x64\x69\x6e\x67\x00\x00\x00\x10". #ding----
	"\x63\x6f\x6e\x74\x65\x6e\x74\x2d". #content-
	"\x6c\x61\x6e\x67\x75\x61\x67\x65". #language
	"\x00\x00\x00\x0e\x63\x6f\x6e\x74". #----cont
	"\x65\x6e\x74\x2d\x6c\x65\x6e\x67". #ent-leng
	"\x74\x68\x00\x00\x00\x10\x63\x6f". #th----co
	"\x6e\x74\x65\x6e\x74\x2d\x6c\x6f". #ntent-lo
	"\x63\x61\x74\x69\x6f\x6e\x00\x00". #cation--
	"\x00\x0b\x63\x6f\x6e\x74\x65\x6e". #--conten
	"\x74\x2d\x6d\x64\x35\x00\x00\x00". #t-md5---
	"\x0d\x63\x6f\x6e\x74\x65\x6e\x74". #-content
	"\x2d\x72\x61\x6e\x67\x65\x00\x00". #-range--
	"\x00\x0c\x63\x6f\x6e\x74\x65\x6e". #--conten
	"\x74\x2d\x74\x79\x70\x65\x00\x00". #t-type--
	"\x00\x04\x64\x61\x74\x65\x00\x00". #--date--
	"\x00\x04\x65\x74\x61\x67\x00\x00". #--etag--
	"\x00\x06\x65\x78\x70\x65\x63\x74". #--expect
	"\x00\x00\x00\x07\x65\x78\x70\x69". #----expi
	"\x72\x65\x73\x00\x00\x00\x04\x66". #res----f
	"\x72\x6f\x6d\x00\x00\x00\x04\x68". #rom----h
	"\x6f\x73\x74\x00\x00\x00\x08\x69". #ost----i
	"\x66\x2d\x6d\x61\x74\x63\x68\x00". #f-match-
	"\x00\x00\x11\x69\x66\x2d\x6d\x6f". #---if-mo
	"\x64\x69\x66\x69\x65\x64\x2d\x73". #dified-s
	"\x69\x6e\x63\x65\x00\x00\x00\x0d". #ince----
	"\x69\x66\x2d\x6e\x6f\x6e\x65\x2d". #if-none-
	"\x6d\x61\x74\x63\x68\x00\x00\x00". #match---
	"\x08\x69\x66\x2d\x72\x61\x6e\x67". #-if-rang
	"\x65\x00\x00\x00\x13\x69\x66\x2d". #e----if-
	"\x75\x6e\x6d\x6f\x64\x69\x66\x69". #unmodifi
	"\x65\x64\x2d\x73\x69\x6e\x63\x65". #ed-since
	"\x00\x00\x00\x0d\x6c\x61\x73\x74". #----last
	"\x2d\x6d\x6f\x64\x69\x66\x69\x65". #-modifie
	"\x64\x00\x00\x00\x08\x6c\x6f\x63". #d----loc
	"\x61\x74\x69\x6f\x6e\x00\x00\x00". #ation---
	"\x0c\x6d\x61\x78\x2d\x66\x6f\x72". #-max-for
	"\x77\x61\x72\x64\x73\x00\x00\x00". #wards---
	"\x06\x70\x72\x61\x67\x6d\x61\x00". #-pragma-
	"\x00\x00\x12\x70\x72\x6f\x78\x79". #---proxy
	"\x2d\x61\x75\x74\x68\x65\x6e\x74". #-authent
	"\x69\x63\x61\x74\x65\x00\x00\x00". #icate---
	"\x13\x70\x72\x6f\x78\x79\x2d\x61". #-proxy-a
	"\x75\x74\x68\x6f\x72\x69\x7a\x61". #uthoriza
	"\x74\x69\x6f\x6e\x00\x00\x00\x05". #tion----
	"\x72\x61\x6e\x67\x65\x00\x00\x00". #range---
	"\x07\x72\x65\x66\x65\x72\x65\x72". #-referer
	"\x00\x00\x00\x0b\x72\x65\x74\x72". #----retr
	"\x79\x2d\x61\x66\x74\x65\x72\x00". #y-after-
	"\x00\x00\x06\x73\x65\x72\x76\x65". #---serve
	"\x72\x00\x00\x00\x02\x74\x65\x00". #r----te-
	"\x00\x00\x07\x74\x72\x61\x69\x6c". #---trail
	"\x65\x72\x00\x00\x00\x11\x74\x72". #er----tr
	"\x61\x6e\x73\x66\x65\x72\x2d\x65". #ansfer-e
	"\x6e\x63\x6f\x64\x69\x6e\x67\x00". #ncoding-
	"\x00\x00\x07\x75\x70\x67\x72\x61". #---upgra
	"\x64\x65\x00\x00\x00\x0a\x75\x73". #de----us
	"\x65\x72\x2d\x61\x67\x65\x6e\x74". #er-agent
	"\x00\x00\x00\x04\x76\x61\x72\x79". #----vary
	"\x00\x00\x00\x03\x76\x69\x61\x00". #----via-
	"\x00\x00\x07\x77\x61\x72\x6e\x69". #---warni
	"\x6e\x67\x00\x00\x00\x10\x77\x77". #ng----ww
	"\x77\x2d\x61\x75\x74\x68\x65\x6e". #w-authen
	"\x74\x69\x63\x61\x74\x65\x00\x00". #ticate--
	"\x00\x06\x6d\x65\x74\x68\x6f\x64". #--method
	"\x00\x00\x00\x03\x67\x65\x74\x00". #----get-
	"\x00\x00\x06\x73\x74\x61\x74\x75". #---statu
	"\x73\x00\x00\x00\x06\x32\x30\x30". #s----200
	"\x20\x4f\x4b\x00\x00\x00\x07\x76". #-OK----v
	"\x65\x72\x73\x69\x6f\x6e\x00\x00". #ersion--
	"\x00\x08\x48\x54\x54\x50\x2f\x31". #--HTTP-1
	"\x2e\x31\x00\x00\x00\x03\x75\x72". #-1----ur
	"\x6c\x00\x00\x00\x06\x70\x75\x62". #l----pub
	"\x6c\x69\x63\x00\x00\x00\x0a\x73". #lic----s
	"\x65\x74\x2d\x63\x6f\x6f\x6b\x69". #et-cooki
	"\x65\x00\x00\x00\x0a\x6b\x65\x65". #e----kee
	"\x70\x2d\x61\x6c\x69\x76\x65\x00". #p-alive-
	"\x00\x00\x06\x6f\x72\x69\x67\x69". #---origi
	"\x6e\x31\x30\x30\x31\x30\x31\x32". #n1001012
	"\x30\x31\x32\x30\x32\x32\x30\x35". #01202205
	"\x32\x30\x36\x33\x30\x30\x33\x30". #20630030
	"\x32\x33\x30\x33\x33\x30\x34\x33". #23033043
	"\x30\x35\x33\x30\x36\x33\x30\x37". #05306307
	"\x34\x30\x32\x34\x30\x35\x34\x30". #40240540
	"\x36\x34\x30\x37\x34\x30\x38\x34". #64074084
	"\x30\x39\x34\x31\x30\x34\x31\x31". #09410411
	"\x34\x31\x32\x34\x31\x33\x34\x31". #41241341
	"\x34\x34\x31\x35\x34\x31\x36\x34". #44154164
	"\x31\x37\x35\x30\x32\x35\x30\x34". #17502504
	"\x35\x30\x35\x32\x30\x33\x20\x4e". #505203-N
	"\x6f\x6e\x2d\x41\x75\x74\x68\x6f". #on-Autho
	"\x72\x69\x74\x61\x74\x69\x76\x65". #ritative
	"\x20\x49\x6e\x66\x6f\x72\x6d\x61". #-Informa
	"\x74\x69\x6f\x6e\x32\x30\x34\x20". #tion204-
	"\x4e\x6f\x20\x43\x6f\x6e\x74\x65". #No-Conte
	"\x6e\x74\x33\x30\x31\x20\x4d\x6f". #nt301-Mo
	"\x76\x65\x64\x20\x50\x65\x72\x6d". #ved-Perm
	"\x61\x6e\x65\x6e\x74\x6c\x79\x34". #anently4
	"\x30\x30\x20\x42\x61\x64\x20\x52". #00-Bad-R
	"\x65\x71\x75\x65\x73\x74\x34\x30". #equest40
	"\x31\x20\x55\x6e\x61\x75\x74\x68". #1-Unauth
	"\x6f\x72\x69\x7a\x65\x64\x34\x30". #orized40
	"\x33\x20\x46\x6f\x72\x62\x69\x64". #3-Forbid
	"\x64\x65\x6e\x34\x30\x34\x20\x4e". #den404-N
	"\x6f\x74\x20\x46\x6f\x75\x6e\x64". #ot-Found
	"\x35\x30\x30\x20\x49\x6e\x74\x65". #500-Inte
	"\x72\x6e\x61\x6c\x20\x53\x65\x72". #rnal-Ser
	"\x76\x65\x72\x20\x45\x72\x72\x6f". #ver-Erro
	"\x72\x35\x30\x31\x20\x4e\x6f\x74". #r501-Not
	"\x20\x49\x6d\x70\x6c\x65\x6d\x65". #-Impleme
	"\x6e\x74\x65\x64\x35\x30\x33\x20". #nted503-
	"\x53\x65\x72\x76\x69\x63\x65\x20". #Service-
	"\x55\x6e\x61\x76\x61\x69\x6c\x61". #Unavaila
	"\x62\x6c\x65\x4a\x61\x6e\x20\x46". #bleJan-F
	"\x65\x62\x20\x4d\x61\x72\x20\x41". #eb-Mar-A
	"\x70\x72\x20\x4d\x61\x79\x20\x4a". #pr-May-J
	"\x75\x6e\x20\x4a\x75\x6c\x20\x41". #un-Jul-A
	"\x75\x67\x20\x53\x65\x70\x74\x20". #ug-Sept-
	"\x4f\x63\x74\x20\x4e\x6f\x76\x20". #Oct-Nov-
	"\x44\x65\x63\x20\x30\x30\x3a\x30". #Dec-00-0
	"\x30\x3a\x30\x30\x20\x4d\x6f\x6e". #0-00-Mon
	"\x2c\x20\x54\x75\x65\x2c\x20\x57". #--Tue--W
	"\x65\x64\x2c\x20\x54\x68\x75\x2c". #ed--Thu-
	"\x20\x46\x72\x69\x2c\x20\x53\x61". #-Fri--Sa
	"\x74\x2c\x20\x53\x75\x6e\x2c\x20". #t--Sun--
	"\x47\x4d\x54\x63\x68\x75\x6e\x6b". #GMTchunk
	"\x65\x64\x2c\x74\x65\x78\x74\x2f". #ed-text-
	"\x68\x74\x6d\x6c\x2c\x69\x6d\x61". #html-ima
	"\x67\x65\x2f\x70\x6e\x67\x2c\x69". #ge-png-i
	"\x6d\x61\x67\x65\x2f\x6a\x70\x67". #mage-jpg
	"\x2c\x69\x6d\x61\x67\x65\x2f\x67". #-image-g
	"\x69\x66\x2c\x61\x70\x70\x6c\x69". #if-appli
	"\x63\x61\x74\x69\x6f\x6e\x2f\x78". #cation-x
	"\x6d\x6c\x2c\x61\x70\x70\x6c\x69". #ml-appli
	"\x63\x61\x74\x69\x6f\x6e\x2f\x78". #cation-x
	"\x68\x74\x6d\x6c\x2b\x78\x6d\x6c". #html-xml
	"\x2c\x74\x65\x78\x74\x2f\x70\x6c". #-text-pl
	"\x61\x69\x6e\x2c\x74\x65\x78\x74". #ain-text
	"\x2f\x6a\x61\x76\x61\x73\x63\x72". #-javascr
	"\x69\x70\x74\x2c\x70\x75\x62\x6c". #ipt-publ
	"\x69\x63\x70\x72\x69\x76\x61\x74". #icprivat
	"\x65\x6d\x61\x78\x2d\x61\x67\x65". #emax-age
	"\x3d\x67\x7a\x69\x70\x2c\x64\x65". #-gzip-de
	"\x66\x6c\x61\x74\x65\x2c\x73\x64". #flate-sd
	"\x63\x68\x63\x68\x61\x72\x73\x65". #chcharse
	"\x74\x3d\x75\x74\x66\x2d\x38\x63". #t-utf-8c
	"\x68\x61\x72\x73\x65\x74\x3d\x69". #harset-i
	"\x73\x6f\x2d\x38\x38\x35\x39\x2d". #so-8859-
	"\x31\x2c\x75\x74\x66\x2d\x2c\x2a". #1-utf---
	"\x2c\x65\x6e\x71\x3d\x30\x2e";     #-enq-0-

=head1 METHODS

=over 4

=item new

Creates a new compressor instance.

=cut

sub new
{
	my $class = shift;
	my $self = bless {}, $class;

	# Initiate the Zlib streams
	my $status;
	($self->{inflater}, $status) = inflateInit (
		-Dictionary => DICT);
	die $status if $status;
	($self->{deflater}, $status) = deflateInit (
		-Level => 0,
		-Dictionary => DICT);
	die $status if $status;

	return $self;
}

=item compress STRING

Returns a compressed string.

=cut

sub compress
{
	my $self = shift;
	my $msg = shift;

	my ($o1, $o2, $status);
	($o1, $status) = $self->{deflater}->deflate ($msg);
	die $status if $status;
	($o2, $status) = $self->{deflater}->flush (Z_SYNC_FLUSH);
	die $status if $status;

	return $o1.$o2;
}

=item uncompress STRING

Returns an uncompressed string given a compressed one.

=cut

sub uncompress
{
	my $self = shift;
	my $msg = shift;

	my ($out, $status) = $self->{inflater}->inflate (\$msg);
	die $status if $status;

	return $out;
}

=back

=head1 SEE ALSO

=over

=item *

L<https://developers.google.com/speed/spdy/> -- SPDY project web site

=item *

L<http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3> -- Protocol specification

=back

=head1 CONTRIBUTING

Source code for I<Net::SPDY> is kept in a public GIT repository.
Visit L<https://github.com/lkundrak/net-spdy>.

Bugs reports and feature enhancement requests are tracked at
L<https://rt.cpan.org/Public/Dist/Display.html?Name=Net::SPDY>.

=head1 COPYRIGHT

Copyright 2012, Lubomir Rintel

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 AUTHOR

Lubomir Rintel C<lkundrak@v3.sk>

=cut

1;