vv9k / mobi-rs

A crate to work with MOBI format ebooks
MIT License
38 stars 10 forks source link

Writing Mobi files? #20

Open philippeitis opened 3 years ago

philippeitis commented 3 years ago

It would be nice to have the option to do something like the following (+ possible implementation details):

struct MobiWriter {
     header: MobiMetadata,
     records: Option<Vec<Record>>
     // equal to Mobi buf, can be overwritten by a records vec.
     buf: Vec<u8>
}

fn main() {
    // let book = Mobi::from_parts(header, records).unwrap();
    let book = Mobi::from_path("path/to/book.mobi").unwrap();
    let mut writer = MobiWriter::from(book);
    writer.set_author("Someone else");
    writer.set_title("A different title");
    // writer.set_records(records);
    writer.write_to_file("different/book.mobi").unwrap();
}

Since it seems like the Mobi header isn't particularly complex, I think implementing a MobiWriter struct that supports writing a new header without modifying the records wouldn't be too difficult (eg. write the header, fix some numbers, and then write the buf as is), and very useful (eg. fixing title and author).

If writing records was also supported, I'd imagine that writer would write records that into a records field which it uses as lazy storage until .write() is called, at which time records is correctly compressed with lz77 and is used instead of buf (which would be an exact copy of the original compressed record data).

This could also be useful for validating that mobi works correctly - if the implementation is correct, then reading and writing should produce identical copies, and otherwise, there might be a bug.

I'm also really happy to see that v0.5.0 was released, since it works really well for my project 👍

vv9k commented 3 years ago

Writing records is currently out of scope. From what I've tested recently even reading records doesn't work that well so I would probably focus on that first. On the other hand, adding a struct to modify header values seems like something rather quick to implement and would add a lot of value so I'll probably dig into this soon.

My current plan is to fix the decompression algorithm, add tests for it, cleanup record api and then look into writing.

Glad to see it working for you :) It's definitely starting to look more library-like.