[Zucchini] Add zucchini API declaration; implement MainGen and MainApply.

This includes:
- Add Generate, GenerateRaw and Apply in zucchini.h
- Implement MainGen and MainApply using these functions

Please ignore changes regarding BufferRegion, which is introduced
in 606739.

Bug: 729154
Change-Id: I6024c7b3431199f70fa4bebe2e198a3e94e30f0c
Reviewed-on: https://chromium-review.googlesource.com/606897
Commit-Queue: Etienne Pierre-Doray <[email protected]>
Reviewed-by: Samuel Huang <[email protected]>
Cr-Commit-Position: refs/heads/master@{#493213}
diff --git a/chrome/installer/zucchini/zucchini_commands.cc b/chrome/installer/zucchini/zucchini_commands.cc
index be3bb34..1447f41b 100644
--- a/chrome/installer/zucchini/zucchini_commands.cc
+++ b/chrome/installer/zucchini/zucchini_commands.cc
@@ -16,6 +16,8 @@
 #include "chrome/installer/zucchini/buffer_view.h"
 #include "chrome/installer/zucchini/crc32.h"
 #include "chrome/installer/zucchini/io_utils.h"
+#include "chrome/installer/zucchini/patch_reader.h"
+#include "chrome/installer/zucchini/patch_writer.h"
 
 namespace {
 
@@ -68,6 +70,10 @@
   DISALLOW_COPY_AND_ASSIGN(MappedFileWriter);
 };
 
+/******** Command-line Switches ********/
+
+const char kSwitchRaw[] = "raw";
+
 }  // namespace
 
 zucchini::status::Code MainGen(MainParams params) {
@@ -79,13 +85,26 @@
   if (!new_image.is_ok())
     return zucchini::status::kStatusFileReadError;
 
-  // TODO(etiennep): Implement.
+  zucchini::EnsemblePatchWriter patch_writer(old_image.region(),
+                                             new_image.region());
 
-  // Dummy output as placeholder.
-  MappedFileWriter patch(params.file_paths[2], 256);
+  auto generate = params.command_line.HasSwitch(kSwitchRaw)
+                      ? zucchini::GenerateRaw
+                      : zucchini::GenerateEnsemble;
+  zucchini::status::Code status =
+      generate(old_image.region(), new_image.region(), &patch_writer);
+  if (status != zucchini::status::kStatusSuccess) {
+    params.out << "Fatal error encountered when generating patch." << std::endl;
+    return status;
+  }
+
+  MappedFileWriter patch(params.file_paths[2], patch_writer.SerializedSize());
   if (!patch.is_ok())
     return zucchini::status::kStatusFileWriteError;
 
+  if (!patch_writer.SerializeInto(patch.region()))
+    return zucchini::status::kStatusPatchWriteError;
+
   return zucchini::status::kStatusSuccess;
 }
 
@@ -98,13 +117,23 @@
   if (!patch.is_ok())
     return zucchini::status::kStatusFileReadError;
 
-  // TODO(etiennep): Implement.
+  auto patch_reader = zucchini::EnsemblePatchReader::Create(patch.region());
+  if (!patch_reader.has_value()) {
+    params.err << "Error reading patch header." << std::endl;
+    return zucchini::status::kStatusPatchReadError;
+  }
+  zucchini::PatchHeader header = patch_reader->header();
 
-  // Dummy output as placeholder.
-  MappedFileWriter new_image(params.file_paths[2], 256);
+  MappedFileWriter new_image(params.file_paths[2], header.new_size);
   if (!new_image.is_ok())
     return zucchini::status::kStatusFileWriteError;
 
+  zucchini::status::Code status =
+      zucchini::Apply(old_image.region(), *patch_reader, new_image.region());
+  if (status != zucchini::status::kStatusSuccess) {
+    params.err << "Fatal error encountered while applying patch." << std::endl;
+    return status;
+  }
   return zucchini::status::kStatusSuccess;
 }