Here is the skeleton of Archive::(Reader|Writer|Modifier|Entry)::Ar.
As you can see, most of the work is done in Entry::Ar.
module Archive
module Modifier
class Ar < Generic
# nothing to do here, taken care in Generic
end
end
module Reader
class Ar < Generic
def initialize(io)
# mostly nothing to do here
end
end
end
module Writer
class Ar < Generic
# nothing to do here, taken care in Generic
end
end
module Entry
class Ar < Generic
def initialize(io)
# creates two parts and extracts an
# entry from the io stream
super(io, :header, :data)
parse
end
def parse
@parts[:header] = EntryPart.new(Header) do
start = @io.pos
raw = @io.read(Header::LEN)
[start...@io.pos, raw]
end
@parts[:data] = EntryPart.new(String) do
start = @io.pos
raw = @io.read(@parts[:header].parsed.size)
[start...@io.pos, raw]
end
# ...
end
def update
@parts[:header].parsed.size = @parts[:data].raw.length
end
def to_arc_format
# ...
update
dump = header.parsed.to_arc_format + data.raw
return dump
end
class Header
# various constants such as header
# length defined here
def initialize(header_raw)
# takes raw header and parses it
# to initialize itself
end
def to_arc_format
# ...
end
end
end
end
end
Basically, you need an Archive::Entry::Zip < Archive::Entry::Generic
that, given a io stream passed to initialize, reads and parses an
archive entry, and leaves the io cursor at the beginning of the next
one. If it can also output itself in Zip format again, you will be
able to pass entries to Archive::Writer for writing.
Each Entry::XYZ has parts': a Zip entry will most likely have a
data’ and a header' part. Each part, in turn, has a
raw’ and a
parsed' attribute:
raw’ points to the raw stuff as read from the
stream, `parsed’ to a structure modifiable from code. You will
probably create an Archive::Entry::Zip::Header object that takes care
of receiving the Zip raw header, parse it, and initialize itself. The
data part will usually remain unparsed.
One nice thing of this design is that a mbox Entry can, for example,
implement a to_zip method. Then you could do something like this:
in = File.open(“/var/mail/joe”)
out = File.open(“/home/joe/mails.zip”)
mbox = Archive::Reader::Mbox.new(in)
zip = Archive::Writer::Zip.new(out)
mbox.scan do |entry|
zip.add(entry)
end
The `add’ method from Archive::Writer will see that we’re trying to
write on a zip and that we have a Mbox::Entry#to_zip method, so will
use that, and we’ll have converted from Mbox to Zip on the fly.
(This is not in Archive::Writer::Generic yet, because I have written
no to_xyz methods so far.)
If you have any questions, just ask.
Massimiliano
p.s.: Sorry to ask, isn’t there some way to have your mail client set
correct References: or at least not modify the subject?
···
On Mon, Jul 08, 2002 at 08:41:41PM +0900, Thomas Søndergaard wrote:
Do you think it would be possible to add a set of proxies that adapt
rubyzip interface to Archive’s? After all, the whole Archive thing is
just a matter of convenience (learn to deal with archives once, apply
the knowledge on all formats).
I don’t see why not, and I’d even like to do it. Are the interfaces
that rubyzip would have to implement apparent from the archive
module code? If not, do you have some documentation.