Jelajahi Sumber

:building_construction: add tex2pdf demo

Jeremy Zheng 2 tahun lalu
induk
melakukan
8f6be7dede
46 mengubah file dengan 14867 tambahan dan 120 penghapusan
  1. 1 0
      clients/README.md
  2. 296 0
      clients/cpp/lily.grpc.pb.cc
  3. 978 0
      clients/cpp/lily.grpc.pb.h
  4. 1532 0
      clients/cpp/lily.pb.cc
  5. 1584 0
      clients/cpp/lily.pb.h
  6. 1304 0
      clients/csharp/Lily.cs
  7. 513 0
      clients/csharp/LilyGrpc.cs
  8. 398 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubBuildRequest.java
  9. 9 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubBuildRequestOrBuilder.java
  10. 293 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubGrpc.java
  11. 367 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelGrpc.java
  12. 2385 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelModel.java
  13. 33 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelModelOrBuilder.java
  14. 632 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/File.java
  15. 32 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/FileOrBuilder.java
  16. 131 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/Lily.java
  17. 367 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexGrpc.java
  18. 684 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexToRequest.java
  19. 43 0
      clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexToRequestOrBuilder.java
  20. TEMPAT SAMPAH
      clients/php/GPBMetadata/Lily.php
  21. 0 42
      clients/php/Mint/Morus/V1/MarkdownStub.php
  22. 31 0
      clients/php/Palm/Lily/V1/EpubBuildRequest.php
  23. 35 0
      clients/php/Palm/Lily/V1/EpubClient.php
  24. 49 0
      clients/php/Palm/Lily/V1/ExcelClient.php
  25. 58 0
      clients/php/Palm/Lily/V1/ExcelModel.php
  26. 88 0
      clients/php/Palm/Lily/V1/ExcelModel/Sheet.php
  27. 115 0
      clients/php/Palm/Lily/V1/ExcelModel/Sheet/Cell.php
  28. 95 0
      clients/php/Palm/Lily/V1/File.php
  29. 49 0
      clients/php/Palm/Lily/V1/TexClient.php
  30. 58 0
      clients/php/Palm/Lily/V1/TexToRequest.php
  31. 88 0
      clients/php/Palm/Lily/V1/TexToRequest/File.php
  32. 2 1
      clients/php/composer.json
  33. 61 0
      clients/php/lily-demo.php
  34. 47 0
      clients/python/lily_pb2.py
  35. 272 0
      clients/python/lily_pb2_grpc.py
  36. 45 0
      clients/ruby/lily_pb.rb
  37. 62 0
      clients/ruby/lily_services_pb.rb
  38. 0 68
      clients/schema.sh
  39. 300 0
      dashboard/src/protocols/LilyServiceClientPb.ts
  40. 86 0
      dashboard/src/protocols/MorusServiceClientPb.ts
  41. 139 0
      dashboard/src/protocols/lily_pb.d.ts
  42. 1133 0
      dashboard/src/protocols/lily_pb.js
  43. 44 0
      dashboard/src/protocols/morus_pb.d.ts
  44. 358 0
      dashboard/src/protocols/morus_pb.js
  45. 46 0
      protocols/lily.proto
  46. 24 9
      scripts/schema.sh

+ 1 - 0
clients/README.md

@@ -24,6 +24,7 @@
 
   ```bash
   php -d extension=grpc.so -d max_execution_time=300 morus-demo.php
+  php -d extension=grpc.so -d max_execution_time=300 lily-demo.php
   ```
 
   ![client](documents/client.png)

+ 296 - 0
clients/cpp/lily.grpc.pb.cc

@@ -0,0 +1,296 @@
+// Generated by the gRPC C++ plugin.
+// If you make any local change, they will be lost.
+// source: lily.proto
+
+#include "lily.pb.h"
+#include "lily.grpc.pb.h"
+
+#include <functional>
+#include <grpcpp/support/async_stream.h>
+#include <grpcpp/support/async_unary_call.h>
+#include <grpcpp/impl/channel_interface.h>
+#include <grpcpp/impl/client_unary_call.h>
+#include <grpcpp/support/client_callback.h>
+#include <grpcpp/support/message_allocator.h>
+#include <grpcpp/support/method_handler.h>
+#include <grpcpp/impl/rpc_service_method.h>
+#include <grpcpp/support/server_callback.h>
+#include <grpcpp/impl/server_callback_handlers.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/impl/service_type.h>
+#include <grpcpp/support/sync_stream.h>
+namespace palm {
+namespace lily {
+namespace v1 {
+
+static const char* Excel_method_names[] = {
+  "/palm.lily.v1.Excel/Parse",
+  "/palm.lily.v1.Excel/Generate",
+};
+
+std::unique_ptr< Excel::Stub> Excel::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
+  (void)options;
+  std::unique_ptr< Excel::Stub> stub(new Excel::Stub(channel, options));
+  return stub;
+}
+
+Excel::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
+  : channel_(channel), rpcmethod_Parse_(Excel_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  , rpcmethod_Generate_(Excel_method_names[1], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  {}
+
+::grpc::Status Excel::Stub::Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::palm::lily::v1::ExcelModel* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Parse_, context, request, response);
+}
+
+void Excel::Stub::async::Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Parse_, context, request, response, std::move(f));
+}
+
+void Excel::Stub::async::Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, ::grpc::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Parse_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>* Excel::Stub::PrepareAsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Parse_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>* Excel::Stub::AsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncParseRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+::grpc::Status Excel::Stub::Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::palm::lily::v1::File* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Generate_, context, request, response);
+}
+
+void Excel::Stub::async::Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Generate_, context, request, response, std::move(f));
+}
+
+void Excel::Stub::async::Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Generate_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Excel::Stub::PrepareAsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Generate_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Excel::Stub::AsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncGenerateRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+Excel::Service::Service() {
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      Excel_method_names[0],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< Excel::Service, ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](Excel::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::palm::lily::v1::File* req,
+             ::palm::lily::v1::ExcelModel* resp) {
+               return service->Parse(ctx, req, resp);
+             }, this)));
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      Excel_method_names[1],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< Excel::Service, ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](Excel::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::palm::lily::v1::ExcelModel* req,
+             ::palm::lily::v1::File* resp) {
+               return service->Generate(ctx, req, resp);
+             }, this)));
+}
+
+Excel::Service::~Service() {
+}
+
+::grpc::Status Excel::Service::Parse(::grpc::ServerContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+::grpc::Status Excel::Service::Generate(::grpc::ServerContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+
+static const char* Tex_method_names[] = {
+  "/palm.lily.v1.Tex/ToPdf",
+  "/palm.lily.v1.Tex/ToWord",
+};
+
+std::unique_ptr< Tex::Stub> Tex::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
+  (void)options;
+  std::unique_ptr< Tex::Stub> stub(new Tex::Stub(channel, options));
+  return stub;
+}
+
+Tex::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
+  : channel_(channel), rpcmethod_ToPdf_(Tex_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  , rpcmethod_ToWord_(Tex_method_names[1], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  {}
+
+::grpc::Status Tex::Stub::ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_ToPdf_, context, request, response);
+}
+
+void Tex::Stub::async::ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ToPdf_, context, request, response, std::move(f));
+}
+
+void Tex::Stub::async::ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ToPdf_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Tex::Stub::PrepareAsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::palm::lily::v1::File, ::palm::lily::v1::TexToRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_ToPdf_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Tex::Stub::AsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncToPdfRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+::grpc::Status Tex::Stub::ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_ToWord_, context, request, response);
+}
+
+void Tex::Stub::async::ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ToWord_, context, request, response, std::move(f));
+}
+
+void Tex::Stub::async::ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ToWord_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Tex::Stub::PrepareAsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::palm::lily::v1::File, ::palm::lily::v1::TexToRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_ToWord_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Tex::Stub::AsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncToWordRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+Tex::Service::Service() {
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      Tex_method_names[0],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< Tex::Service, ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](Tex::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::palm::lily::v1::TexToRequest* req,
+             ::palm::lily::v1::File* resp) {
+               return service->ToPdf(ctx, req, resp);
+             }, this)));
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      Tex_method_names[1],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< Tex::Service, ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](Tex::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::palm::lily::v1::TexToRequest* req,
+             ::palm::lily::v1::File* resp) {
+               return service->ToWord(ctx, req, resp);
+             }, this)));
+}
+
+Tex::Service::~Service() {
+}
+
+::grpc::Status Tex::Service::ToPdf(::grpc::ServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+::grpc::Status Tex::Service::ToWord(::grpc::ServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+
+static const char* Epub_method_names[] = {
+  "/palm.lily.v1.Epub/Build",
+};
+
+std::unique_ptr< Epub::Stub> Epub::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
+  (void)options;
+  std::unique_ptr< Epub::Stub> stub(new Epub::Stub(channel, options));
+  return stub;
+}
+
+Epub::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
+  : channel_(channel), rpcmethod_Build_(Epub_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  {}
+
+::grpc::Status Epub::Stub::Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::palm::lily::v1::File* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Build_, context, request, response);
+}
+
+void Epub::Stub::async::Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Build_, context, request, response, std::move(f));
+}
+
+void Epub::Stub::async::Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Build_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Epub::Stub::PrepareAsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::palm::lily::v1::File, ::palm::lily::v1::EpubBuildRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Build_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* Epub::Stub::AsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncBuildRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+Epub::Service::Service() {
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      Epub_method_names[0],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< Epub::Service, ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](Epub::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::palm::lily::v1::EpubBuildRequest* req,
+             ::palm::lily::v1::File* resp) {
+               return service->Build(ctx, req, resp);
+             }, this)));
+}
+
+Epub::Service::~Service() {
+}
+
+::grpc::Status Epub::Service::Build(::grpc::ServerContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+
+}  // namespace palm
+}  // namespace lily
+}  // namespace v1
+

+ 978 - 0
clients/cpp/lily.grpc.pb.h

@@ -0,0 +1,978 @@
+// Generated by the gRPC C++ plugin.
+// If you make any local change, they will be lost.
+// source: lily.proto
+#ifndef GRPC_lily_2eproto__INCLUDED
+#define GRPC_lily_2eproto__INCLUDED
+
+#include "lily.pb.h"
+
+#include <functional>
+#include <grpcpp/generic/async_generic_service.h>
+#include <grpcpp/support/async_stream.h>
+#include <grpcpp/support/async_unary_call.h>
+#include <grpcpp/support/client_callback.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/support/message_allocator.h>
+#include <grpcpp/support/method_handler.h>
+#include <grpcpp/impl/proto_utils.h>
+#include <grpcpp/impl/rpc_method.h>
+#include <grpcpp/support/server_callback.h>
+#include <grpcpp/impl/server_callback_handlers.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/impl/service_type.h>
+#include <grpcpp/support/status.h>
+#include <grpcpp/support/stub_options.h>
+#include <grpcpp/support/sync_stream.h>
+
+namespace palm {
+namespace lily {
+namespace v1 {
+
+// ----------------------------------------------------------------------------
+//
+class Excel final {
+ public:
+  static constexpr char const* service_full_name() {
+    return "palm.lily.v1.Excel";
+  }
+  class StubInterface {
+   public:
+    virtual ~StubInterface() {}
+    virtual ::grpc::Status Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::palm::lily::v1::ExcelModel* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>> AsyncParse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>>(AsyncParseRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>> PrepareAsyncParse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>>(PrepareAsyncParseRaw(context, request, cq));
+    }
+    virtual ::grpc::Status Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::palm::lily::v1::File* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> AsyncGenerate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(AsyncGenerateRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> PrepareAsyncGenerate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(PrepareAsyncGenerateRaw(context, request, cq));
+    }
+    class async_interface {
+     public:
+      virtual ~async_interface() {}
+      virtual void Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, std::function<void(::grpc::Status)>) = 0;
+      virtual void Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+      virtual void Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) = 0;
+      virtual void Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+    };
+    typedef class async_interface experimental_async_interface;
+    virtual class async_interface* async() { return nullptr; }
+    class async_interface* experimental_async() { return async(); }
+   private:
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>* AsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::ExcelModel>* PrepareAsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* AsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* PrepareAsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) = 0;
+  };
+  class Stub final : public StubInterface {
+   public:
+    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+    ::grpc::Status Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::palm::lily::v1::ExcelModel* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>> AsyncParse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>>(AsyncParseRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>> PrepareAsyncParse(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>>(PrepareAsyncParseRaw(context, request, cq));
+    }
+    ::grpc::Status Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::palm::lily::v1::File* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> AsyncGenerate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(AsyncGenerateRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> PrepareAsyncGenerate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(PrepareAsyncGenerateRaw(context, request, cq));
+    }
+    class async final :
+      public StubInterface::async_interface {
+     public:
+      void Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, std::function<void(::grpc::Status)>) override;
+      void Parse(::grpc::ClientContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response, ::grpc::ClientUnaryReactor* reactor) override;
+      void Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) override;
+      void Generate(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) override;
+     private:
+      friend class Stub;
+      explicit async(Stub* stub): stub_(stub) { }
+      Stub* stub() { return stub_; }
+      Stub* stub_;
+    };
+    class async* async() override { return &async_stub_; }
+
+   private:
+    std::shared_ptr< ::grpc::ChannelInterface> channel_;
+    class async async_stub_{this};
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>* AsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::ExcelModel>* PrepareAsyncParseRaw(::grpc::ClientContext* context, const ::palm::lily::v1::File& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* AsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* PrepareAsyncGenerateRaw(::grpc::ClientContext* context, const ::palm::lily::v1::ExcelModel& request, ::grpc::CompletionQueue* cq) override;
+    const ::grpc::internal::RpcMethod rpcmethod_Parse_;
+    const ::grpc::internal::RpcMethod rpcmethod_Generate_;
+  };
+  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+
+  class Service : public ::grpc::Service {
+   public:
+    Service();
+    virtual ~Service();
+    virtual ::grpc::Status Parse(::grpc::ServerContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response);
+    virtual ::grpc::Status Generate(::grpc::ServerContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response);
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_Parse() {
+      ::grpc::Service::MarkMethodAsync(0);
+    }
+    ~WithAsyncMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestParse(::grpc::ServerContext* context, ::palm::lily::v1::File* request, ::grpc::ServerAsyncResponseWriter< ::palm::lily::v1::ExcelModel>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_Generate() {
+      ::grpc::Service::MarkMethodAsync(1);
+    }
+    ~WithAsyncMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestGenerate(::grpc::ServerContext* context, ::palm::lily::v1::ExcelModel* request, ::grpc::ServerAsyncResponseWriter< ::palm::lily::v1::File>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_Parse<WithAsyncMethod_Generate<Service > > AsyncService;
+  template <class BaseClass>
+  class WithCallbackMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithCallbackMethod_Parse() {
+      ::grpc::Service::MarkMethodCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::palm::lily::v1::File* request, ::palm::lily::v1::ExcelModel* response) { return this->Parse(context, request, response); }));}
+    void SetMessageAllocatorFor_Parse(
+        ::grpc::MessageAllocator< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel>* allocator) {
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0);
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~WithCallbackMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Parse(
+      ::grpc::CallbackServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithCallbackMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithCallbackMethod_Generate() {
+      ::grpc::Service::MarkMethodCallback(1,
+          new ::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::palm::lily::v1::ExcelModel* request, ::palm::lily::v1::File* response) { return this->Generate(context, request, response); }));}
+    void SetMessageAllocatorFor_Generate(
+        ::grpc::MessageAllocator< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File>* allocator) {
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1);
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~WithCallbackMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Generate(
+      ::grpc::CallbackServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/)  { return nullptr; }
+  };
+  typedef WithCallbackMethod_Parse<WithCallbackMethod_Generate<Service > > CallbackService;
+  typedef CallbackService ExperimentalCallbackService;
+  template <class BaseClass>
+  class WithGenericMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_Parse() {
+      ::grpc::Service::MarkMethodGeneric(0);
+    }
+    ~WithGenericMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithGenericMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_Generate() {
+      ::grpc::Service::MarkMethodGeneric(1);
+    }
+    ~WithGenericMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_Parse() {
+      ::grpc::Service::MarkMethodRaw(0);
+    }
+    ~WithRawMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestParse(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_Generate() {
+      ::grpc::Service::MarkMethodRaw(1);
+    }
+    ~WithRawMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestGenerate(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithRawCallbackMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawCallbackMethod_Parse() {
+      ::grpc::Service::MarkMethodRawCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Parse(context, request, response); }));
+    }
+    ~WithRawCallbackMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Parse(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithRawCallbackMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawCallbackMethod_Generate() {
+      ::grpc::Service::MarkMethodRawCallback(1,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Generate(context, request, response); }));
+    }
+    ~WithRawCallbackMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Generate(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_Parse : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_Parse() {
+      ::grpc::Service::MarkMethodStreamed(0,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::palm::lily::v1::File, ::palm::lily::v1::ExcelModel>* streamer) {
+                       return this->StreamedParse(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_Parse() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status Parse(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::File* /*request*/, ::palm::lily::v1::ExcelModel* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedParse(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::palm::lily::v1::File,::palm::lily::v1::ExcelModel>* server_unary_streamer) = 0;
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_Generate : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_Generate() {
+      ::grpc::Service::MarkMethodStreamed(1,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::palm::lily::v1::ExcelModel, ::palm::lily::v1::File>* streamer) {
+                       return this->StreamedGenerate(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_Generate() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status Generate(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::ExcelModel* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedGenerate(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::palm::lily::v1::ExcelModel,::palm::lily::v1::File>* server_unary_streamer) = 0;
+  };
+  typedef WithStreamedUnaryMethod_Parse<WithStreamedUnaryMethod_Generate<Service > > StreamedUnaryService;
+  typedef Service SplitStreamedService;
+  typedef WithStreamedUnaryMethod_Parse<WithStreamedUnaryMethod_Generate<Service > > StreamedService;
+};
+
+// ----------------------------------------------------------------------------
+//
+class Tex final {
+ public:
+  static constexpr char const* service_full_name() {
+    return "palm.lily.v1.Tex";
+  }
+  class StubInterface {
+   public:
+    virtual ~StubInterface() {}
+    virtual ::grpc::Status ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> AsyncToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(AsyncToPdfRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> PrepareAsyncToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(PrepareAsyncToPdfRaw(context, request, cq));
+    }
+    virtual ::grpc::Status ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> AsyncToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(AsyncToWordRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> PrepareAsyncToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(PrepareAsyncToWordRaw(context, request, cq));
+    }
+    class async_interface {
+     public:
+      virtual ~async_interface() {}
+      virtual void ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) = 0;
+      virtual void ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+      virtual void ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) = 0;
+      virtual void ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+    };
+    typedef class async_interface experimental_async_interface;
+    virtual class async_interface* async() { return nullptr; }
+    class async_interface* experimental_async() { return async(); }
+   private:
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* AsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* PrepareAsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* AsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* PrepareAsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) = 0;
+  };
+  class Stub final : public StubInterface {
+   public:
+    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+    ::grpc::Status ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> AsyncToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(AsyncToPdfRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> PrepareAsyncToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(PrepareAsyncToPdfRaw(context, request, cq));
+    }
+    ::grpc::Status ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::palm::lily::v1::File* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> AsyncToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(AsyncToWordRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> PrepareAsyncToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(PrepareAsyncToWordRaw(context, request, cq));
+    }
+    class async final :
+      public StubInterface::async_interface {
+     public:
+      void ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) override;
+      void ToPdf(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) override;
+      void ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) override;
+      void ToWord(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) override;
+     private:
+      friend class Stub;
+      explicit async(Stub* stub): stub_(stub) { }
+      Stub* stub() { return stub_; }
+      Stub* stub_;
+    };
+    class async* async() override { return &async_stub_; }
+
+   private:
+    std::shared_ptr< ::grpc::ChannelInterface> channel_;
+    class async async_stub_{this};
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* AsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* PrepareAsyncToPdfRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* AsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* PrepareAsyncToWordRaw(::grpc::ClientContext* context, const ::palm::lily::v1::TexToRequest& request, ::grpc::CompletionQueue* cq) override;
+    const ::grpc::internal::RpcMethod rpcmethod_ToPdf_;
+    const ::grpc::internal::RpcMethod rpcmethod_ToWord_;
+  };
+  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+
+  class Service : public ::grpc::Service {
+   public:
+    Service();
+    virtual ~Service();
+    virtual ::grpc::Status ToPdf(::grpc::ServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response);
+    virtual ::grpc::Status ToWord(::grpc::ServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response);
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_ToPdf() {
+      ::grpc::Service::MarkMethodAsync(0);
+    }
+    ~WithAsyncMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestToPdf(::grpc::ServerContext* context, ::palm::lily::v1::TexToRequest* request, ::grpc::ServerAsyncResponseWriter< ::palm::lily::v1::File>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_ToWord() {
+      ::grpc::Service::MarkMethodAsync(1);
+    }
+    ~WithAsyncMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestToWord(::grpc::ServerContext* context, ::palm::lily::v1::TexToRequest* request, ::grpc::ServerAsyncResponseWriter< ::palm::lily::v1::File>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_ToPdf<WithAsyncMethod_ToWord<Service > > AsyncService;
+  template <class BaseClass>
+  class WithCallbackMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithCallbackMethod_ToPdf() {
+      ::grpc::Service::MarkMethodCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response) { return this->ToPdf(context, request, response); }));}
+    void SetMessageAllocatorFor_ToPdf(
+        ::grpc::MessageAllocator< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>* allocator) {
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0);
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~WithCallbackMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* ToPdf(
+      ::grpc::CallbackServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithCallbackMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithCallbackMethod_ToWord() {
+      ::grpc::Service::MarkMethodCallback(1,
+          new ::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::palm::lily::v1::TexToRequest* request, ::palm::lily::v1::File* response) { return this->ToWord(context, request, response); }));}
+    void SetMessageAllocatorFor_ToWord(
+        ::grpc::MessageAllocator< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>* allocator) {
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1);
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~WithCallbackMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* ToWord(
+      ::grpc::CallbackServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/)  { return nullptr; }
+  };
+  typedef WithCallbackMethod_ToPdf<WithCallbackMethod_ToWord<Service > > CallbackService;
+  typedef CallbackService ExperimentalCallbackService;
+  template <class BaseClass>
+  class WithGenericMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_ToPdf() {
+      ::grpc::Service::MarkMethodGeneric(0);
+    }
+    ~WithGenericMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithGenericMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_ToWord() {
+      ::grpc::Service::MarkMethodGeneric(1);
+    }
+    ~WithGenericMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_ToPdf() {
+      ::grpc::Service::MarkMethodRaw(0);
+    }
+    ~WithRawMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestToPdf(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_ToWord() {
+      ::grpc::Service::MarkMethodRaw(1);
+    }
+    ~WithRawMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestToWord(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithRawCallbackMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawCallbackMethod_ToPdf() {
+      ::grpc::Service::MarkMethodRawCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ToPdf(context, request, response); }));
+    }
+    ~WithRawCallbackMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* ToPdf(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithRawCallbackMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawCallbackMethod_ToWord() {
+      ::grpc::Service::MarkMethodRawCallback(1,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ToWord(context, request, response); }));
+    }
+    ~WithRawCallbackMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* ToWord(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_ToPdf : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_ToPdf() {
+      ::grpc::Service::MarkMethodStreamed(0,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>* streamer) {
+                       return this->StreamedToPdf(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_ToPdf() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status ToPdf(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedToPdf(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::palm::lily::v1::TexToRequest,::palm::lily::v1::File>* server_unary_streamer) = 0;
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_ToWord : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_ToWord() {
+      ::grpc::Service::MarkMethodStreamed(1,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::palm::lily::v1::TexToRequest, ::palm::lily::v1::File>* streamer) {
+                       return this->StreamedToWord(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_ToWord() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status ToWord(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::TexToRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedToWord(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::palm::lily::v1::TexToRequest,::palm::lily::v1::File>* server_unary_streamer) = 0;
+  };
+  typedef WithStreamedUnaryMethod_ToPdf<WithStreamedUnaryMethod_ToWord<Service > > StreamedUnaryService;
+  typedef Service SplitStreamedService;
+  typedef WithStreamedUnaryMethod_ToPdf<WithStreamedUnaryMethod_ToWord<Service > > StreamedService;
+};
+
+// ----------------------------------------------------------------------------
+//
+class Epub final {
+ public:
+  static constexpr char const* service_full_name() {
+    return "palm.lily.v1.Epub";
+  }
+  class StubInterface {
+   public:
+    virtual ~StubInterface() {}
+    virtual ::grpc::Status Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::palm::lily::v1::File* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> AsyncBuild(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(AsyncBuildRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>> PrepareAsyncBuild(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>>(PrepareAsyncBuildRaw(context, request, cq));
+    }
+    class async_interface {
+     public:
+      virtual ~async_interface() {}
+      virtual void Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) = 0;
+      virtual void Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+    };
+    typedef class async_interface experimental_async_interface;
+    virtual class async_interface* async() { return nullptr; }
+    class async_interface* experimental_async() { return async(); }
+   private:
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* AsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::palm::lily::v1::File>* PrepareAsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) = 0;
+  };
+  class Stub final : public StubInterface {
+   public:
+    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+    ::grpc::Status Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::palm::lily::v1::File* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> AsyncBuild(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(AsyncBuildRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>> PrepareAsyncBuild(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>>(PrepareAsyncBuildRaw(context, request, cq));
+    }
+    class async final :
+      public StubInterface::async_interface {
+     public:
+      void Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, std::function<void(::grpc::Status)>) override;
+      void Build(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response, ::grpc::ClientUnaryReactor* reactor) override;
+     private:
+      friend class Stub;
+      explicit async(Stub* stub): stub_(stub) { }
+      Stub* stub() { return stub_; }
+      Stub* stub_;
+    };
+    class async* async() override { return &async_stub_; }
+
+   private:
+    std::shared_ptr< ::grpc::ChannelInterface> channel_;
+    class async async_stub_{this};
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* AsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::palm::lily::v1::File>* PrepareAsyncBuildRaw(::grpc::ClientContext* context, const ::palm::lily::v1::EpubBuildRequest& request, ::grpc::CompletionQueue* cq) override;
+    const ::grpc::internal::RpcMethod rpcmethod_Build_;
+  };
+  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+
+  class Service : public ::grpc::Service {
+   public:
+    Service();
+    virtual ~Service();
+    virtual ::grpc::Status Build(::grpc::ServerContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response);
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_Build() {
+      ::grpc::Service::MarkMethodAsync(0);
+    }
+    ~WithAsyncMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestBuild(::grpc::ServerContext* context, ::palm::lily::v1::EpubBuildRequest* request, ::grpc::ServerAsyncResponseWriter< ::palm::lily::v1::File>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_Build<Service > AsyncService;
+  template <class BaseClass>
+  class WithCallbackMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithCallbackMethod_Build() {
+      ::grpc::Service::MarkMethodCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::palm::lily::v1::EpubBuildRequest* request, ::palm::lily::v1::File* response) { return this->Build(context, request, response); }));}
+    void SetMessageAllocatorFor_Build(
+        ::grpc::MessageAllocator< ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File>* allocator) {
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0);
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~WithCallbackMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Build(
+      ::grpc::CallbackServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/)  { return nullptr; }
+  };
+  typedef WithCallbackMethod_Build<Service > CallbackService;
+  typedef CallbackService ExperimentalCallbackService;
+  template <class BaseClass>
+  class WithGenericMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_Build() {
+      ::grpc::Service::MarkMethodGeneric(0);
+    }
+    ~WithGenericMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_Build() {
+      ::grpc::Service::MarkMethodRaw(0);
+    }
+    ~WithRawMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestBuild(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class WithRawCallbackMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawCallbackMethod_Build() {
+      ::grpc::Service::MarkMethodRawCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+                   ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Build(context, request, response); }));
+    }
+    ~WithRawCallbackMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    virtual ::grpc::ServerUnaryReactor* Build(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)  { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_Build : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_Build() {
+      ::grpc::Service::MarkMethodStreamed(0,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::palm::lily::v1::EpubBuildRequest, ::palm::lily::v1::File>* streamer) {
+                       return this->StreamedBuild(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_Build() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status Build(::grpc::ServerContext* /*context*/, const ::palm::lily::v1::EpubBuildRequest* /*request*/, ::palm::lily::v1::File* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedBuild(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::palm::lily::v1::EpubBuildRequest,::palm::lily::v1::File>* server_unary_streamer) = 0;
+  };
+  typedef WithStreamedUnaryMethod_Build<Service > StreamedUnaryService;
+  typedef Service SplitStreamedService;
+  typedef WithStreamedUnaryMethod_Build<Service > StreamedService;
+};
+
+}  // namespace v1
+}  // namespace lily
+}  // namespace palm
+
+
+#endif  // GRPC_lily_2eproto__INCLUDED

+ 1532 - 0
clients/cpp/lily.pb.cc

@@ -0,0 +1,1532 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+#include "lily.pb.h"
+
+#include <algorithm>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
+// @@protoc_insertion_point(includes)
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+PROTOBUF_PRAGMA_INIT_SEG
+namespace _pb = ::PROTOBUF_NAMESPACE_ID;
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
+namespace palm {
+namespace lily {
+namespace v1 {
+template <typename>
+PROTOBUF_CONSTEXPR File::File(
+    ::_pbi::ConstantInitialized): _impl_{
+    /*decltype(_impl_._has_bits_)*/{}
+  , /*decltype(_impl_._cached_size_)*/{}
+  , /*decltype(_impl_.content_type_)*/ {
+    &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {}
+  }
+
+  , /*decltype(_impl_.payload_)*/ {
+    &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {}
+  }
+} {}
+struct FileDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR FileDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~FileDefaultTypeInternal() {}
+  union {
+    File _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDefaultTypeInternal _File_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR ExcelModel_Sheet_Cell::ExcelModel_Sheet_Cell(
+    ::_pbi::ConstantInitialized): _impl_{
+    /*decltype(_impl_.val_)*/ {
+    &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {}
+  }
+
+  , /*decltype(_impl_.row_)*/ 0u
+
+  , /*decltype(_impl_.col_)*/ 0u
+
+  , /*decltype(_impl_._cached_size_)*/{}} {}
+struct ExcelModel_Sheet_CellDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR ExcelModel_Sheet_CellDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~ExcelModel_Sheet_CellDefaultTypeInternal() {}
+  union {
+    ExcelModel_Sheet_Cell _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExcelModel_Sheet_CellDefaultTypeInternal _ExcelModel_Sheet_Cell_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR ExcelModel_Sheet::ExcelModel_Sheet(
+    ::_pbi::ConstantInitialized): _impl_{
+    /*decltype(_impl_.cells_)*/{}
+  , /*decltype(_impl_.name_)*/ {
+    &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {}
+  }
+
+  , /*decltype(_impl_._cached_size_)*/{}} {}
+struct ExcelModel_SheetDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR ExcelModel_SheetDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~ExcelModel_SheetDefaultTypeInternal() {}
+  union {
+    ExcelModel_Sheet _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExcelModel_SheetDefaultTypeInternal _ExcelModel_Sheet_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR ExcelModel::ExcelModel(
+    ::_pbi::ConstantInitialized): _impl_{
+    /*decltype(_impl_.sheets_)*/{}
+  , /*decltype(_impl_._cached_size_)*/{}} {}
+struct ExcelModelDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR ExcelModelDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~ExcelModelDefaultTypeInternal() {}
+  union {
+    ExcelModel _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExcelModelDefaultTypeInternal _ExcelModel_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR TexToRequest_FilesEntry_DoNotUse::TexToRequest_FilesEntry_DoNotUse(
+    ::_pbi::ConstantInitialized) {}
+struct TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal() {}
+  union {
+    TexToRequest_FilesEntry_DoNotUse _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal _TexToRequest_FilesEntry_DoNotUse_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR TexToRequest::TexToRequest(
+    ::_pbi::ConstantInitialized): _impl_{
+    /*decltype(_impl_.files_)*/{}
+  , /*decltype(_impl_._cached_size_)*/{}} {}
+struct TexToRequestDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR TexToRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~TexToRequestDefaultTypeInternal() {}
+  union {
+    TexToRequest _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TexToRequestDefaultTypeInternal _TexToRequest_default_instance_;
+template <typename>
+PROTOBUF_CONSTEXPR EpubBuildRequest::EpubBuildRequest(
+    ::_pbi::ConstantInitialized) {}
+struct EpubBuildRequestDefaultTypeInternal {
+  PROTOBUF_CONSTEXPR EpubBuildRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
+  ~EpubBuildRequestDefaultTypeInternal() {}
+  union {
+    EpubBuildRequest _instance;
+  };
+};
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EpubBuildRequestDefaultTypeInternal _EpubBuildRequest_default_instance_;
+}  // namespace v1
+}  // namespace lily
+}  // namespace palm
+static ::_pb::Metadata file_level_metadata_lily_2eproto[7];
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_lily_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_lily_2eproto = nullptr;
+const ::uint32_t TableStruct_lily_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::File, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::File, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::File, _impl_.content_type_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::File, _impl_.payload_),
+    0,
+    ~0u,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet_Cell, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet_Cell, _impl_.row_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet_Cell, _impl_.col_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet_Cell, _impl_.val_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel_Sheet, _impl_.cells_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::ExcelModel, _impl_.sheets_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse, _has_bits_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse, key_),
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse, value_),
+    0,
+    1,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::TexToRequest, _impl_.files_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::palm::lily::v1::EpubBuildRequest, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+};
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, 10, -1, sizeof(::palm::lily::v1::File)},
+        { 12, -1, -1, sizeof(::palm::lily::v1::ExcelModel_Sheet_Cell)},
+        { 23, -1, -1, sizeof(::palm::lily::v1::ExcelModel_Sheet)},
+        { 33, -1, -1, sizeof(::palm::lily::v1::ExcelModel)},
+        { 42, 52, -1, sizeof(::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse)},
+        { 54, -1, -1, sizeof(::palm::lily::v1::TexToRequest)},
+        { 63, -1, -1, sizeof(::palm::lily::v1::EpubBuildRequest)},
+};
+
+static const ::_pb::Message* const file_default_instances[] = {
+    &::palm::lily::v1::_File_default_instance_._instance,
+    &::palm::lily::v1::_ExcelModel_Sheet_Cell_default_instance_._instance,
+    &::palm::lily::v1::_ExcelModel_Sheet_default_instance_._instance,
+    &::palm::lily::v1::_ExcelModel_default_instance_._instance,
+    &::palm::lily::v1::_TexToRequest_FilesEntry_DoNotUse_default_instance_._instance,
+    &::palm::lily::v1::_TexToRequest_default_instance_._instance,
+    &::palm::lily::v1::_EpubBuildRequest_default_instance_._instance,
+};
+const char descriptor_table_protodef_lily_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n\nlily.proto\022\014palm.lily.v1\"C\n\004File\022\031\n\014co"
+    "ntent_type\030\001 \001(\tH\000\210\001\001\022\017\n\007payload\030\002 \001(\014B\017"
+    "\n\r_content_type\"\266\001\n\nExcelModel\022.\n\006sheets"
+    "\030\001 \003(\0132\036.palm.lily.v1.ExcelModel.Sheet\032x"
+    "\n\005Sheet\022\014\n\004name\030\001 \001(\t\0222\n\005cells\030\002 \003(\0132#.p"
+    "alm.lily.v1.ExcelModel.Sheet.Cell\032-\n\004Cel"
+    "l\022\013\n\003row\030\001 \001(\r\022\013\n\003col\030\002 \001(\r\022\013\n\003val\030\003 \001(\t"
+    "\"r\n\014TexToRequest\0224\n\005files\030\001 \003(\0132%.palm.l"
+    "ily.v1.TexToRequest.FilesEntry\032,\n\nFilesE"
+    "ntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\014:\0028\001\"\022\n\020"
+    "EpubBuildRequest2|\n\005Excel\0227\n\005Parse\022\022.pal"
+    "m.lily.v1.File\032\030.palm.lily.v1.ExcelModel"
+    "\"\000\022:\n\010Generate\022\030.palm.lily.v1.ExcelModel"
+    "\032\022.palm.lily.v1.File\"\0002|\n\003Tex\0229\n\005ToPdf\022\032"
+    ".palm.lily.v1.TexToRequest\032\022.palm.lily.v"
+    "1.File\"\000\022:\n\006ToWord\022\032.palm.lily.v1.TexToR"
+    "equest\032\022.palm.lily.v1.File\"\0002E\n\004Epub\022=\n\005"
+    "Build\022\036.palm.lily.v1.EpubBuildRequest\032\022."
+    "palm.lily.v1.File\"\000B.\n*com.github.saturn"
+    "_xiv.palm.plugins.lily.v1P\001b\006proto3"
+};
+static ::absl::once_flag descriptor_table_lily_2eproto_once;
+const ::_pbi::DescriptorTable descriptor_table_lily_2eproto = {
+    false,
+    false,
+    795,
+    descriptor_table_protodef_lily_2eproto,
+    "lily.proto",
+    &descriptor_table_lily_2eproto_once,
+    nullptr,
+    0,
+    7,
+    schemas,
+    file_default_instances,
+    TableStruct_lily_2eproto::offsets,
+    file_level_metadata_lily_2eproto,
+    file_level_enum_descriptors_lily_2eproto,
+    file_level_service_descriptors_lily_2eproto,
+};
+
+// This function exists to be marked as weak.
+// It can significantly speed up compilation by breaking up LLVM's SCC
+// in the .pb.cc translation units. Large translation units see a
+// reduction of more than 35% of walltime for optimized builds. Without
+// the weak attribute all the messages in the file, including all the
+// vtables and everything they use become part of the same SCC through
+// a cycle like:
+// GetMetadata -> descriptor table -> default instances ->
+//   vtables -> GetMetadata
+// By adding a weak function here we break the connection from the
+// individual vtables back into the descriptor table.
+PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_lily_2eproto_getter() {
+  return &descriptor_table_lily_2eproto;
+}
+// Force running AddDescriptors() at dynamic initialization time.
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_lily_2eproto(&descriptor_table_lily_2eproto);
+namespace palm {
+namespace lily {
+namespace v1 {
+// ===================================================================
+
+class File::_Internal {
+ public:
+  using HasBits = decltype(std::declval<File>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(File, _impl_._has_bits_);
+  static void set_has_content_type(HasBits* has_bits) {
+    (*has_bits)[0] |= 1u;
+  }
+};
+
+File::File(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor(arena);
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.File)
+}
+File::File(const File& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  File* const _this = this; (void)_this;
+  new (&_impl_) Impl_{
+      decltype(_impl_._has_bits_){from._impl_._has_bits_}
+    , /*decltype(_impl_._cached_size_)*/{}
+    , decltype(_impl_.content_type_) {}
+
+    , decltype(_impl_.payload_) {}
+  };
+
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  _impl_.content_type_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.content_type_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
+    _this->_impl_.content_type_.Set(from._internal_content_type(), _this->GetArenaForAllocation());
+  }
+  _impl_.payload_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.payload_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if (!from._internal_payload().empty()) {
+    _this->_impl_.payload_.Set(from._internal_payload(), _this->GetArenaForAllocation());
+  }
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.File)
+}
+
+inline void File::SharedCtor(::_pb::Arena* arena) {
+  (void)arena;
+  new (&_impl_) Impl_{
+      decltype(_impl_._has_bits_){}
+    , /*decltype(_impl_._cached_size_)*/{}
+    , decltype(_impl_.content_type_) {}
+
+    , decltype(_impl_.payload_) {}
+
+  };
+  _impl_.content_type_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.content_type_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  _impl_.payload_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.payload_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+}
+
+File::~File() {
+  // @@protoc_insertion_point(destructor:palm.lily.v1.File)
+  if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) {
+  (void)arena;
+    return;
+  }
+  SharedDtor();
+}
+
+inline void File::SharedDtor() {
+  ABSL_DCHECK(GetArenaForAllocation() == nullptr);
+  _impl_.content_type_.Destroy();
+  _impl_.payload_.Destroy();
+}
+
+void File::SetCachedSize(int size) const {
+  _impl_._cached_size_.Set(size);
+}
+
+void File::Clear() {
+// @@protoc_insertion_point(message_clear_start:palm.lily.v1.File)
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _impl_._has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    _impl_.content_type_.ClearNonDefaultToEmpty();
+  }
+  _impl_.payload_.ClearToEmpty();
+  _impl_._has_bits_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* File::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  _Internal::HasBits has_bits{};
+  while (!ctx->Done(&ptr)) {
+    ::uint32_t tag;
+    ptr = ::_pbi::ReadTag(ptr, &tag);
+    switch (tag >> 3) {
+      // optional string content_type = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
+          auto str = _internal_mutable_content_type();
+          ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(ptr);
+          CHK_(::_pbi::VerifyUTF8(str, "palm.lily.v1.File.content_type"));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      // bytes payload = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
+          auto str = _internal_mutable_payload();
+          ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(ptr);
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      default:
+        goto handle_unusual;
+    }  // switch
+  handle_unusual:
+    if ((tag == 0) || ((tag & 7) == 4)) {
+      CHK_(ptr);
+      ctx->SetLastTag(tag);
+      goto message_done;
+    }
+    ptr = UnknownFieldParse(
+        tag,
+        _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+        ptr, ctx);
+    CHK_(ptr != nullptr);
+  }  // while
+message_done:
+  _impl_._has_bits_.Or(has_bits);
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto message_done;
+#undef CHK_
+}
+
+::uint8_t* File::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:palm.lily.v1.File)
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _impl_._has_bits_[0];
+  // optional string content_type = 1;
+  if (cached_has_bits & 0x00000001u) {
+    const std::string& _s = this->_internal_content_type();
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+        _s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "palm.lily.v1.File.content_type");
+    target = stream->WriteStringMaybeAliased(1, _s, target);
+  }
+
+  // bytes payload = 2;
+  if (!this->_internal_payload().empty()) {
+    const std::string& _s = this->_internal_payload();
+    target = stream->WriteBytesMaybeAliased(2, _s, target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:palm.lily.v1.File)
+  return target;
+}
+
+::size_t File::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:palm.lily.v1.File)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // optional string content_type = 1;
+  cached_has_bits = _impl_._has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+                                    this->_internal_content_type());
+  }
+
+  // bytes payload = 2;
+  if (!this->_internal_payload().empty()) {
+    total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
+                                    this->_internal_payload());
+  }
+
+  return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData File::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck,
+    File::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*File::GetClassData() const { return &_class_data_; }
+
+
+void File::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
+  auto* const _this = static_cast<File*>(&to_msg);
+  auto& from = static_cast<const File&>(from_msg);
+  // @@protoc_insertion_point(class_specific_merge_from_start:palm.lily.v1.File)
+  ABSL_DCHECK_NE(&from, _this);
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
+    _this->_internal_set_content_type(from._internal_content_type());
+  }
+  if (!from._internal_payload().empty()) {
+    _this->_internal_set_payload(from._internal_payload());
+  }
+  _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void File::CopyFrom(const File& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:palm.lily.v1.File)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool File::IsInitialized() const {
+  return true;
+}
+
+void File::InternalSwap(File* other) {
+  using std::swap;
+  auto* lhs_arena = GetArenaForAllocation();
+  auto* rhs_arena = other->GetArenaForAllocation();
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]);
+  ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.content_type_, lhs_arena,
+                                       &other->_impl_.content_type_, rhs_arena);
+  ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.payload_, lhs_arena,
+                                       &other->_impl_.payload_, rhs_arena);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata File::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[0]);
+}
+// ===================================================================
+
+class ExcelModel_Sheet_Cell::_Internal {
+ public:
+};
+
+ExcelModel_Sheet_Cell::ExcelModel_Sheet_Cell(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor(arena);
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.ExcelModel.Sheet.Cell)
+}
+ExcelModel_Sheet_Cell::ExcelModel_Sheet_Cell(const ExcelModel_Sheet_Cell& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  ExcelModel_Sheet_Cell* const _this = this; (void)_this;
+  new (&_impl_) Impl_{
+      decltype(_impl_.val_) {}
+
+    , decltype(_impl_.row_) {}
+
+    , decltype(_impl_.col_) {}
+
+    , /*decltype(_impl_._cached_size_)*/{}};
+
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  _impl_.val_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.val_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if (!from._internal_val().empty()) {
+    _this->_impl_.val_.Set(from._internal_val(), _this->GetArenaForAllocation());
+  }
+  ::memcpy(&_impl_.row_, &from._impl_.row_,
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.col_) -
+    reinterpret_cast<char*>(&_impl_.row_)) + sizeof(_impl_.col_));
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.ExcelModel.Sheet.Cell)
+}
+
+inline void ExcelModel_Sheet_Cell::SharedCtor(::_pb::Arena* arena) {
+  (void)arena;
+  new (&_impl_) Impl_{
+      decltype(_impl_.val_) {}
+
+    , decltype(_impl_.row_) { 0u }
+
+    , decltype(_impl_.col_) { 0u }
+
+    , /*decltype(_impl_._cached_size_)*/{}
+  };
+  _impl_.val_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.val_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+}
+
+ExcelModel_Sheet_Cell::~ExcelModel_Sheet_Cell() {
+  // @@protoc_insertion_point(destructor:palm.lily.v1.ExcelModel.Sheet.Cell)
+  if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) {
+  (void)arena;
+    return;
+  }
+  SharedDtor();
+}
+
+inline void ExcelModel_Sheet_Cell::SharedDtor() {
+  ABSL_DCHECK(GetArenaForAllocation() == nullptr);
+  _impl_.val_.Destroy();
+}
+
+void ExcelModel_Sheet_Cell::SetCachedSize(int size) const {
+  _impl_._cached_size_.Set(size);
+}
+
+void ExcelModel_Sheet_Cell::Clear() {
+// @@protoc_insertion_point(message_clear_start:palm.lily.v1.ExcelModel.Sheet.Cell)
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _impl_.val_.ClearToEmpty();
+  ::memset(&_impl_.row_, 0, static_cast<::size_t>(
+      reinterpret_cast<char*>(&_impl_.col_) -
+      reinterpret_cast<char*>(&_impl_.row_)) + sizeof(_impl_.col_));
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* ExcelModel_Sheet_Cell::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::uint32_t tag;
+    ptr = ::_pbi::ReadTag(ptr, &tag);
+    switch (tag >> 3) {
+      // uint32 row = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
+          _impl_.row_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+          CHK_(ptr);
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      // uint32 col = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
+          _impl_.col_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+          CHK_(ptr);
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      // string val = 3;
+      case 3:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
+          auto str = _internal_mutable_val();
+          ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(ptr);
+          CHK_(::_pbi::VerifyUTF8(str, "palm.lily.v1.ExcelModel.Sheet.Cell.val"));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      default:
+        goto handle_unusual;
+    }  // switch
+  handle_unusual:
+    if ((tag == 0) || ((tag & 7) == 4)) {
+      CHK_(ptr);
+      ctx->SetLastTag(tag);
+      goto message_done;
+    }
+    ptr = UnknownFieldParse(
+        tag,
+        _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+        ptr, ctx);
+    CHK_(ptr != nullptr);
+  }  // while
+message_done:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto message_done;
+#undef CHK_
+}
+
+::uint8_t* ExcelModel_Sheet_Cell::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:palm.lily.v1.ExcelModel.Sheet.Cell)
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // uint32 row = 1;
+  if (this->_internal_row() != 0) {
+    target = stream->EnsureSpace(target);
+    target = ::_pbi::WireFormatLite::WriteUInt32ToArray(
+        1, this->_internal_row(), target);
+  }
+
+  // uint32 col = 2;
+  if (this->_internal_col() != 0) {
+    target = stream->EnsureSpace(target);
+    target = ::_pbi::WireFormatLite::WriteUInt32ToArray(
+        2, this->_internal_col(), target);
+  }
+
+  // string val = 3;
+  if (!this->_internal_val().empty()) {
+    const std::string& _s = this->_internal_val();
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+        _s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "palm.lily.v1.ExcelModel.Sheet.Cell.val");
+    target = stream->WriteStringMaybeAliased(3, _s, target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:palm.lily.v1.ExcelModel.Sheet.Cell)
+  return target;
+}
+
+::size_t ExcelModel_Sheet_Cell::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:palm.lily.v1.ExcelModel.Sheet.Cell)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string val = 3;
+  if (!this->_internal_val().empty()) {
+    total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+                                    this->_internal_val());
+  }
+
+  // uint32 row = 1;
+  if (this->_internal_row() != 0) {
+    total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne(
+        this->_internal_row());
+  }
+
+  // uint32 col = 2;
+  if (this->_internal_col() != 0) {
+    total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne(
+        this->_internal_col());
+  }
+
+  return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ExcelModel_Sheet_Cell::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck,
+    ExcelModel_Sheet_Cell::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ExcelModel_Sheet_Cell::GetClassData() const { return &_class_data_; }
+
+
+void ExcelModel_Sheet_Cell::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
+  auto* const _this = static_cast<ExcelModel_Sheet_Cell*>(&to_msg);
+  auto& from = static_cast<const ExcelModel_Sheet_Cell&>(from_msg);
+  // @@protoc_insertion_point(class_specific_merge_from_start:palm.lily.v1.ExcelModel.Sheet.Cell)
+  ABSL_DCHECK_NE(&from, _this);
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (!from._internal_val().empty()) {
+    _this->_internal_set_val(from._internal_val());
+  }
+  if (from._internal_row() != 0) {
+    _this->_internal_set_row(from._internal_row());
+  }
+  if (from._internal_col() != 0) {
+    _this->_internal_set_col(from._internal_col());
+  }
+  _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void ExcelModel_Sheet_Cell::CopyFrom(const ExcelModel_Sheet_Cell& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:palm.lily.v1.ExcelModel.Sheet.Cell)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ExcelModel_Sheet_Cell::IsInitialized() const {
+  return true;
+}
+
+void ExcelModel_Sheet_Cell::InternalSwap(ExcelModel_Sheet_Cell* other) {
+  using std::swap;
+  auto* lhs_arena = GetArenaForAllocation();
+  auto* rhs_arena = other->GetArenaForAllocation();
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.val_, lhs_arena,
+                                       &other->_impl_.val_, rhs_arena);
+  ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+      PROTOBUF_FIELD_OFFSET(ExcelModel_Sheet_Cell, _impl_.col_)
+      + sizeof(ExcelModel_Sheet_Cell::_impl_.col_)
+      - PROTOBUF_FIELD_OFFSET(ExcelModel_Sheet_Cell, _impl_.row_)>(
+          reinterpret_cast<char*>(&_impl_.row_),
+          reinterpret_cast<char*>(&other->_impl_.row_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata ExcelModel_Sheet_Cell::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[1]);
+}
+// ===================================================================
+
+class ExcelModel_Sheet::_Internal {
+ public:
+};
+
+ExcelModel_Sheet::ExcelModel_Sheet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor(arena);
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.ExcelModel.Sheet)
+}
+ExcelModel_Sheet::ExcelModel_Sheet(const ExcelModel_Sheet& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  ExcelModel_Sheet* const _this = this; (void)_this;
+  new (&_impl_) Impl_{
+      decltype(_impl_.cells_){from._impl_.cells_}
+    , decltype(_impl_.name_) {}
+
+    , /*decltype(_impl_._cached_size_)*/{}};
+
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  _impl_.name_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.name_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if (!from._internal_name().empty()) {
+    _this->_impl_.name_.Set(from._internal_name(), _this->GetArenaForAllocation());
+  }
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.ExcelModel.Sheet)
+}
+
+inline void ExcelModel_Sheet::SharedCtor(::_pb::Arena* arena) {
+  (void)arena;
+  new (&_impl_) Impl_{
+      decltype(_impl_.cells_){arena}
+    , decltype(_impl_.name_) {}
+
+    , /*decltype(_impl_._cached_size_)*/{}
+  };
+  _impl_.name_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        _impl_.name_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+}
+
+ExcelModel_Sheet::~ExcelModel_Sheet() {
+  // @@protoc_insertion_point(destructor:palm.lily.v1.ExcelModel.Sheet)
+  if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) {
+  (void)arena;
+    return;
+  }
+  SharedDtor();
+}
+
+inline void ExcelModel_Sheet::SharedDtor() {
+  ABSL_DCHECK(GetArenaForAllocation() == nullptr);
+  _internal_mutable_cells()->~RepeatedPtrField();
+  _impl_.name_.Destroy();
+}
+
+void ExcelModel_Sheet::SetCachedSize(int size) const {
+  _impl_._cached_size_.Set(size);
+}
+
+void ExcelModel_Sheet::Clear() {
+// @@protoc_insertion_point(message_clear_start:palm.lily.v1.ExcelModel.Sheet)
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _internal_mutable_cells()->Clear();
+  _impl_.name_.ClearToEmpty();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* ExcelModel_Sheet::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::uint32_t tag;
+    ptr = ::_pbi::ReadTag(ptr, &tag);
+    switch (tag >> 3) {
+      // string name = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
+          auto str = _internal_mutable_name();
+          ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(ptr);
+          CHK_(::_pbi::VerifyUTF8(str, "palm.lily.v1.ExcelModel.Sheet.name"));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      // repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
+          ptr -= 1;
+          do {
+            ptr += 1;
+            ptr = ctx->ParseMessage(_internal_add_cells(), ptr);
+            CHK_(ptr);
+            if (!ctx->DataAvailable(ptr)) break;
+          } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      default:
+        goto handle_unusual;
+    }  // switch
+  handle_unusual:
+    if ((tag == 0) || ((tag & 7) == 4)) {
+      CHK_(ptr);
+      ctx->SetLastTag(tag);
+      goto message_done;
+    }
+    ptr = UnknownFieldParse(
+        tag,
+        _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+        ptr, ctx);
+    CHK_(ptr != nullptr);
+  }  // while
+message_done:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto message_done;
+#undef CHK_
+}
+
+::uint8_t* ExcelModel_Sheet::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:palm.lily.v1.ExcelModel.Sheet)
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (!this->_internal_name().empty()) {
+    const std::string& _s = this->_internal_name();
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+        _s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "palm.lily.v1.ExcelModel.Sheet.name");
+    target = stream->WriteStringMaybeAliased(1, _s, target);
+  }
+
+  // repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;
+  for (unsigned i = 0,
+      n = static_cast<unsigned>(this->_internal_cells_size()); i < n; i++) {
+    const auto& repfield = this->_internal_cells(i);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+        InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:palm.lily.v1.ExcelModel.Sheet)
+  return target;
+}
+
+::size_t ExcelModel_Sheet::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:palm.lily.v1.ExcelModel.Sheet)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;
+  total_size += 1UL * this->_internal_cells_size();
+  for (const auto& msg : this->_internal_cells()) {
+    total_size +=
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
+  }
+
+  // string name = 1;
+  if (!this->_internal_name().empty()) {
+    total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+                                    this->_internal_name());
+  }
+
+  return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ExcelModel_Sheet::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck,
+    ExcelModel_Sheet::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ExcelModel_Sheet::GetClassData() const { return &_class_data_; }
+
+
+void ExcelModel_Sheet::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
+  auto* const _this = static_cast<ExcelModel_Sheet*>(&to_msg);
+  auto& from = static_cast<const ExcelModel_Sheet&>(from_msg);
+  // @@protoc_insertion_point(class_specific_merge_from_start:palm.lily.v1.ExcelModel.Sheet)
+  ABSL_DCHECK_NE(&from, _this);
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  _this->_internal_mutable_cells()->MergeFrom(from._internal_cells());
+  if (!from._internal_name().empty()) {
+    _this->_internal_set_name(from._internal_name());
+  }
+  _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void ExcelModel_Sheet::CopyFrom(const ExcelModel_Sheet& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:palm.lily.v1.ExcelModel.Sheet)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ExcelModel_Sheet::IsInitialized() const {
+  return true;
+}
+
+void ExcelModel_Sheet::InternalSwap(ExcelModel_Sheet* other) {
+  using std::swap;
+  auto* lhs_arena = GetArenaForAllocation();
+  auto* rhs_arena = other->GetArenaForAllocation();
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  _internal_mutable_cells()->InternalSwap(other->_internal_mutable_cells());
+  ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, lhs_arena,
+                                       &other->_impl_.name_, rhs_arena);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata ExcelModel_Sheet::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[2]);
+}
+// ===================================================================
+
+class ExcelModel::_Internal {
+ public:
+};
+
+ExcelModel::ExcelModel(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor(arena);
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.ExcelModel)
+}
+ExcelModel::ExcelModel(const ExcelModel& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  ExcelModel* const _this = this; (void)_this;
+  new (&_impl_) Impl_{
+      decltype(_impl_.sheets_){from._impl_.sheets_}
+    , /*decltype(_impl_._cached_size_)*/{}};
+
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.ExcelModel)
+}
+
+inline void ExcelModel::SharedCtor(::_pb::Arena* arena) {
+  (void)arena;
+  new (&_impl_) Impl_{
+      decltype(_impl_.sheets_){arena}
+    , /*decltype(_impl_._cached_size_)*/{}
+  };
+}
+
+ExcelModel::~ExcelModel() {
+  // @@protoc_insertion_point(destructor:palm.lily.v1.ExcelModel)
+  if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) {
+  (void)arena;
+    return;
+  }
+  SharedDtor();
+}
+
+inline void ExcelModel::SharedDtor() {
+  ABSL_DCHECK(GetArenaForAllocation() == nullptr);
+  _internal_mutable_sheets()->~RepeatedPtrField();
+}
+
+void ExcelModel::SetCachedSize(int size) const {
+  _impl_._cached_size_.Set(size);
+}
+
+void ExcelModel::Clear() {
+// @@protoc_insertion_point(message_clear_start:palm.lily.v1.ExcelModel)
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _internal_mutable_sheets()->Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* ExcelModel::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::uint32_t tag;
+    ptr = ::_pbi::ReadTag(ptr, &tag);
+    switch (tag >> 3) {
+      // repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
+          ptr -= 1;
+          do {
+            ptr += 1;
+            ptr = ctx->ParseMessage(_internal_add_sheets(), ptr);
+            CHK_(ptr);
+            if (!ctx->DataAvailable(ptr)) break;
+          } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      default:
+        goto handle_unusual;
+    }  // switch
+  handle_unusual:
+    if ((tag == 0) || ((tag & 7) == 4)) {
+      CHK_(ptr);
+      ctx->SetLastTag(tag);
+      goto message_done;
+    }
+    ptr = UnknownFieldParse(
+        tag,
+        _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+        ptr, ctx);
+    CHK_(ptr != nullptr);
+  }  // while
+message_done:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto message_done;
+#undef CHK_
+}
+
+::uint8_t* ExcelModel::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:palm.lily.v1.ExcelModel)
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;
+  for (unsigned i = 0,
+      n = static_cast<unsigned>(this->_internal_sheets_size()); i < n; i++) {
+    const auto& repfield = this->_internal_sheets(i);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+        InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:palm.lily.v1.ExcelModel)
+  return target;
+}
+
+::size_t ExcelModel::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:palm.lily.v1.ExcelModel)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;
+  total_size += 1UL * this->_internal_sheets_size();
+  for (const auto& msg : this->_internal_sheets()) {
+    total_size +=
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
+  }
+
+  return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ExcelModel::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck,
+    ExcelModel::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ExcelModel::GetClassData() const { return &_class_data_; }
+
+
+void ExcelModel::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
+  auto* const _this = static_cast<ExcelModel*>(&to_msg);
+  auto& from = static_cast<const ExcelModel&>(from_msg);
+  // @@protoc_insertion_point(class_specific_merge_from_start:palm.lily.v1.ExcelModel)
+  ABSL_DCHECK_NE(&from, _this);
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  _this->_internal_mutable_sheets()->MergeFrom(from._internal_sheets());
+  _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void ExcelModel::CopyFrom(const ExcelModel& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:palm.lily.v1.ExcelModel)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ExcelModel::IsInitialized() const {
+  return true;
+}
+
+void ExcelModel::InternalSwap(ExcelModel* other) {
+  using std::swap;
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  _internal_mutable_sheets()->InternalSwap(other->_internal_mutable_sheets());
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata ExcelModel::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[3]);
+}
+// ===================================================================
+
+TexToRequest_FilesEntry_DoNotUse::TexToRequest_FilesEntry_DoNotUse() {}
+TexToRequest_FilesEntry_DoNotUse::TexToRequest_FilesEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+    : SuperType(arena) {}
+void TexToRequest_FilesEntry_DoNotUse::MergeFrom(const TexToRequest_FilesEntry_DoNotUse& other) {
+  MergeFromInternal(other);
+}
+::PROTOBUF_NAMESPACE_ID::Metadata TexToRequest_FilesEntry_DoNotUse::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[4]);
+}
+// ===================================================================
+
+class TexToRequest::_Internal {
+ public:
+};
+
+TexToRequest::TexToRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor(arena);
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.TexToRequest)
+}
+TexToRequest::TexToRequest(const TexToRequest& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  TexToRequest* const _this = this; (void)_this;
+  new (&_impl_) Impl_{
+      /*decltype(_impl_.files_)*/{}
+    , /*decltype(_impl_._cached_size_)*/{}};
+
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  _this->_impl_.files_.MergeFrom(from._impl_.files_);
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.TexToRequest)
+}
+
+inline void TexToRequest::SharedCtor(::_pb::Arena* arena) {
+  (void)arena;
+  new (&_impl_) Impl_{
+      /*decltype(_impl_.files_)*/{::_pbi::ArenaInitialized(), arena}
+    , /*decltype(_impl_._cached_size_)*/{}
+  };
+}
+
+TexToRequest::~TexToRequest() {
+  // @@protoc_insertion_point(destructor:palm.lily.v1.TexToRequest)
+  if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) {
+  (void)arena;
+    return;
+  }
+  SharedDtor();
+}
+
+inline void TexToRequest::SharedDtor() {
+  ABSL_DCHECK(GetArenaForAllocation() == nullptr);
+  _impl_.files_.~MapField();
+}
+
+void TexToRequest::SetCachedSize(int size) const {
+  _impl_._cached_size_.Set(size);
+}
+
+void TexToRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:palm.lily.v1.TexToRequest)
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _impl_.files_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* TexToRequest::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::uint32_t tag;
+    ptr = ::_pbi::ReadTag(ptr, &tag);
+    switch (tag >> 3) {
+      // map<string, bytes> files = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
+          ptr -= 1;
+          do {
+            ptr += 1;
+            ptr = ctx->ParseMessage(&_impl_.files_, ptr);
+            CHK_(ptr);
+            if (!ctx->DataAvailable(ptr)) break;
+          } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
+        } else {
+          goto handle_unusual;
+        }
+        continue;
+      default:
+        goto handle_unusual;
+    }  // switch
+  handle_unusual:
+    if ((tag == 0) || ((tag & 7) == 4)) {
+      CHK_(ptr);
+      ctx->SetLastTag(tag);
+      goto message_done;
+    }
+    ptr = UnknownFieldParse(
+        tag,
+        _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+        ptr, ctx);
+    CHK_(ptr != nullptr);
+  }  // while
+message_done:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto message_done;
+#undef CHK_
+}
+
+::uint8_t* TexToRequest::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:palm.lily.v1.TexToRequest)
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // map<string, bytes> files = 1;
+  if (!this->_internal_files().empty()) {
+    using MapType = ::_pb::Map<std::string, std::string>;
+    using WireHelper = TexToRequest_FilesEntry_DoNotUse::Funcs;
+    const auto& map_field = this->_internal_files();
+    auto check_utf8 = [](const MapType::value_type& entry) {
+      (void)entry;
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+          entry.first.data(), static_cast<int>(entry.first.length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "palm.lily.v1.TexToRequest.files");
+    };
+
+    if (stream->IsSerializationDeterministic() && map_field.size() > 1) {
+      for (const auto& entry : ::_pbi::MapSorterPtr<MapType>(map_field)) {
+        target = WireHelper::InternalSerialize(1, entry.first, entry.second, target, stream);
+        check_utf8(entry);
+      }
+    } else {
+      for (const auto& entry : map_field) {
+        target = WireHelper::InternalSerialize(1, entry.first, entry.second, target, stream);
+        check_utf8(entry);
+      }
+    }
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:palm.lily.v1.TexToRequest)
+  return target;
+}
+
+::size_t TexToRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:palm.lily.v1.TexToRequest)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // map<string, bytes> files = 1;
+  total_size += 1 *
+      ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_files_size());
+  for (::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >::const_iterator
+      it = this->_internal_files().begin();
+      it != this->_internal_files().end(); ++it) {
+    total_size += TexToRequest_FilesEntry_DoNotUse::Funcs::ByteSizeLong(it->first, it->second);
+  }
+
+  return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData TexToRequest::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck,
+    TexToRequest::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*TexToRequest::GetClassData() const { return &_class_data_; }
+
+
+void TexToRequest::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
+  auto* const _this = static_cast<TexToRequest*>(&to_msg);
+  auto& from = static_cast<const TexToRequest&>(from_msg);
+  // @@protoc_insertion_point(class_specific_merge_from_start:palm.lily.v1.TexToRequest)
+  ABSL_DCHECK_NE(&from, _this);
+  ::uint32_t cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  _this->_impl_.files_.MergeFrom(from._impl_.files_);
+  _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void TexToRequest::CopyFrom(const TexToRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:palm.lily.v1.TexToRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TexToRequest::IsInitialized() const {
+  return true;
+}
+
+void TexToRequest::InternalSwap(TexToRequest* other) {
+  using std::swap;
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  _impl_.files_.InternalSwap(&other->_impl_.files_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata TexToRequest::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[5]);
+}
+// ===================================================================
+
+class EpubBuildRequest::_Internal {
+ public:
+};
+
+EpubBuildRequest::EpubBuildRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase(arena) {
+  // @@protoc_insertion_point(arena_constructor:palm.lily.v1.EpubBuildRequest)
+}
+EpubBuildRequest::EpubBuildRequest(const EpubBuildRequest& from)
+  : ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase() {
+  EpubBuildRequest* const _this = this; (void)_this;
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:palm.lily.v1.EpubBuildRequest)
+}
+
+
+
+
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EpubBuildRequest::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl,
+    ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl,
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EpubBuildRequest::GetClassData() const { return &_class_data_; }
+
+
+
+
+
+
+
+::PROTOBUF_NAMESPACE_ID::Metadata EpubBuildRequest::GetMetadata() const {
+  return ::_pbi::AssignDescriptors(
+      &descriptor_table_lily_2eproto_getter, &descriptor_table_lily_2eproto_once,
+      file_level_metadata_lily_2eproto[6]);
+}
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace v1
+}  // namespace lily
+}  // namespace palm
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::File*
+Arena::CreateMaybeMessage< ::palm::lily::v1::File >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::File >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::ExcelModel_Sheet_Cell*
+Arena::CreateMaybeMessage< ::palm::lily::v1::ExcelModel_Sheet_Cell >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::ExcelModel_Sheet_Cell >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::ExcelModel_Sheet*
+Arena::CreateMaybeMessage< ::palm::lily::v1::ExcelModel_Sheet >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::ExcelModel_Sheet >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::ExcelModel*
+Arena::CreateMaybeMessage< ::palm::lily::v1::ExcelModel >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::ExcelModel >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse*
+Arena::CreateMaybeMessage< ::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::TexToRequest*
+Arena::CreateMaybeMessage< ::palm::lily::v1::TexToRequest >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::TexToRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::palm::lily::v1::EpubBuildRequest*
+Arena::CreateMaybeMessage< ::palm::lily::v1::EpubBuildRequest >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::palm::lily::v1::EpubBuildRequest >(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+// @@protoc_insertion_point(global_scope)
+#include "google/protobuf/port_undef.inc"

+ 1584 - 0
clients/cpp/lily.pb.h

@@ -0,0 +1,1584 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_lily_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_lily_2eproto_2epb_2eh
+
+#include <limits>
+#include <string>
+#include <type_traits>
+
+#include "google/protobuf/port_def.inc"
+#if PROTOBUF_VERSION < 4023000
+#error "This file was generated by a newer version of protoc which is"
+#error "incompatible with your Protocol Buffer headers. Please update"
+#error "your headers."
+#endif  // PROTOBUF_VERSION
+
+#if 4023004 < PROTOBUF_MIN_PROTOC_VERSION
+#error "This file was generated by an older version of protoc which is"
+#error "incompatible with your Protocol Buffer headers. Please"
+#error "regenerate this file with a newer version of protoc."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_bases.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/map.h"  // IWYU pragma: export
+#include "google/protobuf/map_entry.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/unknown_field_set.h"
+// @@protoc_insertion_point(includes)
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+#define PROTOBUF_INTERNAL_EXPORT_lily_2eproto
+
+PROTOBUF_NAMESPACE_OPEN
+namespace internal {
+class AnyMetadata;
+}  // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_lily_2eproto {
+  static const ::uint32_t offsets[];
+};
+extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable
+    descriptor_table_lily_2eproto;
+namespace palm {
+namespace lily {
+namespace v1 {
+class EpubBuildRequest;
+struct EpubBuildRequestDefaultTypeInternal;
+extern EpubBuildRequestDefaultTypeInternal _EpubBuildRequest_default_instance_;
+class ExcelModel;
+struct ExcelModelDefaultTypeInternal;
+extern ExcelModelDefaultTypeInternal _ExcelModel_default_instance_;
+class ExcelModel_Sheet;
+struct ExcelModel_SheetDefaultTypeInternal;
+extern ExcelModel_SheetDefaultTypeInternal _ExcelModel_Sheet_default_instance_;
+class ExcelModel_Sheet_Cell;
+struct ExcelModel_Sheet_CellDefaultTypeInternal;
+extern ExcelModel_Sheet_CellDefaultTypeInternal _ExcelModel_Sheet_Cell_default_instance_;
+class File;
+struct FileDefaultTypeInternal;
+extern FileDefaultTypeInternal _File_default_instance_;
+class TexToRequest;
+struct TexToRequestDefaultTypeInternal;
+extern TexToRequestDefaultTypeInternal _TexToRequest_default_instance_;
+class TexToRequest_FilesEntry_DoNotUse;
+struct TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal;
+extern TexToRequest_FilesEntry_DoNotUseDefaultTypeInternal _TexToRequest_FilesEntry_DoNotUse_default_instance_;
+}  // namespace v1
+}  // namespace lily
+}  // namespace palm
+PROTOBUF_NAMESPACE_OPEN
+template <>
+::palm::lily::v1::EpubBuildRequest* Arena::CreateMaybeMessage<::palm::lily::v1::EpubBuildRequest>(Arena*);
+template <>
+::palm::lily::v1::ExcelModel* Arena::CreateMaybeMessage<::palm::lily::v1::ExcelModel>(Arena*);
+template <>
+::palm::lily::v1::ExcelModel_Sheet* Arena::CreateMaybeMessage<::palm::lily::v1::ExcelModel_Sheet>(Arena*);
+template <>
+::palm::lily::v1::ExcelModel_Sheet_Cell* Arena::CreateMaybeMessage<::palm::lily::v1::ExcelModel_Sheet_Cell>(Arena*);
+template <>
+::palm::lily::v1::File* Arena::CreateMaybeMessage<::palm::lily::v1::File>(Arena*);
+template <>
+::palm::lily::v1::TexToRequest* Arena::CreateMaybeMessage<::palm::lily::v1::TexToRequest>(Arena*);
+template <>
+::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse* Arena::CreateMaybeMessage<::palm::lily::v1::TexToRequest_FilesEntry_DoNotUse>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+
+namespace palm {
+namespace lily {
+namespace v1 {
+
+// ===================================================================
+
+
+// -------------------------------------------------------------------
+
+class File final :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:palm.lily.v1.File) */ {
+ public:
+  inline File() : File(nullptr) {}
+  ~File() override;
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  File(const File& from);
+  File(File&& from) noexcept
+    : File() {
+    *this = ::std::move(from);
+  }
+
+  inline File& operator=(const File& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline File& operator=(File&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const File& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const File* internal_default_instance() {
+    return reinterpret_cast<const File*>(
+               &_File_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  friend void swap(File& a, File& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(File* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(File* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<File>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+  void CopyFrom(const File& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  void MergeFrom( const File& from) {
+    File::MergeImpl(*this, from);
+  }
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
+  public:
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  ::size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
+
+  private:
+  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(File* other);
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.File";
+  }
+  protected:
+  explicit File(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kContentTypeFieldNumber = 1,
+    kPayloadFieldNumber = 2,
+  };
+  // optional string content_type = 1;
+  bool has_content_type() const;
+  void clear_content_type() ;
+  const std::string& content_type() const;
+
+
+
+
+  template <typename Arg_ = const std::string&, typename... Args_>
+  void set_content_type(Arg_&& arg, Args_... args);
+  std::string* mutable_content_type();
+  PROTOBUF_NODISCARD std::string* release_content_type();
+  void set_allocated_content_type(std::string* ptr);
+
+  private:
+  const std::string& _internal_content_type() const;
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_content_type(
+      const std::string& value);
+  std::string* _internal_mutable_content_type();
+
+  public:
+  // bytes payload = 2;
+  void clear_payload() ;
+  const std::string& payload() const;
+
+
+
+
+  template <typename Arg_ = const std::string&, typename... Args_>
+  void set_payload(Arg_&& arg, Args_... args);
+  std::string* mutable_payload();
+  PROTOBUF_NODISCARD std::string* release_payload();
+  void set_allocated_payload(std::string* ptr);
+
+  private:
+  const std::string& _internal_payload() const;
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_payload(
+      const std::string& value);
+  std::string* _internal_mutable_payload();
+
+  public:
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.File)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+    ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_type_;
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr payload_;
+  };
+  union { Impl_ _impl_; };
+  friend struct ::TableStruct_lily_2eproto;
+};// -------------------------------------------------------------------
+
+class ExcelModel_Sheet_Cell final :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:palm.lily.v1.ExcelModel.Sheet.Cell) */ {
+ public:
+  inline ExcelModel_Sheet_Cell() : ExcelModel_Sheet_Cell(nullptr) {}
+  ~ExcelModel_Sheet_Cell() override;
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR ExcelModel_Sheet_Cell(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  ExcelModel_Sheet_Cell(const ExcelModel_Sheet_Cell& from);
+  ExcelModel_Sheet_Cell(ExcelModel_Sheet_Cell&& from) noexcept
+    : ExcelModel_Sheet_Cell() {
+    *this = ::std::move(from);
+  }
+
+  inline ExcelModel_Sheet_Cell& operator=(const ExcelModel_Sheet_Cell& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline ExcelModel_Sheet_Cell& operator=(ExcelModel_Sheet_Cell&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const ExcelModel_Sheet_Cell& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const ExcelModel_Sheet_Cell* internal_default_instance() {
+    return reinterpret_cast<const ExcelModel_Sheet_Cell*>(
+               &_ExcelModel_Sheet_Cell_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  friend void swap(ExcelModel_Sheet_Cell& a, ExcelModel_Sheet_Cell& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(ExcelModel_Sheet_Cell* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(ExcelModel_Sheet_Cell* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  ExcelModel_Sheet_Cell* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<ExcelModel_Sheet_Cell>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+  void CopyFrom(const ExcelModel_Sheet_Cell& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  void MergeFrom( const ExcelModel_Sheet_Cell& from) {
+    ExcelModel_Sheet_Cell::MergeImpl(*this, from);
+  }
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
+  public:
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  ::size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
+
+  private:
+  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ExcelModel_Sheet_Cell* other);
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.ExcelModel.Sheet.Cell";
+  }
+  protected:
+  explicit ExcelModel_Sheet_Cell(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kValFieldNumber = 3,
+    kRowFieldNumber = 1,
+    kColFieldNumber = 2,
+  };
+  // string val = 3;
+  void clear_val() ;
+  const std::string& val() const;
+
+
+
+
+  template <typename Arg_ = const std::string&, typename... Args_>
+  void set_val(Arg_&& arg, Args_... args);
+  std::string* mutable_val();
+  PROTOBUF_NODISCARD std::string* release_val();
+  void set_allocated_val(std::string* ptr);
+
+  private:
+  const std::string& _internal_val() const;
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_val(
+      const std::string& value);
+  std::string* _internal_mutable_val();
+
+  public:
+  // uint32 row = 1;
+  void clear_row() ;
+  ::uint32_t row() const;
+  void set_row(::uint32_t value);
+
+  private:
+  ::uint32_t _internal_row() const;
+  void _internal_set_row(::uint32_t value);
+
+  public:
+  // uint32 col = 2;
+  void clear_col() ;
+  ::uint32_t col() const;
+  void set_col(::uint32_t value);
+
+  private:
+  ::uint32_t _internal_col() const;
+  void _internal_set_col(::uint32_t value);
+
+  public:
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel.Sheet.Cell)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr val_;
+    ::uint32_t row_;
+    ::uint32_t col_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  };
+  union { Impl_ _impl_; };
+  friend struct ::TableStruct_lily_2eproto;
+};// -------------------------------------------------------------------
+
+class ExcelModel_Sheet final :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:palm.lily.v1.ExcelModel.Sheet) */ {
+ public:
+  inline ExcelModel_Sheet() : ExcelModel_Sheet(nullptr) {}
+  ~ExcelModel_Sheet() override;
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR ExcelModel_Sheet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  ExcelModel_Sheet(const ExcelModel_Sheet& from);
+  ExcelModel_Sheet(ExcelModel_Sheet&& from) noexcept
+    : ExcelModel_Sheet() {
+    *this = ::std::move(from);
+  }
+
+  inline ExcelModel_Sheet& operator=(const ExcelModel_Sheet& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline ExcelModel_Sheet& operator=(ExcelModel_Sheet&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const ExcelModel_Sheet& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const ExcelModel_Sheet* internal_default_instance() {
+    return reinterpret_cast<const ExcelModel_Sheet*>(
+               &_ExcelModel_Sheet_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  friend void swap(ExcelModel_Sheet& a, ExcelModel_Sheet& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(ExcelModel_Sheet* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(ExcelModel_Sheet* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  ExcelModel_Sheet* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<ExcelModel_Sheet>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+  void CopyFrom(const ExcelModel_Sheet& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  void MergeFrom( const ExcelModel_Sheet& from) {
+    ExcelModel_Sheet::MergeImpl(*this, from);
+  }
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
+  public:
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  ::size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
+
+  private:
+  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ExcelModel_Sheet* other);
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.ExcelModel.Sheet";
+  }
+  protected:
+  explicit ExcelModel_Sheet(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ExcelModel_Sheet_Cell Cell;
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kCellsFieldNumber = 2,
+    kNameFieldNumber = 1,
+  };
+  // repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;
+  int cells_size() const;
+  private:
+  int _internal_cells_size() const;
+
+  public:
+  void clear_cells() ;
+  ::palm::lily::v1::ExcelModel_Sheet_Cell* mutable_cells(int index);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet_Cell >*
+      mutable_cells();
+  private:
+  const ::palm::lily::v1::ExcelModel_Sheet_Cell& _internal_cells(int index) const;
+  ::palm::lily::v1::ExcelModel_Sheet_Cell* _internal_add_cells();
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet_Cell>& _internal_cells() const;
+  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet_Cell>* _internal_mutable_cells();
+  public:
+  const ::palm::lily::v1::ExcelModel_Sheet_Cell& cells(int index) const;
+  ::palm::lily::v1::ExcelModel_Sheet_Cell* add_cells();
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet_Cell >&
+      cells() const;
+  // string name = 1;
+  void clear_name() ;
+  const std::string& name() const;
+
+
+
+
+  template <typename Arg_ = const std::string&, typename... Args_>
+  void set_name(Arg_&& arg, Args_... args);
+  std::string* mutable_name();
+  PROTOBUF_NODISCARD std::string* release_name();
+  void set_allocated_name(std::string* ptr);
+
+  private:
+  const std::string& _internal_name() const;
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(
+      const std::string& value);
+  std::string* _internal_mutable_name();
+
+  public:
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel.Sheet)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet_Cell > cells_;
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  };
+  union { Impl_ _impl_; };
+  friend struct ::TableStruct_lily_2eproto;
+};// -------------------------------------------------------------------
+
+class ExcelModel final :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:palm.lily.v1.ExcelModel) */ {
+ public:
+  inline ExcelModel() : ExcelModel(nullptr) {}
+  ~ExcelModel() override;
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR ExcelModel(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  ExcelModel(const ExcelModel& from);
+  ExcelModel(ExcelModel&& from) noexcept
+    : ExcelModel() {
+    *this = ::std::move(from);
+  }
+
+  inline ExcelModel& operator=(const ExcelModel& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline ExcelModel& operator=(ExcelModel&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const ExcelModel& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const ExcelModel* internal_default_instance() {
+    return reinterpret_cast<const ExcelModel*>(
+               &_ExcelModel_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  friend void swap(ExcelModel& a, ExcelModel& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(ExcelModel* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(ExcelModel* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  ExcelModel* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<ExcelModel>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+  void CopyFrom(const ExcelModel& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  void MergeFrom( const ExcelModel& from) {
+    ExcelModel::MergeImpl(*this, from);
+  }
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
+  public:
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  ::size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
+
+  private:
+  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ExcelModel* other);
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.ExcelModel";
+  }
+  protected:
+  explicit ExcelModel(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ExcelModel_Sheet Sheet;
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kSheetsFieldNumber = 1,
+  };
+  // repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;
+  int sheets_size() const;
+  private:
+  int _internal_sheets_size() const;
+
+  public:
+  void clear_sheets() ;
+  ::palm::lily::v1::ExcelModel_Sheet* mutable_sheets(int index);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet >*
+      mutable_sheets();
+  private:
+  const ::palm::lily::v1::ExcelModel_Sheet& _internal_sheets(int index) const;
+  ::palm::lily::v1::ExcelModel_Sheet* _internal_add_sheets();
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet>& _internal_sheets() const;
+  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet>* _internal_mutable_sheets();
+  public:
+  const ::palm::lily::v1::ExcelModel_Sheet& sheets(int index) const;
+  ::palm::lily::v1::ExcelModel_Sheet* add_sheets();
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet >&
+      sheets() const;
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet > sheets_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  };
+  union { Impl_ _impl_; };
+  friend struct ::TableStruct_lily_2eproto;
+};// -------------------------------------------------------------------
+
+class TexToRequest_FilesEntry_DoNotUse final : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<TexToRequest_FilesEntry_DoNotUse, 
+    std::string, std::string,
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_BYTES> {
+public:
+  typedef ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<TexToRequest_FilesEntry_DoNotUse, 
+    std::string, std::string,
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_BYTES> SuperType;
+  TexToRequest_FilesEntry_DoNotUse();
+  template <typename = void>
+  explicit PROTOBUF_CONSTEXPR TexToRequest_FilesEntry_DoNotUse(
+      ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+  explicit TexToRequest_FilesEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void MergeFrom(const TexToRequest_FilesEntry_DoNotUse& other);
+  static const TexToRequest_FilesEntry_DoNotUse* internal_default_instance() { return reinterpret_cast<const TexToRequest_FilesEntry_DoNotUse*>(&_TexToRequest_FilesEntry_DoNotUse_default_instance_); }
+  static bool ValidateKey(std::string* s) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast<int>(s->size()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, "palm.lily.v1.TexToRequest.FilesEntry.key");
+ }
+  static bool ValidateValue(void*) { return true; }
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  friend struct ::TableStruct_lily_2eproto;
+};
+// -------------------------------------------------------------------
+
+class TexToRequest final :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:palm.lily.v1.TexToRequest) */ {
+ public:
+  inline TexToRequest() : TexToRequest(nullptr) {}
+  ~TexToRequest() override;
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR TexToRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  TexToRequest(const TexToRequest& from);
+  TexToRequest(TexToRequest&& from) noexcept
+    : TexToRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline TexToRequest& operator=(const TexToRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline TexToRequest& operator=(TexToRequest&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const TexToRequest& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const TexToRequest* internal_default_instance() {
+    return reinterpret_cast<const TexToRequest*>(
+               &_TexToRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  friend void swap(TexToRequest& a, TexToRequest& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(TexToRequest* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(TexToRequest* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  TexToRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<TexToRequest>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+  void CopyFrom(const TexToRequest& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+  void MergeFrom( const TexToRequest& from) {
+    TexToRequest::MergeImpl(*this, from);
+  }
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
+  public:
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  ::size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
+
+  private:
+  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(TexToRequest* other);
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.TexToRequest";
+  }
+  protected:
+  explicit TexToRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kFilesFieldNumber = 1,
+  };
+  // map<string, bytes> files = 1;
+  int files_size() const;
+  private:
+  int _internal_files_size() const;
+
+  public:
+  void clear_files() ;
+  private:
+  const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >&
+      _internal_files() const;
+  ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >*
+      _internal_mutable_files();
+  public:
+  const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >&
+      files() const;
+  ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >*
+      mutable_files();
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.TexToRequest)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+    ::PROTOBUF_NAMESPACE_ID::internal::MapField<
+        TexToRequest_FilesEntry_DoNotUse,
+        std::string, std::string,
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_BYTES> files_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  };
+  union { Impl_ _impl_; };
+  friend struct ::TableStruct_lily_2eproto;
+};// -------------------------------------------------------------------
+
+class EpubBuildRequest final :
+    public ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:palm.lily.v1.EpubBuildRequest) */ {
+ public:
+  inline EpubBuildRequest() : EpubBuildRequest(nullptr) {}
+  template<typename = void>
+  explicit PROTOBUF_CONSTEXPR EpubBuildRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  EpubBuildRequest(const EpubBuildRequest& from);
+  EpubBuildRequest(EpubBuildRequest&& from) noexcept
+    : EpubBuildRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline EpubBuildRequest& operator=(const EpubBuildRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline EpubBuildRequest& operator=(EpubBuildRequest&& from) noexcept {
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()
+  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+        && GetOwningArena() != nullptr
+  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
+    ) {
+      InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+  }
+  inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return default_instance().GetMetadata().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return default_instance().GetMetadata().reflection;
+  }
+  static const EpubBuildRequest& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const EpubBuildRequest* internal_default_instance() {
+    return reinterpret_cast<const EpubBuildRequest*>(
+               &_EpubBuildRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  friend void swap(EpubBuildRequest& a, EpubBuildRequest& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(EpubBuildRequest* other) {
+    if (other == this) return;
+  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() != nullptr &&
+        GetOwningArena() == other->GetOwningArena()) {
+   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
+    if (GetOwningArena() == other->GetOwningArena()) {
+  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(EpubBuildRequest* other) {
+    if (other == this) return;
+    ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  EpubBuildRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+    return CreateMaybeMessage<EpubBuildRequest>(arena);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyFrom;
+  inline void CopyFrom(const EpubBuildRequest& from) {
+    ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl(*this, from);
+  }
+  using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeFrom;
+  void MergeFrom(const EpubBuildRequest& from) {
+    ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl(*this, from);
+  }
+  public:
+
+  private:
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::absl::string_view FullMessageName() {
+    return "palm.lily.v1.EpubBuildRequest";
+  }
+  protected:
+  explicit EpubBuildRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.EpubBuildRequest)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  struct Impl_ {
+  };
+  friend struct ::TableStruct_lily_2eproto;
+};
+
+// ===================================================================
+
+
+
+
+// ===================================================================
+
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// File
+
+// optional string content_type = 1;
+inline bool File::has_content_type() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
+  return value;
+}
+inline void File::clear_content_type() {
+  _impl_.content_type_.ClearToEmpty();
+  _impl_._has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& File::content_type() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.File.content_type)
+  return _internal_content_type();
+}
+template <typename Arg_, typename... Args_>
+inline PROTOBUF_ALWAYS_INLINE void File::set_content_type(Arg_&& arg,
+                                                     Args_... args) {
+  _impl_._has_bits_[0] |= 0x00000001u;
+  _impl_.content_type_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation());
+  // @@protoc_insertion_point(field_set:palm.lily.v1.File.content_type)
+}
+inline std::string* File::mutable_content_type() {
+  std::string* _s = _internal_mutable_content_type();
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.File.content_type)
+  return _s;
+}
+inline const std::string& File::_internal_content_type() const {
+  return _impl_.content_type_.Get();
+}
+inline void File::_internal_set_content_type(const std::string& value) {
+  _impl_._has_bits_[0] |= 0x00000001u;
+
+
+  _impl_.content_type_.Set(value, GetArenaForAllocation());
+}
+inline std::string* File::_internal_mutable_content_type() {
+  _impl_._has_bits_[0] |= 0x00000001u;
+  return _impl_.content_type_.Mutable( GetArenaForAllocation());
+}
+inline std::string* File::release_content_type() {
+  // @@protoc_insertion_point(field_release:palm.lily.v1.File.content_type)
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
+    return nullptr;
+  }
+  _impl_._has_bits_[0] &= ~0x00000001u;
+  auto* released = _impl_.content_type_.Release();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  _impl_.content_type_.Set("", GetArenaForAllocation());
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  return released;
+}
+inline void File::set_allocated_content_type(std::string* value) {
+  if (value != nullptr) {
+    _impl_._has_bits_[0] |= 0x00000001u;
+  } else {
+    _impl_._has_bits_[0] &= ~0x00000001u;
+  }
+  _impl_.content_type_.SetAllocated(value, GetArenaForAllocation());
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        if (_impl_.content_type_.IsDefault()) {
+          _impl_.content_type_.Set("", GetArenaForAllocation());
+        }
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  // @@protoc_insertion_point(field_set_allocated:palm.lily.v1.File.content_type)
+}
+
+// bytes payload = 2;
+inline void File::clear_payload() {
+  _impl_.payload_.ClearToEmpty();
+}
+inline const std::string& File::payload() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.File.payload)
+  return _internal_payload();
+}
+template <typename Arg_, typename... Args_>
+inline PROTOBUF_ALWAYS_INLINE void File::set_payload(Arg_&& arg,
+                                                     Args_... args) {
+  ;
+  _impl_.payload_.SetBytes(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation());
+  // @@protoc_insertion_point(field_set:palm.lily.v1.File.payload)
+}
+inline std::string* File::mutable_payload() {
+  std::string* _s = _internal_mutable_payload();
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.File.payload)
+  return _s;
+}
+inline const std::string& File::_internal_payload() const {
+  return _impl_.payload_.Get();
+}
+inline void File::_internal_set_payload(const std::string& value) {
+  ;
+
+
+  _impl_.payload_.Set(value, GetArenaForAllocation());
+}
+inline std::string* File::_internal_mutable_payload() {
+  ;
+  return _impl_.payload_.Mutable( GetArenaForAllocation());
+}
+inline std::string* File::release_payload() {
+  // @@protoc_insertion_point(field_release:palm.lily.v1.File.payload)
+  return _impl_.payload_.Release();
+}
+inline void File::set_allocated_payload(std::string* value) {
+  _impl_.payload_.SetAllocated(value, GetArenaForAllocation());
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        if (_impl_.payload_.IsDefault()) {
+          _impl_.payload_.Set("", GetArenaForAllocation());
+        }
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  // @@protoc_insertion_point(field_set_allocated:palm.lily.v1.File.payload)
+}
+
+// -------------------------------------------------------------------
+
+// ExcelModel_Sheet_Cell
+
+// uint32 row = 1;
+inline void ExcelModel_Sheet_Cell::clear_row() {
+  _impl_.row_ = 0u;
+}
+inline ::uint32_t ExcelModel_Sheet_Cell::row() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.Sheet.Cell.row)
+  return _internal_row();
+}
+inline void ExcelModel_Sheet_Cell::set_row(::uint32_t value) {
+  _internal_set_row(value);
+  // @@protoc_insertion_point(field_set:palm.lily.v1.ExcelModel.Sheet.Cell.row)
+}
+inline ::uint32_t ExcelModel_Sheet_Cell::_internal_row() const {
+  return _impl_.row_;
+}
+inline void ExcelModel_Sheet_Cell::_internal_set_row(::uint32_t value) {
+  ;
+  _impl_.row_ = value;
+}
+
+// uint32 col = 2;
+inline void ExcelModel_Sheet_Cell::clear_col() {
+  _impl_.col_ = 0u;
+}
+inline ::uint32_t ExcelModel_Sheet_Cell::col() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.Sheet.Cell.col)
+  return _internal_col();
+}
+inline void ExcelModel_Sheet_Cell::set_col(::uint32_t value) {
+  _internal_set_col(value);
+  // @@protoc_insertion_point(field_set:palm.lily.v1.ExcelModel.Sheet.Cell.col)
+}
+inline ::uint32_t ExcelModel_Sheet_Cell::_internal_col() const {
+  return _impl_.col_;
+}
+inline void ExcelModel_Sheet_Cell::_internal_set_col(::uint32_t value) {
+  ;
+  _impl_.col_ = value;
+}
+
+// string val = 3;
+inline void ExcelModel_Sheet_Cell::clear_val() {
+  _impl_.val_.ClearToEmpty();
+}
+inline const std::string& ExcelModel_Sheet_Cell::val() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.Sheet.Cell.val)
+  return _internal_val();
+}
+template <typename Arg_, typename... Args_>
+inline PROTOBUF_ALWAYS_INLINE void ExcelModel_Sheet_Cell::set_val(Arg_&& arg,
+                                                     Args_... args) {
+  ;
+  _impl_.val_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation());
+  // @@protoc_insertion_point(field_set:palm.lily.v1.ExcelModel.Sheet.Cell.val)
+}
+inline std::string* ExcelModel_Sheet_Cell::mutable_val() {
+  std::string* _s = _internal_mutable_val();
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.ExcelModel.Sheet.Cell.val)
+  return _s;
+}
+inline const std::string& ExcelModel_Sheet_Cell::_internal_val() const {
+  return _impl_.val_.Get();
+}
+inline void ExcelModel_Sheet_Cell::_internal_set_val(const std::string& value) {
+  ;
+
+
+  _impl_.val_.Set(value, GetArenaForAllocation());
+}
+inline std::string* ExcelModel_Sheet_Cell::_internal_mutable_val() {
+  ;
+  return _impl_.val_.Mutable( GetArenaForAllocation());
+}
+inline std::string* ExcelModel_Sheet_Cell::release_val() {
+  // @@protoc_insertion_point(field_release:palm.lily.v1.ExcelModel.Sheet.Cell.val)
+  return _impl_.val_.Release();
+}
+inline void ExcelModel_Sheet_Cell::set_allocated_val(std::string* value) {
+  _impl_.val_.SetAllocated(value, GetArenaForAllocation());
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        if (_impl_.val_.IsDefault()) {
+          _impl_.val_.Set("", GetArenaForAllocation());
+        }
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  // @@protoc_insertion_point(field_set_allocated:palm.lily.v1.ExcelModel.Sheet.Cell.val)
+}
+
+// -------------------------------------------------------------------
+
+// ExcelModel_Sheet
+
+// string name = 1;
+inline void ExcelModel_Sheet::clear_name() {
+  _impl_.name_.ClearToEmpty();
+}
+inline const std::string& ExcelModel_Sheet::name() const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.Sheet.name)
+  return _internal_name();
+}
+template <typename Arg_, typename... Args_>
+inline PROTOBUF_ALWAYS_INLINE void ExcelModel_Sheet::set_name(Arg_&& arg,
+                                                     Args_... args) {
+  ;
+  _impl_.name_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation());
+  // @@protoc_insertion_point(field_set:palm.lily.v1.ExcelModel.Sheet.name)
+}
+inline std::string* ExcelModel_Sheet::mutable_name() {
+  std::string* _s = _internal_mutable_name();
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.ExcelModel.Sheet.name)
+  return _s;
+}
+inline const std::string& ExcelModel_Sheet::_internal_name() const {
+  return _impl_.name_.Get();
+}
+inline void ExcelModel_Sheet::_internal_set_name(const std::string& value) {
+  ;
+
+
+  _impl_.name_.Set(value, GetArenaForAllocation());
+}
+inline std::string* ExcelModel_Sheet::_internal_mutable_name() {
+  ;
+  return _impl_.name_.Mutable( GetArenaForAllocation());
+}
+inline std::string* ExcelModel_Sheet::release_name() {
+  // @@protoc_insertion_point(field_release:palm.lily.v1.ExcelModel.Sheet.name)
+  return _impl_.name_.Release();
+}
+inline void ExcelModel_Sheet::set_allocated_name(std::string* value) {
+  _impl_.name_.SetAllocated(value, GetArenaForAllocation());
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+        if (_impl_.name_.IsDefault()) {
+          _impl_.name_.Set("", GetArenaForAllocation());
+        }
+  #endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  // @@protoc_insertion_point(field_set_allocated:palm.lily.v1.ExcelModel.Sheet.name)
+}
+
+// repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;
+inline int ExcelModel_Sheet::_internal_cells_size() const {
+  return _impl_.cells_.size();
+}
+inline int ExcelModel_Sheet::cells_size() const {
+  return _internal_cells_size();
+}
+inline void ExcelModel_Sheet::clear_cells() {
+  _internal_mutable_cells()->Clear();
+}
+inline ::palm::lily::v1::ExcelModel_Sheet_Cell* ExcelModel_Sheet::mutable_cells(int index) {
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.ExcelModel.Sheet.cells)
+  return _internal_mutable_cells()->Mutable(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet_Cell >*
+ExcelModel_Sheet::mutable_cells() {
+  // @@protoc_insertion_point(field_mutable_list:palm.lily.v1.ExcelModel.Sheet.cells)
+  return _internal_mutable_cells();
+}
+inline const ::palm::lily::v1::ExcelModel_Sheet_Cell& ExcelModel_Sheet::_internal_cells(int index) const {
+  return _internal_cells().Get(index);
+}
+inline const ::palm::lily::v1::ExcelModel_Sheet_Cell& ExcelModel_Sheet::cells(int index) const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.Sheet.cells)
+  return _internal_cells(index);
+}
+inline ::palm::lily::v1::ExcelModel_Sheet_Cell* ExcelModel_Sheet::_internal_add_cells() {
+  return _internal_mutable_cells()->Add();
+}
+inline ::palm::lily::v1::ExcelModel_Sheet_Cell* ExcelModel_Sheet::add_cells() {
+  ::palm::lily::v1::ExcelModel_Sheet_Cell* _add = _internal_add_cells();
+  // @@protoc_insertion_point(field_add:palm.lily.v1.ExcelModel.Sheet.cells)
+  return _add;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet_Cell >&
+ExcelModel_Sheet::cells() const {
+  // @@protoc_insertion_point(field_list:palm.lily.v1.ExcelModel.Sheet.cells)
+  return _internal_cells();
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet_Cell>&
+ExcelModel_Sheet::_internal_cells() const {
+  return _impl_.cells_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet_Cell>*
+ExcelModel_Sheet::_internal_mutable_cells() {
+  return &_impl_.cells_;
+}
+
+// -------------------------------------------------------------------
+
+// ExcelModel
+
+// repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;
+inline int ExcelModel::_internal_sheets_size() const {
+  return _impl_.sheets_.size();
+}
+inline int ExcelModel::sheets_size() const {
+  return _internal_sheets_size();
+}
+inline void ExcelModel::clear_sheets() {
+  _internal_mutable_sheets()->Clear();
+}
+inline ::palm::lily::v1::ExcelModel_Sheet* ExcelModel::mutable_sheets(int index) {
+  // @@protoc_insertion_point(field_mutable:palm.lily.v1.ExcelModel.sheets)
+  return _internal_mutable_sheets()->Mutable(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet >*
+ExcelModel::mutable_sheets() {
+  // @@protoc_insertion_point(field_mutable_list:palm.lily.v1.ExcelModel.sheets)
+  return _internal_mutable_sheets();
+}
+inline const ::palm::lily::v1::ExcelModel_Sheet& ExcelModel::_internal_sheets(int index) const {
+  return _internal_sheets().Get(index);
+}
+inline const ::palm::lily::v1::ExcelModel_Sheet& ExcelModel::sheets(int index) const {
+  // @@protoc_insertion_point(field_get:palm.lily.v1.ExcelModel.sheets)
+  return _internal_sheets(index);
+}
+inline ::palm::lily::v1::ExcelModel_Sheet* ExcelModel::_internal_add_sheets() {
+  return _internal_mutable_sheets()->Add();
+}
+inline ::palm::lily::v1::ExcelModel_Sheet* ExcelModel::add_sheets() {
+  ::palm::lily::v1::ExcelModel_Sheet* _add = _internal_add_sheets();
+  // @@protoc_insertion_point(field_add:palm.lily.v1.ExcelModel.sheets)
+  return _add;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::palm::lily::v1::ExcelModel_Sheet >&
+ExcelModel::sheets() const {
+  // @@protoc_insertion_point(field_list:palm.lily.v1.ExcelModel.sheets)
+  return _internal_sheets();
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet>&
+ExcelModel::_internal_sheets() const {
+  return _impl_.sheets_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::palm::lily::v1::ExcelModel_Sheet>*
+ExcelModel::_internal_mutable_sheets() {
+  return &_impl_.sheets_;
+}
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// TexToRequest
+
+// map<string, bytes> files = 1;
+inline int TexToRequest::_internal_files_size() const {
+  return _impl_.files_.size();
+}
+inline int TexToRequest::files_size() const {
+  return _internal_files_size();
+}
+inline void TexToRequest::clear_files() {
+  _impl_.files_.Clear();
+}
+inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >&
+TexToRequest::_internal_files() const {
+  return _impl_.files_.GetMap();
+}
+inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >&
+TexToRequest::files() const {
+  // @@protoc_insertion_point(field_map:palm.lily.v1.TexToRequest.files)
+  return _internal_files();
+}
+inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >*
+TexToRequest::_internal_mutable_files() {
+  return _impl_.files_.MutableMap();
+}
+inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >*
+TexToRequest::mutable_files() {
+  // @@protoc_insertion_point(field_mutable_map:palm.lily.v1.TexToRequest.files)
+  return _internal_mutable_files();
+}
+
+// -------------------------------------------------------------------
+
+// EpubBuildRequest
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif  // __GNUC__
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace v1
+}  // namespace lily
+}  // namespace palm
+
+
+// @@protoc_insertion_point(global_scope)
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_lily_2eproto_2epb_2eh

+ 1304 - 0
clients/csharp/Lily.cs

@@ -0,0 +1,1304 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: lily.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021, 8981
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Palm.Lily.V1 {
+
+  /// <summary>Holder for reflection information generated from lily.proto</summary>
+  public static partial class LilyReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for lily.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static LilyReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CgpsaWx5LnByb3RvEgxwYWxtLmxpbHkudjEiQwoERmlsZRIZCgxjb250ZW50",
+            "X3R5cGUYASABKAlIAIgBARIPCgdwYXlsb2FkGAIgASgMQg8KDV9jb250ZW50",
+            "X3R5cGUitgEKCkV4Y2VsTW9kZWwSLgoGc2hlZXRzGAEgAygLMh4ucGFsbS5s",
+            "aWx5LnYxLkV4Y2VsTW9kZWwuU2hlZXQaeAoFU2hlZXQSDAoEbmFtZRgBIAEo",
+            "CRIyCgVjZWxscxgCIAMoCzIjLnBhbG0ubGlseS52MS5FeGNlbE1vZGVsLlNo",
+            "ZWV0LkNlbGwaLQoEQ2VsbBILCgNyb3cYASABKA0SCwoDY29sGAIgASgNEgsK",
+            "A3ZhbBgDIAEoCSJyCgxUZXhUb1JlcXVlc3QSNAoFZmlsZXMYASADKAsyJS5w",
+            "YWxtLmxpbHkudjEuVGV4VG9SZXF1ZXN0LkZpbGVzRW50cnkaLAoKRmlsZXNF",
+            "bnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAw6AjgBIhIKEEVwdWJC",
+            "dWlsZFJlcXVlc3QyfAoFRXhjZWwSNwoFUGFyc2USEi5wYWxtLmxpbHkudjEu",
+            "RmlsZRoYLnBhbG0ubGlseS52MS5FeGNlbE1vZGVsIgASOgoIR2VuZXJhdGUS",
+            "GC5wYWxtLmxpbHkudjEuRXhjZWxNb2RlbBoSLnBhbG0ubGlseS52MS5GaWxl",
+            "IgAyfAoDVGV4EjkKBVRvUGRmEhoucGFsbS5saWx5LnYxLlRleFRvUmVxdWVz",
+            "dBoSLnBhbG0ubGlseS52MS5GaWxlIgASOgoGVG9Xb3JkEhoucGFsbS5saWx5",
+            "LnYxLlRleFRvUmVxdWVzdBoSLnBhbG0ubGlseS52MS5GaWxlIgAyRQoERXB1",
+            "YhI9CgVCdWlsZBIeLnBhbG0ubGlseS52MS5FcHViQnVpbGRSZXF1ZXN0GhIu",
+            "cGFsbS5saWx5LnYxLkZpbGUiAEIuCipjb20uZ2l0aHViLnNhdHVybl94aXYu",
+            "cGFsbS5wbHVnaW5zLmxpbHkudjFQAWIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.File), global::Palm.Lily.V1.File.Parser, new[]{ "ContentType", "Payload" }, new[]{ "ContentType" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.ExcelModel), global::Palm.Lily.V1.ExcelModel.Parser, new[]{ "Sheets" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.ExcelModel.Types.Sheet), global::Palm.Lily.V1.ExcelModel.Types.Sheet.Parser, new[]{ "Name", "Cells" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell), global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell.Parser, new[]{ "Row", "Col", "Val" }, null, null, null, null)})}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.TexToRequest), global::Palm.Lily.V1.TexToRequest.Parser, new[]{ "Files" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Palm.Lily.V1.EpubBuildRequest), global::Palm.Lily.V1.EpubBuildRequest.Parser, null, null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  public sealed partial class File : pb::IMessage<File>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<File> _parser = new pb::MessageParser<File>(() => new File());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<File> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public File() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public File(File other) : this() {
+      contentType_ = other.contentType_;
+      payload_ = other.payload_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public File Clone() {
+      return new File(this);
+    }
+
+    /// <summary>Field number for the "content_type" field.</summary>
+    public const int ContentTypeFieldNumber = 1;
+    private readonly static string ContentTypeDefaultValue = "";
+
+    private string contentType_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string ContentType {
+      get { return contentType_ ?? ContentTypeDefaultValue; }
+      set {
+        contentType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "content_type" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasContentType {
+      get { return contentType_ != null; }
+    }
+    /// <summary>Clears the value of the "content_type" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearContentType() {
+      contentType_ = null;
+    }
+
+    /// <summary>Field number for the "payload" field.</summary>
+    public const int PayloadFieldNumber = 2;
+    private pb::ByteString payload_ = pb::ByteString.Empty;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pb::ByteString Payload {
+      get { return payload_; }
+      set {
+        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as File);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(File other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ContentType != other.ContentType) return false;
+      if (Payload != other.Payload) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (HasContentType) hash ^= ContentType.GetHashCode();
+      if (Payload.Length != 0) hash ^= Payload.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (HasContentType) {
+        output.WriteRawTag(10);
+        output.WriteString(ContentType);
+      }
+      if (Payload.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteBytes(Payload);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasContentType) {
+        output.WriteRawTag(10);
+        output.WriteString(ContentType);
+      }
+      if (Payload.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteBytes(Payload);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (HasContentType) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContentType);
+      }
+      if (Payload.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payload);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(File other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasContentType) {
+        ContentType = other.ContentType;
+      }
+      if (other.Payload.Length != 0) {
+        Payload = other.Payload;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            ContentType = input.ReadString();
+            break;
+          }
+          case 18: {
+            Payload = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            ContentType = input.ReadString();
+            break;
+          }
+          case 18: {
+            Payload = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  public sealed partial class ExcelModel : pb::IMessage<ExcelModel>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<ExcelModel> _parser = new pb::MessageParser<ExcelModel>(() => new ExcelModel());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<ExcelModel> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ExcelModel() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ExcelModel(ExcelModel other) : this() {
+      sheets_ = other.sheets_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ExcelModel Clone() {
+      return new ExcelModel(this);
+    }
+
+    /// <summary>Field number for the "sheets" field.</summary>
+    public const int SheetsFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Palm.Lily.V1.ExcelModel.Types.Sheet> _repeated_sheets_codec
+        = pb::FieldCodec.ForMessage(10, global::Palm.Lily.V1.ExcelModel.Types.Sheet.Parser);
+    private readonly pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet> sheets_ = new pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet>();
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet> Sheets {
+      get { return sheets_; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as ExcelModel);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(ExcelModel other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!sheets_.Equals(other.sheets_)) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= sheets_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      sheets_.WriteTo(output, _repeated_sheets_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      sheets_.WriteTo(ref output, _repeated_sheets_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      size += sheets_.CalculateSize(_repeated_sheets_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(ExcelModel other) {
+      if (other == null) {
+        return;
+      }
+      sheets_.Add(other.sheets_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            sheets_.AddEntriesFrom(input, _repeated_sheets_codec);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            sheets_.AddEntriesFrom(ref input, _repeated_sheets_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the ExcelModel message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static partial class Types {
+      public sealed partial class Sheet : pb::IMessage<Sheet>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
+        private static readonly pb::MessageParser<Sheet> _parser = new pb::MessageParser<Sheet>(() => new Sheet());
+        private pb::UnknownFieldSet _unknownFields;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pb::MessageParser<Sheet> Parser { get { return _parser; } }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Palm.Lily.V1.ExcelModel.Descriptor.NestedTypes[0]; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public Sheet() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public Sheet(Sheet other) : this() {
+          name_ = other.name_;
+          cells_ = other.cells_.Clone();
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public Sheet Clone() {
+          return new Sheet(this);
+        }
+
+        /// <summary>Field number for the "name" field.</summary>
+        public const int NameFieldNumber = 1;
+        private string name_ = "";
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public string Name {
+          get { return name_; }
+          set {
+            name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "cells" field.</summary>
+        public const int CellsFieldNumber = 2;
+        private static readonly pb::FieldCodec<global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell> _repeated_cells_codec
+            = pb::FieldCodec.ForMessage(18, global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell.Parser);
+        private readonly pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell> cells_ = new pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell>();
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public pbc::RepeatedField<global::Palm.Lily.V1.ExcelModel.Types.Sheet.Types.Cell> Cells {
+          get { return cells_; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override bool Equals(object other) {
+          return Equals(other as Sheet);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool Equals(Sheet other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Name != other.Name) return false;
+          if(!cells_.Equals(other.cells_)) return false;
+          return Equals(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Name.Length != 0) hash ^= Name.GetHashCode();
+          hash ^= cells_.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
+          return hash;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (Name.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Name);
+          }
+          cells_.WriteTo(output, _repeated_cells_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (Name.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Name);
+          }
+          cells_.WriteTo(ref output, _repeated_cells_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public int CalculateSize() {
+          int size = 0;
+          if (Name.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+          }
+          size += cells_.CalculateSize(_repeated_cells_codec);
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
+          return size;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(Sheet other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Name.Length != 0) {
+            Name = other.Name;
+          }
+          cells_.Add(other.cells_);
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                break;
+              case 10: {
+                Name = input.ReadString();
+                break;
+              }
+              case 18: {
+                cells_.AddEntriesFrom(input, _repeated_cells_codec);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                Name = input.ReadString();
+                break;
+              }
+              case 18: {
+                cells_.AddEntriesFrom(ref input, _repeated_cells_codec);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
+        #region Nested types
+        /// <summary>Container for nested types declared in the Sheet message type.</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static partial class Types {
+          public sealed partial class Cell : pb::IMessage<Cell>
+          #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              , pb::IBufferMessage
+          #endif
+          {
+            private static readonly pb::MessageParser<Cell> _parser = new pb::MessageParser<Cell>(() => new Cell());
+            private pb::UnknownFieldSet _unknownFields;
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public static pb::MessageParser<Cell> Parser { get { return _parser; } }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public static pbr::MessageDescriptor Descriptor {
+              get { return global::Palm.Lily.V1.ExcelModel.Types.Sheet.Descriptor.NestedTypes[0]; }
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            pbr::MessageDescriptor pb::IMessage.Descriptor {
+              get { return Descriptor; }
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public Cell() {
+              OnConstruction();
+            }
+
+            partial void OnConstruction();
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public Cell(Cell other) : this() {
+              row_ = other.row_;
+              col_ = other.col_;
+              val_ = other.val_;
+              _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public Cell Clone() {
+              return new Cell(this);
+            }
+
+            /// <summary>Field number for the "row" field.</summary>
+            public const int RowFieldNumber = 1;
+            private uint row_;
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public uint Row {
+              get { return row_; }
+              set {
+                row_ = value;
+              }
+            }
+
+            /// <summary>Field number for the "col" field.</summary>
+            public const int ColFieldNumber = 2;
+            private uint col_;
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public uint Col {
+              get { return col_; }
+              set {
+                col_ = value;
+              }
+            }
+
+            /// <summary>Field number for the "val" field.</summary>
+            public const int ValFieldNumber = 3;
+            private string val_ = "";
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public string Val {
+              get { return val_; }
+              set {
+                val_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+              }
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public override bool Equals(object other) {
+              return Equals(other as Cell);
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public bool Equals(Cell other) {
+              if (ReferenceEquals(other, null)) {
+                return false;
+              }
+              if (ReferenceEquals(other, this)) {
+                return true;
+              }
+              if (Row != other.Row) return false;
+              if (Col != other.Col) return false;
+              if (Val != other.Val) return false;
+              return Equals(_unknownFields, other._unknownFields);
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public override int GetHashCode() {
+              int hash = 1;
+              if (Row != 0) hash ^= Row.GetHashCode();
+              if (Col != 0) hash ^= Col.GetHashCode();
+              if (Val.Length != 0) hash ^= Val.GetHashCode();
+              if (_unknownFields != null) {
+                hash ^= _unknownFields.GetHashCode();
+              }
+              return hash;
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public override string ToString() {
+              return pb::JsonFormatter.ToDiagnosticString(this);
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public void WriteTo(pb::CodedOutputStream output) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              output.WriteRawMessage(this);
+            #else
+              if (Row != 0) {
+                output.WriteRawTag(8);
+                output.WriteUInt32(Row);
+              }
+              if (Col != 0) {
+                output.WriteRawTag(16);
+                output.WriteUInt32(Col);
+              }
+              if (Val.Length != 0) {
+                output.WriteRawTag(26);
+                output.WriteString(Val);
+              }
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(output);
+              }
+            #endif
+            }
+
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+              if (Row != 0) {
+                output.WriteRawTag(8);
+                output.WriteUInt32(Row);
+              }
+              if (Col != 0) {
+                output.WriteRawTag(16);
+                output.WriteUInt32(Col);
+              }
+              if (Val.Length != 0) {
+                output.WriteRawTag(26);
+                output.WriteString(Val);
+              }
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(ref output);
+              }
+            }
+            #endif
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public int CalculateSize() {
+              int size = 0;
+              if (Row != 0) {
+                size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Row);
+              }
+              if (Col != 0) {
+                size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Col);
+              }
+              if (Val.Length != 0) {
+                size += 1 + pb::CodedOutputStream.ComputeStringSize(Val);
+              }
+              if (_unknownFields != null) {
+                size += _unknownFields.CalculateSize();
+              }
+              return size;
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public void MergeFrom(Cell other) {
+              if (other == null) {
+                return;
+              }
+              if (other.Row != 0) {
+                Row = other.Row;
+              }
+              if (other.Col != 0) {
+                Col = other.Col;
+              }
+              if (other.Val.Length != 0) {
+                Val = other.Val;
+              }
+              _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+            }
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            public void MergeFrom(pb::CodedInputStream input) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              input.ReadRawMessage(this);
+            #else
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                    break;
+                  case 8: {
+                    Row = input.ReadUInt32();
+                    break;
+                  }
+                  case 16: {
+                    Col = input.ReadUInt32();
+                    break;
+                  }
+                  case 26: {
+                    Val = input.ReadString();
+                    break;
+                  }
+                }
+              }
+            #endif
+            }
+
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                    break;
+                  case 8: {
+                    Row = input.ReadUInt32();
+                    break;
+                  }
+                  case 16: {
+                    Col = input.ReadUInt32();
+                    break;
+                  }
+                  case 26: {
+                    Val = input.ReadString();
+                    break;
+                  }
+                }
+              }
+            }
+            #endif
+
+          }
+
+        }
+        #endregion
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  public sealed partial class TexToRequest : pb::IMessage<TexToRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<TexToRequest> _parser = new pb::MessageParser<TexToRequest>(() => new TexToRequest());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<TexToRequest> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TexToRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TexToRequest(TexToRequest other) : this() {
+      files_ = other.files_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TexToRequest Clone() {
+      return new TexToRequest(this);
+    }
+
+    /// <summary>Field number for the "files" field.</summary>
+    public const int FilesFieldNumber = 1;
+    private static readonly pbc::MapField<string, pb::ByteString>.Codec _map_files_codec
+        = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 10);
+    private readonly pbc::MapField<string, pb::ByteString> files_ = new pbc::MapField<string, pb::ByteString>();
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::MapField<string, pb::ByteString> Files {
+      get { return files_; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as TexToRequest);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(TexToRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Files.Equals(other.Files)) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Files.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      files_.WriteTo(output, _map_files_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      files_.WriteTo(ref output, _map_files_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      size += files_.CalculateSize(_map_files_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(TexToRequest other) {
+      if (other == null) {
+        return;
+      }
+      files_.MergeFrom(other.files_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            files_.AddEntriesFrom(input, _map_files_codec);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            files_.AddEntriesFrom(ref input, _map_files_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  public sealed partial class EpubBuildRequest : pb::IMessage<EpubBuildRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<EpubBuildRequest> _parser = new pb::MessageParser<EpubBuildRequest>(() => new EpubBuildRequest());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<EpubBuildRequest> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public EpubBuildRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public EpubBuildRequest(EpubBuildRequest other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public EpubBuildRequest Clone() {
+      return new EpubBuildRequest(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as EpubBuildRequest);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(EpubBuildRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(EpubBuildRequest other) {
+      if (other == null) {
+        return;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 513 - 0
clients/csharp/LilyGrpc.cs

@@ -0,0 +1,513 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: lily.proto
+// </auto-generated>
+#pragma warning disable 0414, 1591, 8981, 0612
+#region Designer generated code
+
+using grpc = global::Grpc.Core;
+
+namespace Palm.Lily.V1 {
+  public static partial class Excel
+  {
+    static readonly string __ServiceName = "palm.lily.v1.Excel";
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context)
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (message is global::Google.Protobuf.IBufferMessage)
+      {
+        context.SetPayloadLength(message.CalculateSize());
+        global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter());
+        context.Complete();
+        return;
+      }
+      #endif
+      context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static class __Helper_MessageCache<T>
+    {
+      public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static T __Helper_DeserializeMessage<T>(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser<T> parser) where T : global::Google.Protobuf.IMessage<T>
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (__Helper_MessageCache<T>.IsBufferMessage)
+      {
+        return parser.ParseFrom(context.PayloadAsReadOnlySequence());
+      }
+      #endif
+      return parser.ParseFrom(context.PayloadAsNewBuffer());
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.File> __Marshaller_palm_lily_v1_File = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.File.Parser));
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.ExcelModel> __Marshaller_palm_lily_v1_ExcelModel = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.ExcelModel.Parser));
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Method<global::Palm.Lily.V1.File, global::Palm.Lily.V1.ExcelModel> __Method_Parse = new grpc::Method<global::Palm.Lily.V1.File, global::Palm.Lily.V1.ExcelModel>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "Parse",
+        __Marshaller_palm_lily_v1_File,
+        __Marshaller_palm_lily_v1_ExcelModel);
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Method<global::Palm.Lily.V1.ExcelModel, global::Palm.Lily.V1.File> __Method_Generate = new grpc::Method<global::Palm.Lily.V1.ExcelModel, global::Palm.Lily.V1.File>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "Generate",
+        __Marshaller_palm_lily_v1_ExcelModel,
+        __Marshaller_palm_lily_v1_File);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.Services[0]; }
+    }
+
+    /// <summary>Base class for server-side implementations of Excel</summary>
+    [grpc::BindServiceMethod(typeof(Excel), "BindService")]
+    public abstract partial class ExcelBase
+    {
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::System.Threading.Tasks.Task<global::Palm.Lily.V1.ExcelModel> Parse(global::Palm.Lily.V1.File request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::System.Threading.Tasks.Task<global::Palm.Lily.V1.File> Generate(global::Palm.Lily.V1.ExcelModel request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for Excel</summary>
+    public partial class ExcelClient : grpc::ClientBase<ExcelClient>
+    {
+      /// <summary>Creates a new client for Excel</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public ExcelClient(grpc::ChannelBase channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for Excel that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public ExcelClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected ExcelClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected ExcelClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.ExcelModel Parse(global::Palm.Lily.V1.File request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return Parse(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.ExcelModel Parse(global::Palm.Lily.V1.File request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_Parse, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.ExcelModel> ParseAsync(global::Palm.Lily.V1.File request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ParseAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.ExcelModel> ParseAsync(global::Palm.Lily.V1.File request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_Parse, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File Generate(global::Palm.Lily.V1.ExcelModel request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return Generate(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File Generate(global::Palm.Lily.V1.ExcelModel request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_Generate, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> GenerateAsync(global::Palm.Lily.V1.ExcelModel request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return GenerateAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> GenerateAsync(global::Palm.Lily.V1.ExcelModel request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_Generate, null, options, request);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected override ExcelClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new ExcelClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static grpc::ServerServiceDefinition BindService(ExcelBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_Parse, serviceImpl.Parse)
+          .AddMethod(__Method_Generate, serviceImpl.Generate).Build();
+    }
+
+    /// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, ExcelBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_Parse, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Palm.Lily.V1.File, global::Palm.Lily.V1.ExcelModel>(serviceImpl.Parse));
+      serviceBinder.AddMethod(__Method_Generate, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Palm.Lily.V1.ExcelModel, global::Palm.Lily.V1.File>(serviceImpl.Generate));
+    }
+
+  }
+  public static partial class Tex
+  {
+    static readonly string __ServiceName = "palm.lily.v1.Tex";
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context)
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (message is global::Google.Protobuf.IBufferMessage)
+      {
+        context.SetPayloadLength(message.CalculateSize());
+        global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter());
+        context.Complete();
+        return;
+      }
+      #endif
+      context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static class __Helper_MessageCache<T>
+    {
+      public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static T __Helper_DeserializeMessage<T>(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser<T> parser) where T : global::Google.Protobuf.IMessage<T>
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (__Helper_MessageCache<T>.IsBufferMessage)
+      {
+        return parser.ParseFrom(context.PayloadAsReadOnlySequence());
+      }
+      #endif
+      return parser.ParseFrom(context.PayloadAsNewBuffer());
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.TexToRequest> __Marshaller_palm_lily_v1_TexToRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.TexToRequest.Parser));
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.File> __Marshaller_palm_lily_v1_File = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.File.Parser));
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Method<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File> __Method_ToPdf = new grpc::Method<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "ToPdf",
+        __Marshaller_palm_lily_v1_TexToRequest,
+        __Marshaller_palm_lily_v1_File);
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Method<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File> __Method_ToWord = new grpc::Method<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "ToWord",
+        __Marshaller_palm_lily_v1_TexToRequest,
+        __Marshaller_palm_lily_v1_File);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.Services[1]; }
+    }
+
+    /// <summary>Base class for server-side implementations of Tex</summary>
+    [grpc::BindServiceMethod(typeof(Tex), "BindService")]
+    public abstract partial class TexBase
+    {
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::System.Threading.Tasks.Task<global::Palm.Lily.V1.File> ToPdf(global::Palm.Lily.V1.TexToRequest request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::System.Threading.Tasks.Task<global::Palm.Lily.V1.File> ToWord(global::Palm.Lily.V1.TexToRequest request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for Tex</summary>
+    public partial class TexClient : grpc::ClientBase<TexClient>
+    {
+      /// <summary>Creates a new client for Tex</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public TexClient(grpc::ChannelBase channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for Tex that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public TexClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected TexClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected TexClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File ToPdf(global::Palm.Lily.V1.TexToRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ToPdf(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File ToPdf(global::Palm.Lily.V1.TexToRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_ToPdf, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> ToPdfAsync(global::Palm.Lily.V1.TexToRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ToPdfAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> ToPdfAsync(global::Palm.Lily.V1.TexToRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_ToPdf, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File ToWord(global::Palm.Lily.V1.TexToRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ToWord(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File ToWord(global::Palm.Lily.V1.TexToRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_ToWord, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> ToWordAsync(global::Palm.Lily.V1.TexToRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ToWordAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> ToWordAsync(global::Palm.Lily.V1.TexToRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_ToWord, null, options, request);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected override TexClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new TexClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static grpc::ServerServiceDefinition BindService(TexBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_ToPdf, serviceImpl.ToPdf)
+          .AddMethod(__Method_ToWord, serviceImpl.ToWord).Build();
+    }
+
+    /// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, TexBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_ToPdf, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File>(serviceImpl.ToPdf));
+      serviceBinder.AddMethod(__Method_ToWord, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Palm.Lily.V1.TexToRequest, global::Palm.Lily.V1.File>(serviceImpl.ToWord));
+    }
+
+  }
+  public static partial class Epub
+  {
+    static readonly string __ServiceName = "palm.lily.v1.Epub";
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context)
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (message is global::Google.Protobuf.IBufferMessage)
+      {
+        context.SetPayloadLength(message.CalculateSize());
+        global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter());
+        context.Complete();
+        return;
+      }
+      #endif
+      context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static class __Helper_MessageCache<T>
+    {
+      public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T));
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static T __Helper_DeserializeMessage<T>(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser<T> parser) where T : global::Google.Protobuf.IMessage<T>
+    {
+      #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION
+      if (__Helper_MessageCache<T>.IsBufferMessage)
+      {
+        return parser.ParseFrom(context.PayloadAsReadOnlySequence());
+      }
+      #endif
+      return parser.ParseFrom(context.PayloadAsNewBuffer());
+    }
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.EpubBuildRequest> __Marshaller_palm_lily_v1_EpubBuildRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.EpubBuildRequest.Parser));
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Marshaller<global::Palm.Lily.V1.File> __Marshaller_palm_lily_v1_File = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Palm.Lily.V1.File.Parser));
+
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    static readonly grpc::Method<global::Palm.Lily.V1.EpubBuildRequest, global::Palm.Lily.V1.File> __Method_Build = new grpc::Method<global::Palm.Lily.V1.EpubBuildRequest, global::Palm.Lily.V1.File>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "Build",
+        __Marshaller_palm_lily_v1_EpubBuildRequest,
+        __Marshaller_palm_lily_v1_File);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Palm.Lily.V1.LilyReflection.Descriptor.Services[2]; }
+    }
+
+    /// <summary>Base class for server-side implementations of Epub</summary>
+    [grpc::BindServiceMethod(typeof(Epub), "BindService")]
+    public abstract partial class EpubBase
+    {
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::System.Threading.Tasks.Task<global::Palm.Lily.V1.File> Build(global::Palm.Lily.V1.EpubBuildRequest request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for Epub</summary>
+    public partial class EpubClient : grpc::ClientBase<EpubClient>
+    {
+      /// <summary>Creates a new client for Epub</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public EpubClient(grpc::ChannelBase channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for Epub that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public EpubClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected EpubClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected EpubClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File Build(global::Palm.Lily.V1.EpubBuildRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return Build(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual global::Palm.Lily.V1.File Build(global::Palm.Lily.V1.EpubBuildRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_Build, null, options, request);
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> BuildAsync(global::Palm.Lily.V1.EpubBuildRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return BuildAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      public virtual grpc::AsyncUnaryCall<global::Palm.Lily.V1.File> BuildAsync(global::Palm.Lily.V1.EpubBuildRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_Build, null, options, request);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+      protected override EpubClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new EpubClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static grpc::ServerServiceDefinition BindService(EpubBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_Build, serviceImpl.Build).Build();
+    }
+
+    /// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, EpubBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_Build, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Palm.Lily.V1.EpubBuildRequest, global::Palm.Lily.V1.File>(serviceImpl.Build));
+    }
+
+  }
+}
+#endregion

+ 398 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubBuildRequest.java

@@ -0,0 +1,398 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+/**
+ * Protobuf type {@code palm.lily.v1.EpubBuildRequest}
+ */
+public final class EpubBuildRequest extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:palm.lily.v1.EpubBuildRequest)
+    EpubBuildRequestOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use EpubBuildRequest.newBuilder() to construct.
+  private EpubBuildRequest(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private EpubBuildRequest() {
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new EpubBuildRequest();
+  }
+
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_EpubBuildRequest_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_EpubBuildRequest_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.class, com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.Builder.class);
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    getUnknownFields().writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    size += getUnknownFields().getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest)) {
+      return super.equals(obj);
+    }
+    com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest other = (com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest) obj;
+
+    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (29 * hash) + getUnknownFields().hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code palm.lily.v1.EpubBuildRequest}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:palm.lily.v1.EpubBuildRequest)
+      com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequestOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_EpubBuildRequest_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_EpubBuildRequest_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.class, com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.Builder.class);
+    }
+
+    // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.newBuilder()
+    private Builder() {
+
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_EpubBuildRequest_descriptor;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest getDefaultInstanceForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest build() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest buildPartial() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest result = new com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest(this);
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest) {
+        return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest other) {
+      if (other == com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.getDefaultInstance()) return this;
+      this.mergeUnknownFields(other.getUnknownFields());
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                done = true; // was an endgroup tag
+              }
+              break;
+            } // default:
+          } // switch (tag)
+        } // while (!done)
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.unwrapIOException();
+      } finally {
+        onChanged();
+      } // finally
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:palm.lily.v1.EpubBuildRequest)
+  }
+
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.EpubBuildRequest)
+  private static final com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest();
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<EpubBuildRequest>
+      PARSER = new com.google.protobuf.AbstractParser<EpubBuildRequest>() {
+    @java.lang.Override
+    public EpubBuildRequest parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (com.google.protobuf.UninitializedMessageException e) {
+        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(e)
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  };
+
+  public static com.google.protobuf.Parser<EpubBuildRequest> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<EpubBuildRequest> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 9 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubBuildRequestOrBuilder.java

@@ -0,0 +1,9 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+public interface EpubBuildRequestOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:palm.lily.v1.EpubBuildRequest)
+    com.google.protobuf.MessageOrBuilder {
+}

+ 293 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/EpubGrpc.java

@@ -0,0 +1,293 @@
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+import static io.grpc.MethodDescriptor.generateFullMethodName;
+
+/**
+ */
+@javax.annotation.Generated(
+    value = "by gRPC proto compiler (version 1.58.0)",
+    comments = "Source: lily.proto")
+@io.grpc.stub.annotations.GrpcGenerated
+public final class EpubGrpc {
+
+  private EpubGrpc() {}
+
+  public static final java.lang.String SERVICE_NAME = "palm.lily.v1.Epub";
+
+  // Static method descriptors that strictly reflect the proto.
+  private static volatile io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getBuildMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "Build",
+      requestType = com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.class,
+      responseType = com.github.saturn_xiv.palm.plugins.lily.v1.File.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getBuildMethod() {
+    io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File> getBuildMethod;
+    if ((getBuildMethod = EpubGrpc.getBuildMethod) == null) {
+      synchronized (EpubGrpc.class) {
+        if ((getBuildMethod = EpubGrpc.getBuildMethod) == null) {
+          EpubGrpc.getBuildMethod = getBuildMethod =
+              io.grpc.MethodDescriptor.<com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Build"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()))
+              .setSchemaDescriptor(new EpubMethodDescriptorSupplier("Build"))
+              .build();
+        }
+      }
+    }
+    return getBuildMethod;
+  }
+
+  /**
+   * Creates a new async stub that supports all call types for the service
+   */
+  public static EpubStub newStub(io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<EpubStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<EpubStub>() {
+        @java.lang.Override
+        public EpubStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new EpubStub(channel, callOptions);
+        }
+      };
+    return EpubStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new blocking-style stub that supports unary and streaming output calls on the service
+   */
+  public static EpubBlockingStub newBlockingStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<EpubBlockingStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<EpubBlockingStub>() {
+        @java.lang.Override
+        public EpubBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new EpubBlockingStub(channel, callOptions);
+        }
+      };
+    return EpubBlockingStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new ListenableFuture-style stub that supports unary calls on the service
+   */
+  public static EpubFutureStub newFutureStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<EpubFutureStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<EpubFutureStub>() {
+        @java.lang.Override
+        public EpubFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new EpubFutureStub(channel, callOptions);
+        }
+      };
+    return EpubFutureStub.newStub(factory, channel);
+  }
+
+  /**
+   */
+  public interface AsyncService {
+
+    /**
+     */
+    default void build(com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getBuildMethod(), responseObserver);
+    }
+  }
+
+  /**
+   * Base class for the server implementation of the service Epub.
+   */
+  public static abstract class EpubImplBase
+      implements io.grpc.BindableService, AsyncService {
+
+    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+      return EpubGrpc.bindService(this);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do asynchronous rpc calls to service Epub.
+   */
+  public static final class EpubStub
+      extends io.grpc.stub.AbstractAsyncStub<EpubStub> {
+    private EpubStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected EpubStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new EpubStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public void build(com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getBuildMethod(), getCallOptions()), request, responseObserver);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do synchronous rpc calls to service Epub.
+   */
+  public static final class EpubBlockingStub
+      extends io.grpc.stub.AbstractBlockingStub<EpubBlockingStub> {
+    private EpubBlockingStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected EpubBlockingStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new EpubBlockingStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File build(com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getBuildMethod(), getCallOptions(), request);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service Epub.
+   */
+  public static final class EpubFutureStub
+      extends io.grpc.stub.AbstractFutureStub<EpubFutureStub> {
+    private EpubFutureStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected EpubFutureStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new EpubFutureStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<com.github.saturn_xiv.palm.plugins.lily.v1.File> build(
+        com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getBuildMethod(), getCallOptions()), request);
+    }
+  }
+
+  private static final int METHODID_BUILD = 0;
+
+  private static final class MethodHandlers<Req, Resp> implements
+      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
+    private final AsyncService serviceImpl;
+    private final int methodId;
+
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
+      this.serviceImpl = serviceImpl;
+      this.methodId = methodId;
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_BUILD:
+          serviceImpl.build((com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest) request,
+              (io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File>) responseObserver);
+          break;
+        default:
+          throw new AssertionError();
+      }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver<Req> invoke(
+        io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+          getBuildMethod(),
+          io.grpc.stub.ServerCalls.asyncUnaryCall(
+            new MethodHandlers<
+              com.github.saturn_xiv.palm.plugins.lily.v1.EpubBuildRequest,
+              com.github.saturn_xiv.palm.plugins.lily.v1.File>(
+                service, METHODID_BUILD)))
+        .build();
+  }
+
+  private static abstract class EpubBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
+    EpubBaseDescriptorSupplier() {}
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.getDescriptor();
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
+      return getFileDescriptor().findServiceByName("Epub");
+    }
+  }
+
+  private static final class EpubFileDescriptorSupplier
+      extends EpubBaseDescriptorSupplier {
+    EpubFileDescriptorSupplier() {}
+  }
+
+  private static final class EpubMethodDescriptorSupplier
+      extends EpubBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
+    private final java.lang.String methodName;
+
+    EpubMethodDescriptorSupplier(java.lang.String methodName) {
+      this.methodName = methodName;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
+      return getServiceDescriptor().findMethodByName(methodName);
+    }
+  }
+
+  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
+
+  public static io.grpc.ServiceDescriptor getServiceDescriptor() {
+    io.grpc.ServiceDescriptor result = serviceDescriptor;
+    if (result == null) {
+      synchronized (EpubGrpc.class) {
+        result = serviceDescriptor;
+        if (result == null) {
+          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
+              .setSchemaDescriptor(new EpubFileDescriptorSupplier())
+              .addMethod(getBuildMethod())
+              .build();
+        }
+      }
+    }
+    return result;
+  }
+}

+ 367 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelGrpc.java

@@ -0,0 +1,367 @@
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+import static io.grpc.MethodDescriptor.generateFullMethodName;
+
+/**
+ */
+@javax.annotation.Generated(
+    value = "by gRPC proto compiler (version 1.58.0)",
+    comments = "Source: lily.proto")
+@io.grpc.stub.annotations.GrpcGenerated
+public final class ExcelGrpc {
+
+  private ExcelGrpc() {}
+
+  public static final java.lang.String SERVICE_NAME = "palm.lily.v1.Excel";
+
+  // Static method descriptors that strictly reflect the proto.
+  private static volatile io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.File,
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> getParseMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "Parse",
+      requestType = com.github.saturn_xiv.palm.plugins.lily.v1.File.class,
+      responseType = com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.File,
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> getParseMethod() {
+    io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.File, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> getParseMethod;
+    if ((getParseMethod = ExcelGrpc.getParseMethod) == null) {
+      synchronized (ExcelGrpc.class) {
+        if ((getParseMethod = ExcelGrpc.getParseMethod) == null) {
+          ExcelGrpc.getParseMethod = getParseMethod =
+              io.grpc.MethodDescriptor.<com.github.saturn_xiv.palm.plugins.lily.v1.File, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Parse"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.getDefaultInstance()))
+              .setSchemaDescriptor(new ExcelMethodDescriptorSupplier("Parse"))
+              .build();
+        }
+      }
+    }
+    return getParseMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getGenerateMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "Generate",
+      requestType = com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.class,
+      responseType = com.github.saturn_xiv.palm.plugins.lily.v1.File.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getGenerateMethod() {
+    io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel, com.github.saturn_xiv.palm.plugins.lily.v1.File> getGenerateMethod;
+    if ((getGenerateMethod = ExcelGrpc.getGenerateMethod) == null) {
+      synchronized (ExcelGrpc.class) {
+        if ((getGenerateMethod = ExcelGrpc.getGenerateMethod) == null) {
+          ExcelGrpc.getGenerateMethod = getGenerateMethod =
+              io.grpc.MethodDescriptor.<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel, com.github.saturn_xiv.palm.plugins.lily.v1.File>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Generate"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()))
+              .setSchemaDescriptor(new ExcelMethodDescriptorSupplier("Generate"))
+              .build();
+        }
+      }
+    }
+    return getGenerateMethod;
+  }
+
+  /**
+   * Creates a new async stub that supports all call types for the service
+   */
+  public static ExcelStub newStub(io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<ExcelStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<ExcelStub>() {
+        @java.lang.Override
+        public ExcelStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new ExcelStub(channel, callOptions);
+        }
+      };
+    return ExcelStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new blocking-style stub that supports unary and streaming output calls on the service
+   */
+  public static ExcelBlockingStub newBlockingStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<ExcelBlockingStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<ExcelBlockingStub>() {
+        @java.lang.Override
+        public ExcelBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new ExcelBlockingStub(channel, callOptions);
+        }
+      };
+    return ExcelBlockingStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new ListenableFuture-style stub that supports unary calls on the service
+   */
+  public static ExcelFutureStub newFutureStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<ExcelFutureStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<ExcelFutureStub>() {
+        @java.lang.Override
+        public ExcelFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new ExcelFutureStub(channel, callOptions);
+        }
+      };
+    return ExcelFutureStub.newStub(factory, channel);
+  }
+
+  /**
+   */
+  public interface AsyncService {
+
+    /**
+     */
+    default void parse(com.github.saturn_xiv.palm.plugins.lily.v1.File request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getParseMethod(), responseObserver);
+    }
+
+    /**
+     */
+    default void generate(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGenerateMethod(), responseObserver);
+    }
+  }
+
+  /**
+   * Base class for the server implementation of the service Excel.
+   */
+  public static abstract class ExcelImplBase
+      implements io.grpc.BindableService, AsyncService {
+
+    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+      return ExcelGrpc.bindService(this);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do asynchronous rpc calls to service Excel.
+   */
+  public static final class ExcelStub
+      extends io.grpc.stub.AbstractAsyncStub<ExcelStub> {
+    private ExcelStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected ExcelStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new ExcelStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public void parse(com.github.saturn_xiv.palm.plugins.lily.v1.File request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getParseMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void generate(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getGenerateMethod(), getCallOptions()), request, responseObserver);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do synchronous rpc calls to service Excel.
+   */
+  public static final class ExcelBlockingStub
+      extends io.grpc.stub.AbstractBlockingStub<ExcelBlockingStub> {
+    private ExcelBlockingStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected ExcelBlockingStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new ExcelBlockingStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parse(com.github.saturn_xiv.palm.plugins.lily.v1.File request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getParseMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File generate(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getGenerateMethod(), getCallOptions(), request);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service Excel.
+   */
+  public static final class ExcelFutureStub
+      extends io.grpc.stub.AbstractFutureStub<ExcelFutureStub> {
+    private ExcelFutureStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected ExcelFutureStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new ExcelFutureStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel> parse(
+        com.github.saturn_xiv.palm.plugins.lily.v1.File request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getParseMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<com.github.saturn_xiv.palm.plugins.lily.v1.File> generate(
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getGenerateMethod(), getCallOptions()), request);
+    }
+  }
+
+  private static final int METHODID_PARSE = 0;
+  private static final int METHODID_GENERATE = 1;
+
+  private static final class MethodHandlers<Req, Resp> implements
+      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
+    private final AsyncService serviceImpl;
+    private final int methodId;
+
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
+      this.serviceImpl = serviceImpl;
+      this.methodId = methodId;
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_PARSE:
+          serviceImpl.parse((com.github.saturn_xiv.palm.plugins.lily.v1.File) request,
+              (io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel>) responseObserver);
+          break;
+        case METHODID_GENERATE:
+          serviceImpl.generate((com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel) request,
+              (io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File>) responseObserver);
+          break;
+        default:
+          throw new AssertionError();
+      }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver<Req> invoke(
+        io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+          getParseMethod(),
+          io.grpc.stub.ServerCalls.asyncUnaryCall(
+            new MethodHandlers<
+              com.github.saturn_xiv.palm.plugins.lily.v1.File,
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel>(
+                service, METHODID_PARSE)))
+        .addMethod(
+          getGenerateMethod(),
+          io.grpc.stub.ServerCalls.asyncUnaryCall(
+            new MethodHandlers<
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel,
+              com.github.saturn_xiv.palm.plugins.lily.v1.File>(
+                service, METHODID_GENERATE)))
+        .build();
+  }
+
+  private static abstract class ExcelBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
+    ExcelBaseDescriptorSupplier() {}
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.getDescriptor();
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
+      return getFileDescriptor().findServiceByName("Excel");
+    }
+  }
+
+  private static final class ExcelFileDescriptorSupplier
+      extends ExcelBaseDescriptorSupplier {
+    ExcelFileDescriptorSupplier() {}
+  }
+
+  private static final class ExcelMethodDescriptorSupplier
+      extends ExcelBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
+    private final java.lang.String methodName;
+
+    ExcelMethodDescriptorSupplier(java.lang.String methodName) {
+      this.methodName = methodName;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
+      return getServiceDescriptor().findMethodByName(methodName);
+    }
+  }
+
+  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
+
+  public static io.grpc.ServiceDescriptor getServiceDescriptor() {
+    io.grpc.ServiceDescriptor result = serviceDescriptor;
+    if (result == null) {
+      synchronized (ExcelGrpc.class) {
+        result = serviceDescriptor;
+        if (result == null) {
+          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
+              .setSchemaDescriptor(new ExcelFileDescriptorSupplier())
+              .addMethod(getParseMethod())
+              .addMethod(getGenerateMethod())
+              .build();
+        }
+      }
+    }
+    return result;
+  }
+}

+ 2385 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelModel.java

@@ -0,0 +1,2385 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+/**
+ * Protobuf type {@code palm.lily.v1.ExcelModel}
+ */
+public final class ExcelModel extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:palm.lily.v1.ExcelModel)
+    ExcelModelOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use ExcelModel.newBuilder() to construct.
+  private ExcelModel(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private ExcelModel() {
+    sheets_ = java.util.Collections.emptyList();
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new ExcelModel();
+  }
+
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Builder.class);
+  }
+
+  public interface SheetOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:palm.lily.v1.ExcelModel.Sheet)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>string name = 1;</code>
+     * @return The name.
+     */
+    java.lang.String getName();
+    /**
+     * <code>string name = 1;</code>
+     * @return The bytes for name.
+     */
+    com.google.protobuf.ByteString
+        getNameBytes();
+
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> 
+        getCellsList();
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getCells(int index);
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    int getCellsCount();
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder> 
+        getCellsOrBuilderList();
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder getCellsOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code palm.lily.v1.ExcelModel.Sheet}
+   */
+  public static final class Sheet extends
+      com.google.protobuf.GeneratedMessageV3 implements
+      // @@protoc_insertion_point(message_implements:palm.lily.v1.ExcelModel.Sheet)
+      SheetOrBuilder {
+  private static final long serialVersionUID = 0L;
+    // Use Sheet.newBuilder() to construct.
+    private Sheet(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+    private Sheet() {
+      name_ = "";
+      cells_ = java.util.Collections.emptyList();
+    }
+
+    @java.lang.Override
+    @SuppressWarnings({"unused"})
+    protected java.lang.Object newInstance(
+        UnusedPrivateParameter unused) {
+      return new Sheet();
+    }
+
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder.class);
+    }
+
+    public interface CellOrBuilder extends
+        // @@protoc_insertion_point(interface_extends:palm.lily.v1.ExcelModel.Sheet.Cell)
+        com.google.protobuf.MessageOrBuilder {
+
+      /**
+       * <code>uint32 row = 1;</code>
+       * @return The row.
+       */
+      int getRow();
+
+      /**
+       * <code>uint32 col = 2;</code>
+       * @return The col.
+       */
+      int getCol();
+
+      /**
+       * <code>string val = 3;</code>
+       * @return The val.
+       */
+      java.lang.String getVal();
+      /**
+       * <code>string val = 3;</code>
+       * @return The bytes for val.
+       */
+      com.google.protobuf.ByteString
+          getValBytes();
+    }
+    /**
+     * Protobuf type {@code palm.lily.v1.ExcelModel.Sheet.Cell}
+     */
+    public static final class Cell extends
+        com.google.protobuf.GeneratedMessageV3 implements
+        // @@protoc_insertion_point(message_implements:palm.lily.v1.ExcelModel.Sheet.Cell)
+        CellOrBuilder {
+    private static final long serialVersionUID = 0L;
+      // Use Cell.newBuilder() to construct.
+      private Cell(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+        super(builder);
+      }
+      private Cell() {
+        val_ = "";
+      }
+
+      @java.lang.Override
+      @SuppressWarnings({"unused"})
+      protected java.lang.Object newInstance(
+          UnusedPrivateParameter unused) {
+        return new Cell();
+      }
+
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder.class);
+      }
+
+      public static final int ROW_FIELD_NUMBER = 1;
+      private int row_ = 0;
+      /**
+       * <code>uint32 row = 1;</code>
+       * @return The row.
+       */
+      @java.lang.Override
+      public int getRow() {
+        return row_;
+      }
+
+      public static final int COL_FIELD_NUMBER = 2;
+      private int col_ = 0;
+      /**
+       * <code>uint32 col = 2;</code>
+       * @return The col.
+       */
+      @java.lang.Override
+      public int getCol() {
+        return col_;
+      }
+
+      public static final int VAL_FIELD_NUMBER = 3;
+      @SuppressWarnings("serial")
+      private volatile java.lang.Object val_ = "";
+      /**
+       * <code>string val = 3;</code>
+       * @return The val.
+       */
+      @java.lang.Override
+      public java.lang.String getVal() {
+        java.lang.Object ref = val_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          val_ = s;
+          return s;
+        }
+      }
+      /**
+       * <code>string val = 3;</code>
+       * @return The bytes for val.
+       */
+      @java.lang.Override
+      public com.google.protobuf.ByteString
+          getValBytes() {
+        java.lang.Object ref = val_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          val_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      private byte memoizedIsInitialized = -1;
+      @java.lang.Override
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized == 1) return true;
+        if (isInitialized == 0) return false;
+
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      @java.lang.Override
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        if (row_ != 0) {
+          output.writeUInt32(1, row_);
+        }
+        if (col_ != 0) {
+          output.writeUInt32(2, col_);
+        }
+        if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(val_)) {
+          com.google.protobuf.GeneratedMessageV3.writeString(output, 3, val_);
+        }
+        getUnknownFields().writeTo(output);
+      }
+
+      @java.lang.Override
+      public int getSerializedSize() {
+        int size = memoizedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        if (row_ != 0) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeUInt32Size(1, row_);
+        }
+        if (col_ != 0) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeUInt32Size(2, col_);
+        }
+        if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(val_)) {
+          size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, val_);
+        }
+        size += getUnknownFields().getSerializedSize();
+        memoizedSize = size;
+        return size;
+      }
+
+      @java.lang.Override
+      public boolean equals(final java.lang.Object obj) {
+        if (obj == this) {
+         return true;
+        }
+        if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell)) {
+          return super.equals(obj);
+        }
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell other = (com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell) obj;
+
+        if (getRow()
+            != other.getRow()) return false;
+        if (getCol()
+            != other.getCol()) return false;
+        if (!getVal()
+            .equals(other.getVal())) return false;
+        if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+        return true;
+      }
+
+      @java.lang.Override
+      public int hashCode() {
+        if (memoizedHashCode != 0) {
+          return memoizedHashCode;
+        }
+        int hash = 41;
+        hash = (19 * hash) + getDescriptor().hashCode();
+        hash = (37 * hash) + ROW_FIELD_NUMBER;
+        hash = (53 * hash) + getRow();
+        hash = (37 * hash) + COL_FIELD_NUMBER;
+        hash = (53 * hash) + getCol();
+        hash = (37 * hash) + VAL_FIELD_NUMBER;
+        hash = (53 * hash) + getVal().hashCode();
+        hash = (29 * hash) + getUnknownFields().hashCode();
+        memoizedHashCode = hash;
+        return hash;
+      }
+
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          java.nio.ByteBuffer data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          java.nio.ByteBuffer data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseWithIOException(PARSER, input);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseWithIOException(PARSER, input, extensionRegistry);
+      }
+
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseDelimitedWithIOException(PARSER, input);
+      }
+
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseWithIOException(PARSER, input);
+      }
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return com.google.protobuf.GeneratedMessageV3
+            .parseWithIOException(PARSER, input, extensionRegistry);
+      }
+
+      @java.lang.Override
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder() {
+        return DEFAULT_INSTANCE.toBuilder();
+      }
+      public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell prototype) {
+        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+      }
+      @java.lang.Override
+      public Builder toBuilder() {
+        return this == DEFAULT_INSTANCE
+            ? new Builder() : new Builder().mergeFrom(this);
+      }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code palm.lily.v1.ExcelModel.Sheet.Cell}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+          // @@protoc_insertion_point(builder_implements:palm.lily.v1.ExcelModel.Sheet.Cell)
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor;
+        }
+
+        @java.lang.Override
+        protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder.class);
+        }
+
+        // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.newBuilder()
+        private Builder() {
+
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+          super(parent);
+
+        }
+        @java.lang.Override
+        public Builder clear() {
+          super.clear();
+          bitField0_ = 0;
+          row_ = 0;
+          col_ = 0;
+          val_ = "";
+          return this;
+        }
+
+        @java.lang.Override
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor;
+        }
+
+        @java.lang.Override
+        public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getDefaultInstanceForType() {
+          return com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.getDefaultInstance();
+        }
+
+        @java.lang.Override
+        public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell build() {
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        @java.lang.Override
+        public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell buildPartial() {
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell result = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell(this);
+          if (bitField0_ != 0) { buildPartial0(result); }
+          onBuilt();
+          return result;
+        }
+
+        private void buildPartial0(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell result) {
+          int from_bitField0_ = bitField0_;
+          if (((from_bitField0_ & 0x00000001) != 0)) {
+            result.row_ = row_;
+          }
+          if (((from_bitField0_ & 0x00000002) != 0)) {
+            result.col_ = col_;
+          }
+          if (((from_bitField0_ & 0x00000004) != 0)) {
+            result.val_ = val_;
+          }
+        }
+
+        @java.lang.Override
+        public Builder clone() {
+          return super.clone();
+        }
+        @java.lang.Override
+        public Builder setField(
+            com.google.protobuf.Descriptors.FieldDescriptor field,
+            java.lang.Object value) {
+          return super.setField(field, value);
+        }
+        @java.lang.Override
+        public Builder clearField(
+            com.google.protobuf.Descriptors.FieldDescriptor field) {
+          return super.clearField(field);
+        }
+        @java.lang.Override
+        public Builder clearOneof(
+            com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+          return super.clearOneof(oneof);
+        }
+        @java.lang.Override
+        public Builder setRepeatedField(
+            com.google.protobuf.Descriptors.FieldDescriptor field,
+            int index, java.lang.Object value) {
+          return super.setRepeatedField(field, index, value);
+        }
+        @java.lang.Override
+        public Builder addRepeatedField(
+            com.google.protobuf.Descriptors.FieldDescriptor field,
+            java.lang.Object value) {
+          return super.addRepeatedField(field, value);
+        }
+        @java.lang.Override
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell) {
+            return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell other) {
+          if (other == com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.getDefaultInstance()) return this;
+          if (other.getRow() != 0) {
+            setRow(other.getRow());
+          }
+          if (other.getCol() != 0) {
+            setCol(other.getCol());
+          }
+          if (!other.getVal().isEmpty()) {
+            val_ = other.val_;
+            bitField0_ |= 0x00000004;
+            onChanged();
+          }
+          this.mergeUnknownFields(other.getUnknownFields());
+          onChanged();
+          return this;
+        }
+
+        @java.lang.Override
+        public final boolean isInitialized() {
+          return true;
+        }
+
+        @java.lang.Override
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          if (extensionRegistry == null) {
+            throw new java.lang.NullPointerException();
+          }
+          try {
+            boolean done = false;
+            while (!done) {
+              int tag = input.readTag();
+              switch (tag) {
+                case 0:
+                  done = true;
+                  break;
+                case 8: {
+                  row_ = input.readUInt32();
+                  bitField0_ |= 0x00000001;
+                  break;
+                } // case 8
+                case 16: {
+                  col_ = input.readUInt32();
+                  bitField0_ |= 0x00000002;
+                  break;
+                } // case 16
+                case 26: {
+                  val_ = input.readStringRequireUtf8();
+                  bitField0_ |= 0x00000004;
+                  break;
+                } // case 26
+                default: {
+                  if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                    done = true; // was an endgroup tag
+                  }
+                  break;
+                } // default:
+              } // switch (tag)
+            } // while (!done)
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            throw e.unwrapIOException();
+          } finally {
+            onChanged();
+          } // finally
+          return this;
+        }
+        private int bitField0_;
+
+        private int row_ ;
+        /**
+         * <code>uint32 row = 1;</code>
+         * @return The row.
+         */
+        @java.lang.Override
+        public int getRow() {
+          return row_;
+        }
+        /**
+         * <code>uint32 row = 1;</code>
+         * @param value The row to set.
+         * @return This builder for chaining.
+         */
+        public Builder setRow(int value) {
+
+          row_ = value;
+          bitField0_ |= 0x00000001;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>uint32 row = 1;</code>
+         * @return This builder for chaining.
+         */
+        public Builder clearRow() {
+          bitField0_ = (bitField0_ & ~0x00000001);
+          row_ = 0;
+          onChanged();
+          return this;
+        }
+
+        private int col_ ;
+        /**
+         * <code>uint32 col = 2;</code>
+         * @return The col.
+         */
+        @java.lang.Override
+        public int getCol() {
+          return col_;
+        }
+        /**
+         * <code>uint32 col = 2;</code>
+         * @param value The col to set.
+         * @return This builder for chaining.
+         */
+        public Builder setCol(int value) {
+
+          col_ = value;
+          bitField0_ |= 0x00000002;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>uint32 col = 2;</code>
+         * @return This builder for chaining.
+         */
+        public Builder clearCol() {
+          bitField0_ = (bitField0_ & ~0x00000002);
+          col_ = 0;
+          onChanged();
+          return this;
+        }
+
+        private java.lang.Object val_ = "";
+        /**
+         * <code>string val = 3;</code>
+         * @return The val.
+         */
+        public java.lang.String getVal() {
+          java.lang.Object ref = val_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            val_ = s;
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>string val = 3;</code>
+         * @return The bytes for val.
+         */
+        public com.google.protobuf.ByteString
+            getValBytes() {
+          java.lang.Object ref = val_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            val_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>string val = 3;</code>
+         * @param value The val to set.
+         * @return This builder for chaining.
+         */
+        public Builder setVal(
+            java.lang.String value) {
+          if (value == null) { throw new NullPointerException(); }
+          val_ = value;
+          bitField0_ |= 0x00000004;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>string val = 3;</code>
+         * @return This builder for chaining.
+         */
+        public Builder clearVal() {
+          val_ = getDefaultInstance().getVal();
+          bitField0_ = (bitField0_ & ~0x00000004);
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>string val = 3;</code>
+         * @param value The bytes for val to set.
+         * @return This builder for chaining.
+         */
+        public Builder setValBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) { throw new NullPointerException(); }
+          checkByteStringIsUtf8(value);
+          val_ = value;
+          bitField0_ |= 0x00000004;
+          onChanged();
+          return this;
+        }
+        @java.lang.Override
+        public final Builder setUnknownFields(
+            final com.google.protobuf.UnknownFieldSet unknownFields) {
+          return super.setUnknownFields(unknownFields);
+        }
+
+        @java.lang.Override
+        public final Builder mergeUnknownFields(
+            final com.google.protobuf.UnknownFieldSet unknownFields) {
+          return super.mergeUnknownFields(unknownFields);
+        }
+
+
+        // @@protoc_insertion_point(builder_scope:palm.lily.v1.ExcelModel.Sheet.Cell)
+      }
+
+      // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel.Sheet.Cell)
+      private static final com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell DEFAULT_INSTANCE;
+      static {
+        DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell();
+      }
+
+      public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getDefaultInstance() {
+        return DEFAULT_INSTANCE;
+      }
+
+      private static final com.google.protobuf.Parser<Cell>
+          PARSER = new com.google.protobuf.AbstractParser<Cell>() {
+        @java.lang.Override
+        public Cell parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          Builder builder = newBuilder();
+          try {
+            builder.mergeFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            throw e.setUnfinishedMessage(builder.buildPartial());
+          } catch (com.google.protobuf.UninitializedMessageException e) {
+            throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+          } catch (java.io.IOException e) {
+            throw new com.google.protobuf.InvalidProtocolBufferException(e)
+                .setUnfinishedMessage(builder.buildPartial());
+          }
+          return builder.buildPartial();
+        }
+      };
+
+      public static com.google.protobuf.Parser<Cell> parser() {
+        return PARSER;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<Cell> getParserForType() {
+        return PARSER;
+      }
+
+      @java.lang.Override
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getDefaultInstanceForType() {
+        return DEFAULT_INSTANCE;
+      }
+
+    }
+
+    public static final int NAME_FIELD_NUMBER = 1;
+    @SuppressWarnings("serial")
+    private volatile java.lang.Object name_ = "";
+    /**
+     * <code>string name = 1;</code>
+     * @return The name.
+     */
+    @java.lang.Override
+    public java.lang.String getName() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        name_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string name = 1;</code>
+     * @return The bytes for name.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getNameBytes() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        name_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CELLS_FIELD_NUMBER = 2;
+    @SuppressWarnings("serial")
+    private java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> cells_;
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    @java.lang.Override
+    public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> getCellsList() {
+      return cells_;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    @java.lang.Override
+    public java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder> 
+        getCellsOrBuilderList() {
+      return cells_;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    @java.lang.Override
+    public int getCellsCount() {
+      return cells_.size();
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getCells(int index) {
+      return cells_.get(index);
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder getCellsOrBuilder(
+        int index) {
+      return cells_.get(index);
+    }
+
+    private byte memoizedIsInitialized = -1;
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_);
+      }
+      for (int i = 0; i < cells_.size(); i++) {
+        output.writeMessage(2, cells_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_);
+      }
+      for (int i = 0; i < cells_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, cells_.get(i));
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet)) {
+        return super.equals(obj);
+      }
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet other = (com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet) obj;
+
+      if (!getName()
+          .equals(other.getName())) return false;
+      if (!getCellsList()
+          .equals(other.getCellsList())) return false;
+      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      hash = (37 * hash) + NAME_FIELD_NUMBER;
+      hash = (53 * hash) + getName().hashCode();
+      if (getCellsCount() > 0) {
+        hash = (37 * hash) + CELLS_FIELD_NUMBER;
+        hash = (53 * hash) + getCellsList().hashCode();
+      }
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        java.nio.ByteBuffer data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input);
+    }
+
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code palm.lily.v1.ExcelModel.Sheet}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:palm.lily.v1.ExcelModel.Sheet)
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder.class);
+      }
+
+      // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.newBuilder()
+      private Builder() {
+
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        bitField0_ = 0;
+        name_ = "";
+        if (cellsBuilder_ == null) {
+          cells_ = java.util.Collections.emptyList();
+        } else {
+          cells_ = null;
+          cellsBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000002);
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor;
+      }
+
+      @java.lang.Override
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getDefaultInstanceForType() {
+        return com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet build() {
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet buildPartial() {
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet result = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet(this);
+        buildPartialRepeatedFields(result);
+        if (bitField0_ != 0) { buildPartial0(result); }
+        onBuilt();
+        return result;
+      }
+
+      private void buildPartialRepeatedFields(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet result) {
+        if (cellsBuilder_ == null) {
+          if (((bitField0_ & 0x00000002) != 0)) {
+            cells_ = java.util.Collections.unmodifiableList(cells_);
+            bitField0_ = (bitField0_ & ~0x00000002);
+          }
+          result.cells_ = cells_;
+        } else {
+          result.cells_ = cellsBuilder_.build();
+        }
+      }
+
+      private void buildPartial0(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet result) {
+        int from_bitField0_ = bitField0_;
+        if (((from_bitField0_ & 0x00000001) != 0)) {
+          result.name_ = name_;
+        }
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.setField(field, value);
+      }
+      @java.lang.Override
+      public Builder clearField(
+          com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+      @java.lang.Override
+      public Builder clearOneof(
+          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index, java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet) {
+          return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet other) {
+        if (other == com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.getDefaultInstance()) return this;
+        if (!other.getName().isEmpty()) {
+          name_ = other.name_;
+          bitField0_ |= 0x00000001;
+          onChanged();
+        }
+        if (cellsBuilder_ == null) {
+          if (!other.cells_.isEmpty()) {
+            if (cells_.isEmpty()) {
+              cells_ = other.cells_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+            } else {
+              ensureCellsIsMutable();
+              cells_.addAll(other.cells_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.cells_.isEmpty()) {
+            if (cellsBuilder_.isEmpty()) {
+              cellsBuilder_.dispose();
+              cellsBuilder_ = null;
+              cells_ = other.cells_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+              cellsBuilder_ = 
+                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                   getCellsFieldBuilder() : null;
+            } else {
+              cellsBuilder_.addAllMessages(other.cells_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        if (extensionRegistry == null) {
+          throw new java.lang.NullPointerException();
+        }
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              case 10: {
+                name_ = input.readStringRequireUtf8();
+                bitField0_ |= 0x00000001;
+                break;
+              } // case 10
+              case 18: {
+                com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell m =
+                    input.readMessage(
+                        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.parser(),
+                        extensionRegistry);
+                if (cellsBuilder_ == null) {
+                  ensureCellsIsMutable();
+                  cells_.add(m);
+                } else {
+                  cellsBuilder_.addMessage(m);
+                }
+                break;
+              } // case 18
+              default: {
+                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                  done = true; // was an endgroup tag
+                }
+                break;
+              } // default:
+            } // switch (tag)
+          } // while (!done)
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw e.unwrapIOException();
+        } finally {
+          onChanged();
+        } // finally
+        return this;
+      }
+      private int bitField0_;
+
+      private java.lang.Object name_ = "";
+      /**
+       * <code>string name = 1;</code>
+       * @return The name.
+       */
+      public java.lang.String getName() {
+        java.lang.Object ref = name_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          name_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string name = 1;</code>
+       * @return The bytes for name.
+       */
+      public com.google.protobuf.ByteString
+          getNameBytes() {
+        java.lang.Object ref = name_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          name_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string name = 1;</code>
+       * @param value The name to set.
+       * @return This builder for chaining.
+       */
+      public Builder setName(
+          java.lang.String value) {
+        if (value == null) { throw new NullPointerException(); }
+        name_ = value;
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string name = 1;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearName() {
+        name_ = getDefaultInstance().getName();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string name = 1;</code>
+       * @param value The bytes for name to set.
+       * @return This builder for chaining.
+       */
+      public Builder setNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) { throw new NullPointerException(); }
+        checkByteStringIsUtf8(value);
+        name_ = value;
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return this;
+      }
+
+      private java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> cells_ =
+        java.util.Collections.emptyList();
+      private void ensureCellsIsMutable() {
+        if (!((bitField0_ & 0x00000002) != 0)) {
+          cells_ = new java.util.ArrayList<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell>(cells_);
+          bitField0_ |= 0x00000002;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder> cellsBuilder_;
+
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> getCellsList() {
+        if (cellsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(cells_);
+        } else {
+          return cellsBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public int getCellsCount() {
+        if (cellsBuilder_ == null) {
+          return cells_.size();
+        } else {
+          return cellsBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell getCells(int index) {
+        if (cellsBuilder_ == null) {
+          return cells_.get(index);
+        } else {
+          return cellsBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder setCells(
+          int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell value) {
+        if (cellsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureCellsIsMutable();
+          cells_.set(index, value);
+          onChanged();
+        } else {
+          cellsBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder setCells(
+          int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder builderForValue) {
+        if (cellsBuilder_ == null) {
+          ensureCellsIsMutable();
+          cells_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          cellsBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder addCells(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell value) {
+        if (cellsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureCellsIsMutable();
+          cells_.add(value);
+          onChanged();
+        } else {
+          cellsBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder addCells(
+          int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell value) {
+        if (cellsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureCellsIsMutable();
+          cells_.add(index, value);
+          onChanged();
+        } else {
+          cellsBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder addCells(
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder builderForValue) {
+        if (cellsBuilder_ == null) {
+          ensureCellsIsMutable();
+          cells_.add(builderForValue.build());
+          onChanged();
+        } else {
+          cellsBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder addCells(
+          int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder builderForValue) {
+        if (cellsBuilder_ == null) {
+          ensureCellsIsMutable();
+          cells_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          cellsBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder addAllCells(
+          java.lang.Iterable<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell> values) {
+        if (cellsBuilder_ == null) {
+          ensureCellsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, cells_);
+          onChanged();
+        } else {
+          cellsBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder clearCells() {
+        if (cellsBuilder_ == null) {
+          cells_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+          onChanged();
+        } else {
+          cellsBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public Builder removeCells(int index) {
+        if (cellsBuilder_ == null) {
+          ensureCellsIsMutable();
+          cells_.remove(index);
+          onChanged();
+        } else {
+          cellsBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder getCellsBuilder(
+          int index) {
+        return getCellsFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder getCellsOrBuilder(
+          int index) {
+        if (cellsBuilder_ == null) {
+          return cells_.get(index);  } else {
+          return cellsBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder> 
+           getCellsOrBuilderList() {
+        if (cellsBuilder_ != null) {
+          return cellsBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(cells_);
+        }
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder addCellsBuilder() {
+        return getCellsFieldBuilder().addBuilder(
+            com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder addCellsBuilder(
+          int index) {
+        return getCellsFieldBuilder().addBuilder(
+            index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+       */
+      public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder> 
+           getCellsBuilderList() {
+        return getCellsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder> 
+          getCellsFieldBuilder() {
+        if (cellsBuilder_ == null) {
+          cellsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Cell.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.CellOrBuilder>(
+                  cells_,
+                  ((bitField0_ & 0x00000002) != 0),
+                  getParentForChildren(),
+                  isClean());
+          cells_ = null;
+        }
+        return cellsBuilder_;
+      }
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
+      }
+
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:palm.lily.v1.ExcelModel.Sheet)
+    }
+
+    // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel.Sheet)
+    private static final com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet();
+    }
+
+    public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<Sheet>
+        PARSER = new com.google.protobuf.AbstractParser<Sheet>() {
+      @java.lang.Override
+      public Sheet parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        Builder builder = newBuilder();
+        try {
+          builder.mergeFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(builder.buildPartial());
+        } catch (com.google.protobuf.UninitializedMessageException e) {
+          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+        } catch (java.io.IOException e) {
+          throw new com.google.protobuf.InvalidProtocolBufferException(e)
+              .setUnfinishedMessage(builder.buildPartial());
+        }
+        return builder.buildPartial();
+      }
+    };
+
+    public static com.google.protobuf.Parser<Sheet> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Sheet> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  public static final int SHEETS_FIELD_NUMBER = 1;
+  @SuppressWarnings("serial")
+  private java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> sheets_;
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  @java.lang.Override
+  public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> getSheetsList() {
+    return sheets_;
+  }
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  @java.lang.Override
+  public java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder> 
+      getSheetsOrBuilderList() {
+    return sheets_;
+  }
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  @java.lang.Override
+  public int getSheetsCount() {
+    return sheets_.size();
+  }
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getSheets(int index) {
+    return sheets_.get(index);
+  }
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder getSheetsOrBuilder(
+      int index) {
+    return sheets_.get(index);
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    for (int i = 0; i < sheets_.size(); i++) {
+      output.writeMessage(1, sheets_.get(i));
+    }
+    getUnknownFields().writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    for (int i = 0; i < sheets_.size(); i++) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(1, sheets_.get(i));
+    }
+    size += getUnknownFields().getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel)) {
+      return super.equals(obj);
+    }
+    com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel other = (com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel) obj;
+
+    if (!getSheetsList()
+        .equals(other.getSheetsList())) return false;
+    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    if (getSheetsCount() > 0) {
+      hash = (37 * hash) + SHEETS_FIELD_NUMBER;
+      hash = (53 * hash) + getSheetsList().hashCode();
+    }
+    hash = (29 * hash) + getUnknownFields().hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code palm.lily.v1.ExcelModel}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:palm.lily.v1.ExcelModel)
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModelOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.class, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Builder.class);
+    }
+
+    // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.newBuilder()
+    private Builder() {
+
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      bitField0_ = 0;
+      if (sheetsBuilder_ == null) {
+        sheets_ = java.util.Collections.emptyList();
+      } else {
+        sheets_ = null;
+        sheetsBuilder_.clear();
+      }
+      bitField0_ = (bitField0_ & ~0x00000001);
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_ExcelModel_descriptor;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel getDefaultInstanceForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel build() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel buildPartial() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel result = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel(this);
+      buildPartialRepeatedFields(result);
+      if (bitField0_ != 0) { buildPartial0(result); }
+      onBuilt();
+      return result;
+    }
+
+    private void buildPartialRepeatedFields(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel result) {
+      if (sheetsBuilder_ == null) {
+        if (((bitField0_ & 0x00000001) != 0)) {
+          sheets_ = java.util.Collections.unmodifiableList(sheets_);
+          bitField0_ = (bitField0_ & ~0x00000001);
+        }
+        result.sheets_ = sheets_;
+      } else {
+        result.sheets_ = sheetsBuilder_.build();
+      }
+    }
+
+    private void buildPartial0(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel result) {
+      int from_bitField0_ = bitField0_;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel) {
+        return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel other) {
+      if (other == com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.getDefaultInstance()) return this;
+      if (sheetsBuilder_ == null) {
+        if (!other.sheets_.isEmpty()) {
+          if (sheets_.isEmpty()) {
+            sheets_ = other.sheets_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureSheetsIsMutable();
+            sheets_.addAll(other.sheets_);
+          }
+          onChanged();
+        }
+      } else {
+        if (!other.sheets_.isEmpty()) {
+          if (sheetsBuilder_.isEmpty()) {
+            sheetsBuilder_.dispose();
+            sheetsBuilder_ = null;
+            sheets_ = other.sheets_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+            sheetsBuilder_ = 
+              com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                 getSheetsFieldBuilder() : null;
+          } else {
+            sheetsBuilder_.addAllMessages(other.sheets_);
+          }
+        }
+      }
+      this.mergeUnknownFields(other.getUnknownFields());
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 10: {
+              com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet m =
+                  input.readMessage(
+                      com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.parser(),
+                      extensionRegistry);
+              if (sheetsBuilder_ == null) {
+                ensureSheetsIsMutable();
+                sheets_.add(m);
+              } else {
+                sheetsBuilder_.addMessage(m);
+              }
+              break;
+            } // case 10
+            default: {
+              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                done = true; // was an endgroup tag
+              }
+              break;
+            } // default:
+          } // switch (tag)
+        } // while (!done)
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.unwrapIOException();
+      } finally {
+        onChanged();
+      } // finally
+      return this;
+    }
+    private int bitField0_;
+
+    private java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> sheets_ =
+      java.util.Collections.emptyList();
+    private void ensureSheetsIsMutable() {
+      if (!((bitField0_ & 0x00000001) != 0)) {
+        sheets_ = new java.util.ArrayList<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet>(sheets_);
+        bitField0_ |= 0x00000001;
+       }
+    }
+
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder> sheetsBuilder_;
+
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> getSheetsList() {
+      if (sheetsBuilder_ == null) {
+        return java.util.Collections.unmodifiableList(sheets_);
+      } else {
+        return sheetsBuilder_.getMessageList();
+      }
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public int getSheetsCount() {
+      if (sheetsBuilder_ == null) {
+        return sheets_.size();
+      } else {
+        return sheetsBuilder_.getCount();
+      }
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getSheets(int index) {
+      if (sheetsBuilder_ == null) {
+        return sheets_.get(index);
+      } else {
+        return sheetsBuilder_.getMessage(index);
+      }
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder setSheets(
+        int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet value) {
+      if (sheetsBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureSheetsIsMutable();
+        sheets_.set(index, value);
+        onChanged();
+      } else {
+        sheetsBuilder_.setMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder setSheets(
+        int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder builderForValue) {
+      if (sheetsBuilder_ == null) {
+        ensureSheetsIsMutable();
+        sheets_.set(index, builderForValue.build());
+        onChanged();
+      } else {
+        sheetsBuilder_.setMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder addSheets(com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet value) {
+      if (sheetsBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureSheetsIsMutable();
+        sheets_.add(value);
+        onChanged();
+      } else {
+        sheetsBuilder_.addMessage(value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder addSheets(
+        int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet value) {
+      if (sheetsBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureSheetsIsMutable();
+        sheets_.add(index, value);
+        onChanged();
+      } else {
+        sheetsBuilder_.addMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder addSheets(
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder builderForValue) {
+      if (sheetsBuilder_ == null) {
+        ensureSheetsIsMutable();
+        sheets_.add(builderForValue.build());
+        onChanged();
+      } else {
+        sheetsBuilder_.addMessage(builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder addSheets(
+        int index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder builderForValue) {
+      if (sheetsBuilder_ == null) {
+        ensureSheetsIsMutable();
+        sheets_.add(index, builderForValue.build());
+        onChanged();
+      } else {
+        sheetsBuilder_.addMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder addAllSheets(
+        java.lang.Iterable<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> values) {
+      if (sheetsBuilder_ == null) {
+        ensureSheetsIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, sheets_);
+        onChanged();
+      } else {
+        sheetsBuilder_.addAllMessages(values);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder clearSheets() {
+      if (sheetsBuilder_ == null) {
+        sheets_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+      } else {
+        sheetsBuilder_.clear();
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public Builder removeSheets(int index) {
+      if (sheetsBuilder_ == null) {
+        ensureSheetsIsMutable();
+        sheets_.remove(index);
+        onChanged();
+      } else {
+        sheetsBuilder_.remove(index);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder getSheetsBuilder(
+        int index) {
+      return getSheetsFieldBuilder().getBuilder(index);
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder getSheetsOrBuilder(
+        int index) {
+      if (sheetsBuilder_ == null) {
+        return sheets_.get(index);  } else {
+        return sheetsBuilder_.getMessageOrBuilder(index);
+      }
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder> 
+         getSheetsOrBuilderList() {
+      if (sheetsBuilder_ != null) {
+        return sheetsBuilder_.getMessageOrBuilderList();
+      } else {
+        return java.util.Collections.unmodifiableList(sheets_);
+      }
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder addSheetsBuilder() {
+      return getSheetsFieldBuilder().addBuilder(
+          com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder addSheetsBuilder(
+        int index) {
+      return getSheetsFieldBuilder().addBuilder(
+          index, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    public java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder> 
+         getSheetsBuilderList() {
+      return getSheetsFieldBuilder().getBuilderList();
+    }
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder> 
+        getSheetsFieldBuilder() {
+      if (sheetsBuilder_ == null) {
+        sheetsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+            com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet.Builder, com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder>(
+                sheets_,
+                ((bitField0_ & 0x00000001) != 0),
+                getParentForChildren(),
+                isClean());
+        sheets_ = null;
+      }
+      return sheetsBuilder_;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:palm.lily.v1.ExcelModel)
+  }
+
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.ExcelModel)
+  private static final com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel();
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<ExcelModel>
+      PARSER = new com.google.protobuf.AbstractParser<ExcelModel>() {
+    @java.lang.Override
+    public ExcelModel parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (com.google.protobuf.UninitializedMessageException e) {
+        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(e)
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  };
+
+  public static com.google.protobuf.Parser<ExcelModel> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<ExcelModel> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 33 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/ExcelModelOrBuilder.java

@@ -0,0 +1,33 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+public interface ExcelModelOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:palm.lily.v1.ExcelModel)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  java.util.List<com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet> 
+      getSheetsList();
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.Sheet getSheets(int index);
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  int getSheetsCount();
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  java.util.List<? extends com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder> 
+      getSheetsOrBuilderList();
+  /**
+   * <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+   */
+  com.github.saturn_xiv.palm.plugins.lily.v1.ExcelModel.SheetOrBuilder getSheetsOrBuilder(
+      int index);
+}

+ 632 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/File.java

@@ -0,0 +1,632 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+/**
+ * Protobuf type {@code palm.lily.v1.File}
+ */
+public final class File extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:palm.lily.v1.File)
+    FileOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use File.newBuilder() to construct.
+  private File(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private File() {
+    contentType_ = "";
+    payload_ = com.google.protobuf.ByteString.EMPTY;
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new File();
+  }
+
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_File_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_File_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.github.saturn_xiv.palm.plugins.lily.v1.File.class, com.github.saturn_xiv.palm.plugins.lily.v1.File.Builder.class);
+  }
+
+  private int bitField0_;
+  public static final int CONTENT_TYPE_FIELD_NUMBER = 1;
+  @SuppressWarnings("serial")
+  private volatile java.lang.Object contentType_ = "";
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return Whether the contentType field is set.
+   */
+  @java.lang.Override
+  public boolean hasContentType() {
+    return ((bitField0_ & 0x00000001) != 0);
+  }
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return The contentType.
+   */
+  @java.lang.Override
+  public java.lang.String getContentType() {
+    java.lang.Object ref = contentType_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      contentType_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return The bytes for contentType.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getContentTypeBytes() {
+    java.lang.Object ref = contentType_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      contentType_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int PAYLOAD_FIELD_NUMBER = 2;
+  private com.google.protobuf.ByteString payload_ = com.google.protobuf.ByteString.EMPTY;
+  /**
+   * <code>bytes payload = 2;</code>
+   * @return The payload.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getPayload() {
+    return payload_;
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (((bitField0_ & 0x00000001) != 0)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, contentType_);
+    }
+    if (!payload_.isEmpty()) {
+      output.writeBytes(2, payload_);
+    }
+    getUnknownFields().writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (((bitField0_ & 0x00000001) != 0)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, contentType_);
+    }
+    if (!payload_.isEmpty()) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeBytesSize(2, payload_);
+    }
+    size += getUnknownFields().getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.File)) {
+      return super.equals(obj);
+    }
+    com.github.saturn_xiv.palm.plugins.lily.v1.File other = (com.github.saturn_xiv.palm.plugins.lily.v1.File) obj;
+
+    if (hasContentType() != other.hasContentType()) return false;
+    if (hasContentType()) {
+      if (!getContentType()
+          .equals(other.getContentType())) return false;
+    }
+    if (!getPayload()
+        .equals(other.getPayload())) return false;
+    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    if (hasContentType()) {
+      hash = (37 * hash) + CONTENT_TYPE_FIELD_NUMBER;
+      hash = (53 * hash) + getContentType().hashCode();
+    }
+    hash = (37 * hash) + PAYLOAD_FIELD_NUMBER;
+    hash = (53 * hash) + getPayload().hashCode();
+    hash = (29 * hash) + getUnknownFields().hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.File prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code palm.lily.v1.File}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:palm.lily.v1.File)
+      com.github.saturn_xiv.palm.plugins.lily.v1.FileOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_File_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_File_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.github.saturn_xiv.palm.plugins.lily.v1.File.class, com.github.saturn_xiv.palm.plugins.lily.v1.File.Builder.class);
+    }
+
+    // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.File.newBuilder()
+    private Builder() {
+
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      bitField0_ = 0;
+      contentType_ = "";
+      payload_ = com.google.protobuf.ByteString.EMPTY;
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_File_descriptor;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File getDefaultInstanceForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File build() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.File result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File buildPartial() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.File result = new com.github.saturn_xiv.palm.plugins.lily.v1.File(this);
+      if (bitField0_ != 0) { buildPartial0(result); }
+      onBuilt();
+      return result;
+    }
+
+    private void buildPartial0(com.github.saturn_xiv.palm.plugins.lily.v1.File result) {
+      int from_bitField0_ = bitField0_;
+      int to_bitField0_ = 0;
+      if (((from_bitField0_ & 0x00000001) != 0)) {
+        result.contentType_ = contentType_;
+        to_bitField0_ |= 0x00000001;
+      }
+      if (((from_bitField0_ & 0x00000002) != 0)) {
+        result.payload_ = payload_;
+      }
+      result.bitField0_ |= to_bitField0_;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.File) {
+        return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.File)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.File other) {
+      if (other == com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()) return this;
+      if (other.hasContentType()) {
+        contentType_ = other.contentType_;
+        bitField0_ |= 0x00000001;
+        onChanged();
+      }
+      if (other.getPayload() != com.google.protobuf.ByteString.EMPTY) {
+        setPayload(other.getPayload());
+      }
+      this.mergeUnknownFields(other.getUnknownFields());
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 10: {
+              contentType_ = input.readStringRequireUtf8();
+              bitField0_ |= 0x00000001;
+              break;
+            } // case 10
+            case 18: {
+              payload_ = input.readBytes();
+              bitField0_ |= 0x00000002;
+              break;
+            } // case 18
+            default: {
+              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                done = true; // was an endgroup tag
+              }
+              break;
+            } // default:
+          } // switch (tag)
+        } // while (!done)
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.unwrapIOException();
+      } finally {
+        onChanged();
+      } // finally
+      return this;
+    }
+    private int bitField0_;
+
+    private java.lang.Object contentType_ = "";
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @return Whether the contentType field is set.
+     */
+    public boolean hasContentType() {
+      return ((bitField0_ & 0x00000001) != 0);
+    }
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @return The contentType.
+     */
+    public java.lang.String getContentType() {
+      java.lang.Object ref = contentType_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        contentType_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @return The bytes for contentType.
+     */
+    public com.google.protobuf.ByteString
+        getContentTypeBytes() {
+      java.lang.Object ref = contentType_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        contentType_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @param value The contentType to set.
+     * @return This builder for chaining.
+     */
+    public Builder setContentType(
+        java.lang.String value) {
+      if (value == null) { throw new NullPointerException(); }
+      contentType_ = value;
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearContentType() {
+      contentType_ = getDefaultInstance().getContentType();
+      bitField0_ = (bitField0_ & ~0x00000001);
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>optional string content_type = 1;</code>
+     * @param value The bytes for contentType to set.
+     * @return This builder for chaining.
+     */
+    public Builder setContentTypeBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) { throw new NullPointerException(); }
+      checkByteStringIsUtf8(value);
+      contentType_ = value;
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+
+    private com.google.protobuf.ByteString payload_ = com.google.protobuf.ByteString.EMPTY;
+    /**
+     * <code>bytes payload = 2;</code>
+     * @return The payload.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString getPayload() {
+      return payload_;
+    }
+    /**
+     * <code>bytes payload = 2;</code>
+     * @param value The payload to set.
+     * @return This builder for chaining.
+     */
+    public Builder setPayload(com.google.protobuf.ByteString value) {
+      if (value == null) { throw new NullPointerException(); }
+      payload_ = value;
+      bitField0_ |= 0x00000002;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>bytes payload = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearPayload() {
+      bitField0_ = (bitField0_ & ~0x00000002);
+      payload_ = getDefaultInstance().getPayload();
+      onChanged();
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:palm.lily.v1.File)
+  }
+
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.File)
+  private static final com.github.saturn_xiv.palm.plugins.lily.v1.File DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.File();
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.File getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<File>
+      PARSER = new com.google.protobuf.AbstractParser<File>() {
+    @java.lang.Override
+    public File parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (com.google.protobuf.UninitializedMessageException e) {
+        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(e)
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  };
+
+  public static com.google.protobuf.Parser<File> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<File> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.File getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 32 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/FileOrBuilder.java

@@ -0,0 +1,32 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+public interface FileOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:palm.lily.v1.File)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return Whether the contentType field is set.
+   */
+  boolean hasContentType();
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return The contentType.
+   */
+  java.lang.String getContentType();
+  /**
+   * <code>optional string content_type = 1;</code>
+   * @return The bytes for contentType.
+   */
+  com.google.protobuf.ByteString
+      getContentTypeBytes();
+
+  /**
+   * <code>bytes payload = 2;</code>
+   * @return The payload.
+   */
+  com.google.protobuf.ByteString getPayload();
+}

+ 131 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/Lily.java

@@ -0,0 +1,131 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+public final class Lily {
+  private Lily() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistryLite registry) {
+  }
+
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+    registerAllExtensions(
+        (com.google.protobuf.ExtensionRegistryLite) registry);
+  }
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_File_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_File_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_ExcelModel_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_ExcelModel_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_ExcelModel_Sheet_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_TexToRequest_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_TexToRequest_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_TexToRequest_FilesEntry_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_TexToRequest_FilesEntry_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_palm_lily_v1_EpubBuildRequest_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_palm_lily_v1_EpubBuildRequest_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static  com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\nlily.proto\022\014palm.lily.v1\"C\n\004File\022\031\n\014co" +
+      "ntent_type\030\001 \001(\tH\000\210\001\001\022\017\n\007payload\030\002 \001(\014B\017" +
+      "\n\r_content_type\"\266\001\n\nExcelModel\022.\n\006sheets" +
+      "\030\001 \003(\0132\036.palm.lily.v1.ExcelModel.Sheet\032x" +
+      "\n\005Sheet\022\014\n\004name\030\001 \001(\t\0222\n\005cells\030\002 \003(\0132#.p" +
+      "alm.lily.v1.ExcelModel.Sheet.Cell\032-\n\004Cel" +
+      "l\022\013\n\003row\030\001 \001(\r\022\013\n\003col\030\002 \001(\r\022\013\n\003val\030\003 \001(\t" +
+      "\"r\n\014TexToRequest\0224\n\005files\030\001 \003(\0132%.palm.l" +
+      "ily.v1.TexToRequest.FilesEntry\032,\n\nFilesE" +
+      "ntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\014:\0028\001\"\022\n\020" +
+      "EpubBuildRequest2|\n\005Excel\0227\n\005Parse\022\022.pal" +
+      "m.lily.v1.File\032\030.palm.lily.v1.ExcelModel" +
+      "\"\000\022:\n\010Generate\022\030.palm.lily.v1.ExcelModel" +
+      "\032\022.palm.lily.v1.File\"\0002|\n\003Tex\0229\n\005ToPdf\022\032" +
+      ".palm.lily.v1.TexToRequest\032\022.palm.lily.v" +
+      "1.File\"\000\022:\n\006ToWord\022\032.palm.lily.v1.TexToR" +
+      "equest\032\022.palm.lily.v1.File\"\0002E\n\004Epub\022=\n\005" +
+      "Build\022\036.palm.lily.v1.EpubBuildRequest\032\022." +
+      "palm.lily.v1.File\"\000B.\n*com.github.saturn" +
+      "_xiv.palm.plugins.lily.v1P\001b\006proto3"
+    };
+    descriptor = com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        });
+    internal_static_palm_lily_v1_File_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_palm_lily_v1_File_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_File_descriptor,
+        new java.lang.String[] { "ContentType", "Payload", "ContentType", });
+    internal_static_palm_lily_v1_ExcelModel_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_palm_lily_v1_ExcelModel_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_ExcelModel_descriptor,
+        new java.lang.String[] { "Sheets", });
+    internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor =
+      internal_static_palm_lily_v1_ExcelModel_descriptor.getNestedTypes().get(0);
+    internal_static_palm_lily_v1_ExcelModel_Sheet_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor,
+        new java.lang.String[] { "Name", "Cells", });
+    internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor =
+      internal_static_palm_lily_v1_ExcelModel_Sheet_descriptor.getNestedTypes().get(0);
+    internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_ExcelModel_Sheet_Cell_descriptor,
+        new java.lang.String[] { "Row", "Col", "Val", });
+    internal_static_palm_lily_v1_TexToRequest_descriptor =
+      getDescriptor().getMessageTypes().get(2);
+    internal_static_palm_lily_v1_TexToRequest_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_TexToRequest_descriptor,
+        new java.lang.String[] { "Files", });
+    internal_static_palm_lily_v1_TexToRequest_FilesEntry_descriptor =
+      internal_static_palm_lily_v1_TexToRequest_descriptor.getNestedTypes().get(0);
+    internal_static_palm_lily_v1_TexToRequest_FilesEntry_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_TexToRequest_FilesEntry_descriptor,
+        new java.lang.String[] { "Key", "Value", });
+    internal_static_palm_lily_v1_EpubBuildRequest_descriptor =
+      getDescriptor().getMessageTypes().get(3);
+    internal_static_palm_lily_v1_EpubBuildRequest_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_palm_lily_v1_EpubBuildRequest_descriptor,
+        new java.lang.String[] { });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}

+ 367 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexGrpc.java

@@ -0,0 +1,367 @@
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+import static io.grpc.MethodDescriptor.generateFullMethodName;
+
+/**
+ */
+@javax.annotation.Generated(
+    value = "by gRPC proto compiler (version 1.58.0)",
+    comments = "Source: lily.proto")
+@io.grpc.stub.annotations.GrpcGenerated
+public final class TexGrpc {
+
+  private TexGrpc() {}
+
+  public static final java.lang.String SERVICE_NAME = "palm.lily.v1.Tex";
+
+  // Static method descriptors that strictly reflect the proto.
+  private static volatile io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getToPdfMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "ToPdf",
+      requestType = com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.class,
+      responseType = com.github.saturn_xiv.palm.plugins.lily.v1.File.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getToPdfMethod() {
+    io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File> getToPdfMethod;
+    if ((getToPdfMethod = TexGrpc.getToPdfMethod) == null) {
+      synchronized (TexGrpc.class) {
+        if ((getToPdfMethod = TexGrpc.getToPdfMethod) == null) {
+          TexGrpc.getToPdfMethod = getToPdfMethod =
+              io.grpc.MethodDescriptor.<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ToPdf"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()))
+              .setSchemaDescriptor(new TexMethodDescriptorSupplier("ToPdf"))
+              .build();
+        }
+      }
+    }
+    return getToPdfMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getToWordMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "ToWord",
+      requestType = com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.class,
+      responseType = com.github.saturn_xiv.palm.plugins.lily.v1.File.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+      com.github.saturn_xiv.palm.plugins.lily.v1.File> getToWordMethod() {
+    io.grpc.MethodDescriptor<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File> getToWordMethod;
+    if ((getToWordMethod = TexGrpc.getToWordMethod) == null) {
+      synchronized (TexGrpc.class) {
+        if ((getToWordMethod = TexGrpc.getToWordMethod) == null) {
+          TexGrpc.getToWordMethod = getToWordMethod =
+              io.grpc.MethodDescriptor.<com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest, com.github.saturn_xiv.palm.plugins.lily.v1.File>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ToWord"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  com.github.saturn_xiv.palm.plugins.lily.v1.File.getDefaultInstance()))
+              .setSchemaDescriptor(new TexMethodDescriptorSupplier("ToWord"))
+              .build();
+        }
+      }
+    }
+    return getToWordMethod;
+  }
+
+  /**
+   * Creates a new async stub that supports all call types for the service
+   */
+  public static TexStub newStub(io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<TexStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<TexStub>() {
+        @java.lang.Override
+        public TexStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new TexStub(channel, callOptions);
+        }
+      };
+    return TexStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new blocking-style stub that supports unary and streaming output calls on the service
+   */
+  public static TexBlockingStub newBlockingStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<TexBlockingStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<TexBlockingStub>() {
+        @java.lang.Override
+        public TexBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new TexBlockingStub(channel, callOptions);
+        }
+      };
+    return TexBlockingStub.newStub(factory, channel);
+  }
+
+  /**
+   * Creates a new ListenableFuture-style stub that supports unary calls on the service
+   */
+  public static TexFutureStub newFutureStub(
+      io.grpc.Channel channel) {
+    io.grpc.stub.AbstractStub.StubFactory<TexFutureStub> factory =
+      new io.grpc.stub.AbstractStub.StubFactory<TexFutureStub>() {
+        @java.lang.Override
+        public TexFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+          return new TexFutureStub(channel, callOptions);
+        }
+      };
+    return TexFutureStub.newStub(factory, channel);
+  }
+
+  /**
+   */
+  public interface AsyncService {
+
+    /**
+     */
+    default void toPdf(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getToPdfMethod(), responseObserver);
+    }
+
+    /**
+     */
+    default void toWord(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getToWordMethod(), responseObserver);
+    }
+  }
+
+  /**
+   * Base class for the server implementation of the service Tex.
+   */
+  public static abstract class TexImplBase
+      implements io.grpc.BindableService, AsyncService {
+
+    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+      return TexGrpc.bindService(this);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do asynchronous rpc calls to service Tex.
+   */
+  public static final class TexStub
+      extends io.grpc.stub.AbstractAsyncStub<TexStub> {
+    private TexStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected TexStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new TexStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public void toPdf(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getToPdfMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void toWord(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request,
+        io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getToWordMethod(), getCallOptions()), request, responseObserver);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do synchronous rpc calls to service Tex.
+   */
+  public static final class TexBlockingStub
+      extends io.grpc.stub.AbstractBlockingStub<TexBlockingStub> {
+    private TexBlockingStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected TexBlockingStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new TexBlockingStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File toPdf(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getToPdfMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public com.github.saturn_xiv.palm.plugins.lily.v1.File toWord(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getToWordMethod(), getCallOptions(), request);
+    }
+  }
+
+  /**
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service Tex.
+   */
+  public static final class TexFutureStub
+      extends io.grpc.stub.AbstractFutureStub<TexFutureStub> {
+    private TexFutureStub(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      super(channel, callOptions);
+    }
+
+    @java.lang.Override
+    protected TexFutureStub build(
+        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
+      return new TexFutureStub(channel, callOptions);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<com.github.saturn_xiv.palm.plugins.lily.v1.File> toPdf(
+        com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getToPdfMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<com.github.saturn_xiv.palm.plugins.lily.v1.File> toWord(
+        com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getToWordMethod(), getCallOptions()), request);
+    }
+  }
+
+  private static final int METHODID_TO_PDF = 0;
+  private static final int METHODID_TO_WORD = 1;
+
+  private static final class MethodHandlers<Req, Resp> implements
+      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
+    private final AsyncService serviceImpl;
+    private final int methodId;
+
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
+      this.serviceImpl = serviceImpl;
+      this.methodId = methodId;
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_TO_PDF:
+          serviceImpl.toPdf((com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest) request,
+              (io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File>) responseObserver);
+          break;
+        case METHODID_TO_WORD:
+          serviceImpl.toWord((com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest) request,
+              (io.grpc.stub.StreamObserver<com.github.saturn_xiv.palm.plugins.lily.v1.File>) responseObserver);
+          break;
+        default:
+          throw new AssertionError();
+      }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver<Req> invoke(
+        io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+          getToPdfMethod(),
+          io.grpc.stub.ServerCalls.asyncUnaryCall(
+            new MethodHandlers<
+              com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+              com.github.saturn_xiv.palm.plugins.lily.v1.File>(
+                service, METHODID_TO_PDF)))
+        .addMethod(
+          getToWordMethod(),
+          io.grpc.stub.ServerCalls.asyncUnaryCall(
+            new MethodHandlers<
+              com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest,
+              com.github.saturn_xiv.palm.plugins.lily.v1.File>(
+                service, METHODID_TO_WORD)))
+        .build();
+  }
+
+  private static abstract class TexBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
+    TexBaseDescriptorSupplier() {}
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.getDescriptor();
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
+      return getFileDescriptor().findServiceByName("Tex");
+    }
+  }
+
+  private static final class TexFileDescriptorSupplier
+      extends TexBaseDescriptorSupplier {
+    TexFileDescriptorSupplier() {}
+  }
+
+  private static final class TexMethodDescriptorSupplier
+      extends TexBaseDescriptorSupplier
+      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
+    private final java.lang.String methodName;
+
+    TexMethodDescriptorSupplier(java.lang.String methodName) {
+      this.methodName = methodName;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
+      return getServiceDescriptor().findMethodByName(methodName);
+    }
+  }
+
+  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
+
+  public static io.grpc.ServiceDescriptor getServiceDescriptor() {
+    io.grpc.ServiceDescriptor result = serviceDescriptor;
+    if (result == null) {
+      synchronized (TexGrpc.class) {
+        result = serviceDescriptor;
+        if (result == null) {
+          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
+              .setSchemaDescriptor(new TexFileDescriptorSupplier())
+              .addMethod(getToPdfMethod())
+              .addMethod(getToWordMethod())
+              .build();
+        }
+      }
+    }
+    return result;
+  }
+}

+ 684 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexToRequest.java

@@ -0,0 +1,684 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+/**
+ * Protobuf type {@code palm.lily.v1.TexToRequest}
+ */
+public final class TexToRequest extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:palm.lily.v1.TexToRequest)
+    TexToRequestOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use TexToRequest.newBuilder() to construct.
+  private TexToRequest(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private TexToRequest() {
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new TexToRequest();
+  }
+
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_descriptor;
+  }
+
+  @SuppressWarnings({"rawtypes"})
+  @java.lang.Override
+  protected com.google.protobuf.MapField internalGetMapField(
+      int number) {
+    switch (number) {
+      case 1:
+        return internalGetFiles();
+      default:
+        throw new RuntimeException(
+            "Invalid map field number: " + number);
+    }
+  }
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.class, com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.Builder.class);
+  }
+
+  public static final int FILES_FIELD_NUMBER = 1;
+  private static final class FilesDefaultEntryHolder {
+    static final com.google.protobuf.MapEntry<
+        java.lang.String, com.google.protobuf.ByteString> defaultEntry =
+            com.google.protobuf.MapEntry
+            .<java.lang.String, com.google.protobuf.ByteString>newDefaultInstance(
+                com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_FilesEntry_descriptor, 
+                com.google.protobuf.WireFormat.FieldType.STRING,
+                "",
+                com.google.protobuf.WireFormat.FieldType.BYTES,
+                com.google.protobuf.ByteString.EMPTY);
+  }
+  @SuppressWarnings("serial")
+  private com.google.protobuf.MapField<
+      java.lang.String, com.google.protobuf.ByteString> files_;
+  private com.google.protobuf.MapField<java.lang.String, com.google.protobuf.ByteString>
+  internalGetFiles() {
+    if (files_ == null) {
+      return com.google.protobuf.MapField.emptyMapField(
+          FilesDefaultEntryHolder.defaultEntry);
+    }
+    return files_;
+  }
+  public int getFilesCount() {
+    return internalGetFiles().getMap().size();
+  }
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  @java.lang.Override
+  public boolean containsFiles(
+      java.lang.String key) {
+    if (key == null) { throw new NullPointerException("map key"); }
+    return internalGetFiles().getMap().containsKey(key);
+  }
+  /**
+   * Use {@link #getFilesMap()} instead.
+   */
+  @java.lang.Override
+  @java.lang.Deprecated
+  public java.util.Map<java.lang.String, com.google.protobuf.ByteString> getFiles() {
+    return getFilesMap();
+  }
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  @java.lang.Override
+  public java.util.Map<java.lang.String, com.google.protobuf.ByteString> getFilesMap() {
+    return internalGetFiles().getMap();
+  }
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  @java.lang.Override
+  public /* nullable */
+com.google.protobuf.ByteString getFilesOrDefault(
+      java.lang.String key,
+      /* nullable */
+com.google.protobuf.ByteString defaultValue) {
+    if (key == null) { throw new NullPointerException("map key"); }
+    java.util.Map<java.lang.String, com.google.protobuf.ByteString> map =
+        internalGetFiles().getMap();
+    return map.containsKey(key) ? map.get(key) : defaultValue;
+  }
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getFilesOrThrow(
+      java.lang.String key) {
+    if (key == null) { throw new NullPointerException("map key"); }
+    java.util.Map<java.lang.String, com.google.protobuf.ByteString> map =
+        internalGetFiles().getMap();
+    if (!map.containsKey(key)) {
+      throw new java.lang.IllegalArgumentException();
+    }
+    return map.get(key);
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    com.google.protobuf.GeneratedMessageV3
+      .serializeStringMapTo(
+        output,
+        internalGetFiles(),
+        FilesDefaultEntryHolder.defaultEntry,
+        1);
+    getUnknownFields().writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    for (java.util.Map.Entry<java.lang.String, com.google.protobuf.ByteString> entry
+         : internalGetFiles().getMap().entrySet()) {
+      com.google.protobuf.MapEntry<java.lang.String, com.google.protobuf.ByteString>
+      files__ = FilesDefaultEntryHolder.defaultEntry.newBuilderForType()
+          .setKey(entry.getKey())
+          .setValue(entry.getValue())
+          .build();
+      size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, files__);
+    }
+    size += getUnknownFields().getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest)) {
+      return super.equals(obj);
+    }
+    com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest other = (com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest) obj;
+
+    if (!internalGetFiles().equals(
+        other.internalGetFiles())) return false;
+    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    if (!internalGetFiles().getMap().isEmpty()) {
+      hash = (37 * hash) + FILES_FIELD_NUMBER;
+      hash = (53 * hash) + internalGetFiles().hashCode();
+    }
+    hash = (29 * hash) + getUnknownFields().hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code palm.lily.v1.TexToRequest}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:palm.lily.v1.TexToRequest)
+      com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequestOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_descriptor;
+    }
+
+    @SuppressWarnings({"rawtypes"})
+    protected com.google.protobuf.MapField internalGetMapField(
+        int number) {
+      switch (number) {
+        case 1:
+          return internalGetFiles();
+        default:
+          throw new RuntimeException(
+              "Invalid map field number: " + number);
+      }
+    }
+    @SuppressWarnings({"rawtypes"})
+    protected com.google.protobuf.MapField internalGetMutableMapField(
+        int number) {
+      switch (number) {
+        case 1:
+          return internalGetMutableFiles();
+        default:
+          throw new RuntimeException(
+              "Invalid map field number: " + number);
+      }
+    }
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.class, com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.Builder.class);
+    }
+
+    // Construct using com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.newBuilder()
+    private Builder() {
+
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      bitField0_ = 0;
+      internalGetMutableFiles().clear();
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.Lily.internal_static_palm_lily_v1_TexToRequest_descriptor;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest getDefaultInstanceForType() {
+      return com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest build() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest buildPartial() {
+      com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest result = new com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest(this);
+      if (bitField0_ != 0) { buildPartial0(result); }
+      onBuilt();
+      return result;
+    }
+
+    private void buildPartial0(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest result) {
+      int from_bitField0_ = bitField0_;
+      if (((from_bitField0_ & 0x00000001) != 0)) {
+        result.files_ = internalGetFiles();
+        result.files_.makeImmutable();
+      }
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest) {
+        return mergeFrom((com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest other) {
+      if (other == com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest.getDefaultInstance()) return this;
+      internalGetMutableFiles().mergeFrom(
+          other.internalGetFiles());
+      bitField0_ |= 0x00000001;
+      this.mergeUnknownFields(other.getUnknownFields());
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 10: {
+              com.google.protobuf.MapEntry<java.lang.String, com.google.protobuf.ByteString>
+              files__ = input.readMessage(
+                  FilesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+              internalGetMutableFiles().getMutableMap().put(
+                  files__.getKey(), files__.getValue());
+              bitField0_ |= 0x00000001;
+              break;
+            } // case 10
+            default: {
+              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                done = true; // was an endgroup tag
+              }
+              break;
+            } // default:
+          } // switch (tag)
+        } // while (!done)
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.unwrapIOException();
+      } finally {
+        onChanged();
+      } // finally
+      return this;
+    }
+    private int bitField0_;
+
+    private com.google.protobuf.MapField<
+        java.lang.String, com.google.protobuf.ByteString> files_;
+    private com.google.protobuf.MapField<java.lang.String, com.google.protobuf.ByteString>
+        internalGetFiles() {
+      if (files_ == null) {
+        return com.google.protobuf.MapField.emptyMapField(
+            FilesDefaultEntryHolder.defaultEntry);
+      }
+      return files_;
+    }
+    private com.google.protobuf.MapField<java.lang.String, com.google.protobuf.ByteString>
+        internalGetMutableFiles() {
+      if (files_ == null) {
+        files_ = com.google.protobuf.MapField.newMapField(
+            FilesDefaultEntryHolder.defaultEntry);
+      }
+      if (!files_.isMutable()) {
+        files_ = files_.copy();
+      }
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return files_;
+    }
+    public int getFilesCount() {
+      return internalGetFiles().getMap().size();
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    @java.lang.Override
+    public boolean containsFiles(
+        java.lang.String key) {
+      if (key == null) { throw new NullPointerException("map key"); }
+      return internalGetFiles().getMap().containsKey(key);
+    }
+    /**
+     * Use {@link #getFilesMap()} instead.
+     */
+    @java.lang.Override
+    @java.lang.Deprecated
+    public java.util.Map<java.lang.String, com.google.protobuf.ByteString> getFiles() {
+      return getFilesMap();
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    @java.lang.Override
+    public java.util.Map<java.lang.String, com.google.protobuf.ByteString> getFilesMap() {
+      return internalGetFiles().getMap();
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    @java.lang.Override
+    public /* nullable */
+com.google.protobuf.ByteString getFilesOrDefault(
+        java.lang.String key,
+        /* nullable */
+com.google.protobuf.ByteString defaultValue) {
+      if (key == null) { throw new NullPointerException("map key"); }
+      java.util.Map<java.lang.String, com.google.protobuf.ByteString> map =
+          internalGetFiles().getMap();
+      return map.containsKey(key) ? map.get(key) : defaultValue;
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString getFilesOrThrow(
+        java.lang.String key) {
+      if (key == null) { throw new NullPointerException("map key"); }
+      java.util.Map<java.lang.String, com.google.protobuf.ByteString> map =
+          internalGetFiles().getMap();
+      if (!map.containsKey(key)) {
+        throw new java.lang.IllegalArgumentException();
+      }
+      return map.get(key);
+    }
+    public Builder clearFiles() {
+      bitField0_ = (bitField0_ & ~0x00000001);
+      internalGetMutableFiles().getMutableMap()
+          .clear();
+      return this;
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    public Builder removeFiles(
+        java.lang.String key) {
+      if (key == null) { throw new NullPointerException("map key"); }
+      internalGetMutableFiles().getMutableMap()
+          .remove(key);
+      return this;
+    }
+    /**
+     * Use alternate mutation accessors instead.
+     */
+    @java.lang.Deprecated
+    public java.util.Map<java.lang.String, com.google.protobuf.ByteString>
+        getMutableFiles() {
+      bitField0_ |= 0x00000001;
+      return internalGetMutableFiles().getMutableMap();
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    public Builder putFiles(
+        java.lang.String key,
+        com.google.protobuf.ByteString value) {
+      if (key == null) { throw new NullPointerException("map key"); }
+      if (value == null) { throw new NullPointerException("map value"); }
+      internalGetMutableFiles().getMutableMap()
+          .put(key, value);
+      bitField0_ |= 0x00000001;
+      return this;
+    }
+    /**
+     * <code>map&lt;string, bytes&gt; files = 1;</code>
+     */
+    public Builder putAllFiles(
+        java.util.Map<java.lang.String, com.google.protobuf.ByteString> values) {
+      internalGetMutableFiles().getMutableMap()
+          .putAll(values);
+      bitField0_ |= 0x00000001;
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:palm.lily.v1.TexToRequest)
+  }
+
+  // @@protoc_insertion_point(class_scope:palm.lily.v1.TexToRequest)
+  private static final com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest();
+  }
+
+  public static com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<TexToRequest>
+      PARSER = new com.google.protobuf.AbstractParser<TexToRequest>() {
+    @java.lang.Override
+    public TexToRequest parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (com.google.protobuf.UninitializedMessageException e) {
+        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(e)
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  };
+
+  public static com.google.protobuf.Parser<TexToRequest> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<TexToRequest> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.github.saturn_xiv.palm.plugins.lily.v1.TexToRequest getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 43 - 0
clients/java/com/github/saturn_xiv/palm/plugins/lily/v1/TexToRequestOrBuilder.java

@@ -0,0 +1,43 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: lily.proto
+
+package com.github.saturn_xiv.palm.plugins.lily.v1;
+
+public interface TexToRequestOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:palm.lily.v1.TexToRequest)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  int getFilesCount();
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  boolean containsFiles(
+      java.lang.String key);
+  /**
+   * Use {@link #getFilesMap()} instead.
+   */
+  @java.lang.Deprecated
+  java.util.Map<java.lang.String, com.google.protobuf.ByteString>
+  getFiles();
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  java.util.Map<java.lang.String, com.google.protobuf.ByteString>
+  getFilesMap();
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  /* nullable */
+com.google.protobuf.ByteString getFilesOrDefault(
+      java.lang.String key,
+      /* nullable */
+com.google.protobuf.ByteString defaultValue);
+  /**
+   * <code>map&lt;string, bytes&gt; files = 1;</code>
+   */
+  com.google.protobuf.ByteString getFilesOrThrow(
+      java.lang.String key);
+}

TEMPAT SAMPAH
clients/php/GPBMetadata/Lily.php


+ 0 - 42
clients/php/Mint/Morus/V1/MarkdownStub.php

@@ -1,42 +0,0 @@
-<?php
-// GENERATED CODE -- DO NOT EDIT!
-
-namespace Mint\Morus\V1;
-
-/**
- * ----------------------------------------------------------------------------
- */
-class MarkdownStub {
-
-    /**
-     * @param \Mint\Morus\V1\MarkdownToHtmlRequest $request client request
-     * @param \Grpc\ServerContext $context server request context
-     * @return \Mint\Morus\V1\MarkdownToHtmlResponse for response data, null if if error occured
-     *     initial metadata (if any) and status (if not ok) should be set to $context
-     */
-    public function ToHtml(
-        \Mint\Morus\V1\MarkdownToHtmlRequest $request,
-        \Grpc\ServerContext $context
-    ): ?\Mint\Morus\V1\MarkdownToHtmlResponse {
-        $context->setStatus(\Grpc\Status::unimplemented());
-        return null;
-    }
-
-    /**
-     * Get the method descriptors of the service for server registration
-     *
-     * @return array of \Grpc\MethodDescriptor for the service methods
-     */
-    public final function getMethodDescriptors(): array
-    {
-        return [
-            '/mint.morus.v1.Markdown/ToHtml' => new \Grpc\MethodDescriptor(
-                $this,
-                'ToHtml',
-                '\Mint\Morus\V1\MarkdownToHtmlRequest',
-                \Grpc\MethodDescriptor::UNARY_CALL
-            ),
-        ];
-    }
-
-}

+ 31 - 0
clients/php/Palm/Lily/V1/EpubBuildRequest.php

@@ -0,0 +1,31 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.EpubBuildRequest</code>
+ */
+class EpubBuildRequest extends \Google\Protobuf\Internal\Message
+{
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+}
+

+ 35 - 0
clients/php/Palm/Lily/V1/EpubClient.php

@@ -0,0 +1,35 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+namespace Palm\Lily\V1;
+
+/**
+ * ----------------------------------------------------------------------------
+ *
+ */
+class EpubClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Palm\Lily\V1\EpubBuildRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\UnaryCall
+     */
+    public function Build(\Palm\Lily\V1\EpubBuildRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/palm.lily.v1.Epub/Build',
+        $argument,
+        ['\Palm\Lily\V1\File', 'decode'],
+        $metadata, $options);
+    }
+
+}

+ 49 - 0
clients/php/Palm/Lily/V1/ExcelClient.php

@@ -0,0 +1,49 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+namespace Palm\Lily\V1;
+
+/**
+ * ----------------------------------------------------------------------------
+ *
+ */
+class ExcelClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Palm\Lily\V1\File $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\UnaryCall
+     */
+    public function Parse(\Palm\Lily\V1\File $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/palm.lily.v1.Excel/Parse',
+        $argument,
+        ['\Palm\Lily\V1\ExcelModel', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param \Palm\Lily\V1\ExcelModel $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\UnaryCall
+     */
+    public function Generate(\Palm\Lily\V1\ExcelModel $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/palm.lily.v1.Excel/Generate',
+        $argument,
+        ['\Palm\Lily\V1\File', 'decode'],
+        $metadata, $options);
+    }
+
+}

+ 58 - 0
clients/php/Palm/Lily/V1/ExcelModel.php

@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.ExcelModel</code>
+ */
+class ExcelModel extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     */
+    private $sheets;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array<\Palm\Lily\V1\ExcelModel\Sheet>|\Google\Protobuf\Internal\RepeatedField $sheets
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
+     */
+    public function getSheets()
+    {
+        return $this->sheets;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet sheets = 1;</code>
+     * @param array<\Palm\Lily\V1\ExcelModel\Sheet>|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
+     */
+    public function setSheets($var)
+    {
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Palm\Lily\V1\ExcelModel\Sheet::class);
+        $this->sheets = $arr;
+
+        return $this;
+    }
+
+}
+

+ 88 - 0
clients/php/Palm/Lily/V1/ExcelModel/Sheet.php

@@ -0,0 +1,88 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1\ExcelModel;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.ExcelModel.Sheet</code>
+ */
+class Sheet extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     */
+    protected $name = '';
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     */
+    private $cells;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *     @type array<\Palm\Lily\V1\ExcelModel\Sheet\Cell>|\Google\Protobuf\Internal\RepeatedField $cells
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
+     */
+    public function getCells()
+    {
+        return $this->cells;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated .palm.lily.v1.ExcelModel.Sheet.Cell cells = 2;</code>
+     * @param array<\Palm\Lily\V1\ExcelModel\Sheet\Cell>|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
+     */
+    public function setCells($var)
+    {
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Palm\Lily\V1\ExcelModel\Sheet\Cell::class);
+        $this->cells = $arr;
+
+        return $this;
+    }
+
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Sheet::class, \Palm\Lily\V1\ExcelModel_Sheet::class);
+

+ 115 - 0
clients/php/Palm/Lily/V1/ExcelModel/Sheet/Cell.php

@@ -0,0 +1,115 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1\ExcelModel\Sheet;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.ExcelModel.Sheet.Cell</code>
+ */
+class Cell extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>uint32 row = 1;</code>
+     */
+    protected $row = 0;
+    /**
+     * Generated from protobuf field <code>uint32 col = 2;</code>
+     */
+    protected $col = 0;
+    /**
+     * Generated from protobuf field <code>string val = 3;</code>
+     */
+    protected $val = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $row
+     *     @type int $col
+     *     @type string $val
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>uint32 row = 1;</code>
+     * @return int
+     */
+    public function getRow()
+    {
+        return $this->row;
+    }
+
+    /**
+     * Generated from protobuf field <code>uint32 row = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setRow($var)
+    {
+        GPBUtil::checkUint32($var);
+        $this->row = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>uint32 col = 2;</code>
+     * @return int
+     */
+    public function getCol()
+    {
+        return $this->col;
+    }
+
+    /**
+     * Generated from protobuf field <code>uint32 col = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setCol($var)
+    {
+        GPBUtil::checkUint32($var);
+        $this->col = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string val = 3;</code>
+     * @return string
+     */
+    public function getVal()
+    {
+        return $this->val;
+    }
+
+    /**
+     * Generated from protobuf field <code>string val = 3;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setVal($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->val = $var;
+
+        return $this;
+    }
+
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Cell::class, \Palm\Lily\V1\ExcelModel_Sheet_Cell::class);
+

+ 95 - 0
clients/php/Palm/Lily/V1/File.php

@@ -0,0 +1,95 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.File</code>
+ */
+class File extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>optional string content_type = 1;</code>
+     */
+    protected $content_type = null;
+    /**
+     * Generated from protobuf field <code>bytes payload = 2;</code>
+     */
+    protected $payload = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $content_type
+     *     @type string $payload
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>optional string content_type = 1;</code>
+     * @return string
+     */
+    public function getContentType()
+    {
+        return isset($this->content_type) ? $this->content_type : '';
+    }
+
+    public function hasContentType()
+    {
+        return isset($this->content_type);
+    }
+
+    public function clearContentType()
+    {
+        unset($this->content_type);
+    }
+
+    /**
+     * Generated from protobuf field <code>optional string content_type = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setContentType($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->content_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bytes payload = 2;</code>
+     * @return string
+     */
+    public function getPayload()
+    {
+        return $this->payload;
+    }
+
+    /**
+     * Generated from protobuf field <code>bytes payload = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setPayload($var)
+    {
+        GPBUtil::checkString($var, False);
+        $this->payload = $var;
+
+        return $this;
+    }
+
+}
+

+ 49 - 0
clients/php/Palm/Lily/V1/TexClient.php

@@ -0,0 +1,49 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+namespace Palm\Lily\V1;
+
+/**
+ * ----------------------------------------------------------------------------
+ *
+ */
+class TexClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Palm\Lily\V1\TexToRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\UnaryCall
+     */
+    public function ToPdf(\Palm\Lily\V1\TexToRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/palm.lily.v1.Tex/ToPdf',
+        $argument,
+        ['\Palm\Lily\V1\File', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param \Palm\Lily\V1\TexToRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     * @return \Grpc\UnaryCall
+     */
+    public function ToWord(\Palm\Lily\V1\TexToRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/palm.lily.v1.Tex/ToWord',
+        $argument,
+        ['\Palm\Lily\V1\File', 'decode'],
+        $metadata, $options);
+    }
+
+}

+ 58 - 0
clients/php/Palm/Lily/V1/TexToRequest.php

@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.TexToRequest</code>
+ */
+class TexToRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>map<string, bytes> files = 1;</code>
+     */
+    private $files;
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array|\Google\Protobuf\Internal\MapField $files
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>map<string, bytes> files = 1;</code>
+     * @return \Google\Protobuf\Internal\MapField
+     */
+    public function getFiles()
+    {
+        return $this->files;
+    }
+
+    /**
+     * Generated from protobuf field <code>map<string, bytes> files = 1;</code>
+     * @param array|\Google\Protobuf\Internal\MapField $var
+     * @return $this
+     */
+    public function setFiles($var)
+    {
+        $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::BYTES);
+        $this->files = $arr;
+
+        return $this;
+    }
+
+}
+

+ 88 - 0
clients/php/Palm/Lily/V1/TexToRequest/File.php

@@ -0,0 +1,88 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+namespace Palm\Lily\V1\TexToRequest;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>palm.lily.v1.TexToRequest.File</code>
+ */
+class File extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     */
+    protected $name = '';
+    /**
+     * Generated from protobuf field <code>bytes content = 2;</code>
+     */
+    protected $content = '';
+
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *     @type string $content
+     * }
+     */
+    public function __construct($data = NULL) {
+        \GPBMetadata\Lily::initOnce();
+        parent::__construct($data);
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bytes content = 2;</code>
+     * @return string
+     */
+    public function getContent()
+    {
+        return $this->content;
+    }
+
+    /**
+     * Generated from protobuf field <code>bytes content = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setContent($var)
+    {
+        GPBUtil::checkString($var, False);
+        $this->content = $var;
+
+        return $this;
+    }
+
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(File::class, \Palm\Lily\V1\TexToRequest_File::class);
+

+ 2 - 1
clients/php/composer.json

@@ -9,7 +9,8 @@
       "GPBMetadata\\": [
         "GPBMetadata/"
       ],
-      "Mint\\": "Mint/"
+      "Mint\\": "Mint/",
+      "Palm\\": "Palm/"
     }
   }
 }

+ 61 - 0
clients/php/lily-demo.php

@@ -0,0 +1,61 @@
+<?php
+
+require dirname(__FILE__) . '/vendor/autoload.php';
+
+function tex2pdf($host, $request)
+{
+    $client = new Palm\Lily\V1\TexClient($host, [
+        'credentials' => Grpc\ChannelCredentials::createInsecure(),
+    ]);
+
+    list($response, $status) = $client->ToPdf($request)->wait();
+    if ($status->code !== Grpc\STATUS_OK) {
+        echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
+        exit(1);
+    }
+    echo $response->getContentType() . '(' . strlen($response->getPayload()) . ' bytes)' . PHP_EOL;
+}
+
+$request = new Palm\Lily\V1\TexToRequest();
+
+$request->getFiles()['main.tex'] = <<<'EOF'
+% 导言区
+\documentclass[a4paper, 12pt, fontset=ubuntu]{article} % book, report, letter
+\usepackage{ctex} % Use chinese package
+
+\title{\heiti 一级标题}
+\author{\kaishu 半闲}
+\date{\today}
+
+% 正文区
+
+\begin{document}
+    \maketitle % 头部信息在正文显示
+    \tableofcontents % 显示索引列
+
+    \include{section-1.tex}
+    \include{section-2.tex}
+
+\end{document}
+
+EOF;
+
+$request->getFiles()['section-1.tex'] = <<<'EOF'
+\section{章节1 标题}
+章节1 正文
+\subsection{子章节1.1 标题}
+子章节1-1 正文
+\subsection{子章节1.2 标题}
+子章节1-2 正文
+EOF;
+
+$request->getFiles()['section-2.tex'] = <<<'EOF'
+\section{章节2 标题}
+章节2 正文
+\subsection{子章节2.1 标题}
+子章节2-1 正文
+\subsection{子章节2.2 标题}
+子章节2-2 正文
+EOF;
+
+tex2pdf('localhost:9999', $request);

+ 47 - 0
clients/python/lily_pb2.py

@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nlily.proto\x12\x0cpalm.lily.v1\"C\n\x04\x46ile\x12\x19\n\x0c\x63ontent_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x42\x0f\n\r_content_type\"\xb6\x01\n\nExcelModel\x12.\n\x06sheets\x18\x01 \x03(\x0b\x32\x1e.palm.lily.v1.ExcelModel.Sheet\x1ax\n\x05Sheet\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32#.palm.lily.v1.ExcelModel.Sheet.Cell\x1a-\n\x04\x43\x65ll\x12\x0b\n\x03row\x18\x01 \x01(\r\x12\x0b\n\x03\x63ol\x18\x02 \x01(\r\x12\x0b\n\x03val\x18\x03 \x01(\t\"r\n\x0cTexToRequest\x12\x34\n\x05\x66iles\x18\x01 \x03(\x0b\x32%.palm.lily.v1.TexToRequest.FilesEntry\x1a,\n\nFilesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\x12\n\x10\x45pubBuildRequest2|\n\x05\x45xcel\x12\x37\n\x05Parse\x12\x12.palm.lily.v1.File\x1a\x18.palm.lily.v1.ExcelModel\"\x00\x12:\n\x08Generate\x12\x18.palm.lily.v1.ExcelModel\x1a\x12.palm.lily.v1.File\"\x00\x32|\n\x03Tex\x12\x39\n\x05ToPdf\x12\x1a.palm.lily.v1.TexToRequest\x1a\x12.palm.lily.v1.File\"\x00\x12:\n\x06ToWord\x12\x1a.palm.lily.v1.TexToRequest\x1a\x12.palm.lily.v1.File\"\x00\x32\x45\n\x04\x45pub\x12=\n\x05\x42uild\x12\x1e.palm.lily.v1.EpubBuildRequest\x1a\x12.palm.lily.v1.File\"\x00\x42.\n*com.github.saturn_xiv.palm.plugins.lily.v1P\x01\x62\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'lily_pb2', _globals)
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+  DESCRIPTOR._options = None
+  DESCRIPTOR._serialized_options = b'\n*com.github.saturn_xiv.palm.plugins.lily.v1P\001'
+  _TEXTOREQUEST_FILESENTRY._options = None
+  _TEXTOREQUEST_FILESENTRY._serialized_options = b'8\001'
+  _globals['_FILE']._serialized_start=28
+  _globals['_FILE']._serialized_end=95
+  _globals['_EXCELMODEL']._serialized_start=98
+  _globals['_EXCELMODEL']._serialized_end=280
+  _globals['_EXCELMODEL_SHEET']._serialized_start=160
+  _globals['_EXCELMODEL_SHEET']._serialized_end=280
+  _globals['_EXCELMODEL_SHEET_CELL']._serialized_start=235
+  _globals['_EXCELMODEL_SHEET_CELL']._serialized_end=280
+  _globals['_TEXTOREQUEST']._serialized_start=282
+  _globals['_TEXTOREQUEST']._serialized_end=396
+  _globals['_TEXTOREQUEST_FILESENTRY']._serialized_start=352
+  _globals['_TEXTOREQUEST_FILESENTRY']._serialized_end=396
+  _globals['_EPUBBUILDREQUEST']._serialized_start=398
+  _globals['_EPUBBUILDREQUEST']._serialized_end=416
+  _globals['_EXCEL']._serialized_start=418
+  _globals['_EXCEL']._serialized_end=542
+  _globals['_TEX']._serialized_start=544
+  _globals['_TEX']._serialized_end=668
+  _globals['_EPUB']._serialized_start=670
+  _globals['_EPUB']._serialized_end=739
+# @@protoc_insertion_point(module_scope)

+ 272 - 0
clients/python/lily_pb2_grpc.py

@@ -0,0 +1,272 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+import lily_pb2 as lily__pb2
+
+
+class ExcelStub(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def __init__(self, channel):
+        """Constructor.
+
+        Args:
+            channel: A grpc.Channel.
+        """
+        self.Parse = channel.unary_unary(
+                '/palm.lily.v1.Excel/Parse',
+                request_serializer=lily__pb2.File.SerializeToString,
+                response_deserializer=lily__pb2.ExcelModel.FromString,
+                )
+        self.Generate = channel.unary_unary(
+                '/palm.lily.v1.Excel/Generate',
+                request_serializer=lily__pb2.ExcelModel.SerializeToString,
+                response_deserializer=lily__pb2.File.FromString,
+                )
+
+
+class ExcelServicer(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def Parse(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+    def Generate(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+
+def add_ExcelServicer_to_server(servicer, server):
+    rpc_method_handlers = {
+            'Parse': grpc.unary_unary_rpc_method_handler(
+                    servicer.Parse,
+                    request_deserializer=lily__pb2.File.FromString,
+                    response_serializer=lily__pb2.ExcelModel.SerializeToString,
+            ),
+            'Generate': grpc.unary_unary_rpc_method_handler(
+                    servicer.Generate,
+                    request_deserializer=lily__pb2.ExcelModel.FromString,
+                    response_serializer=lily__pb2.File.SerializeToString,
+            ),
+    }
+    generic_handler = grpc.method_handlers_generic_handler(
+            'palm.lily.v1.Excel', rpc_method_handlers)
+    server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Excel(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    @staticmethod
+    def Parse(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/palm.lily.v1.Excel/Parse',
+            lily__pb2.File.SerializeToString,
+            lily__pb2.ExcelModel.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+    @staticmethod
+    def Generate(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/palm.lily.v1.Excel/Generate',
+            lily__pb2.ExcelModel.SerializeToString,
+            lily__pb2.File.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+
+class TexStub(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def __init__(self, channel):
+        """Constructor.
+
+        Args:
+            channel: A grpc.Channel.
+        """
+        self.ToPdf = channel.unary_unary(
+                '/palm.lily.v1.Tex/ToPdf',
+                request_serializer=lily__pb2.TexToRequest.SerializeToString,
+                response_deserializer=lily__pb2.File.FromString,
+                )
+        self.ToWord = channel.unary_unary(
+                '/palm.lily.v1.Tex/ToWord',
+                request_serializer=lily__pb2.TexToRequest.SerializeToString,
+                response_deserializer=lily__pb2.File.FromString,
+                )
+
+
+class TexServicer(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def ToPdf(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+    def ToWord(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+
+def add_TexServicer_to_server(servicer, server):
+    rpc_method_handlers = {
+            'ToPdf': grpc.unary_unary_rpc_method_handler(
+                    servicer.ToPdf,
+                    request_deserializer=lily__pb2.TexToRequest.FromString,
+                    response_serializer=lily__pb2.File.SerializeToString,
+            ),
+            'ToWord': grpc.unary_unary_rpc_method_handler(
+                    servicer.ToWord,
+                    request_deserializer=lily__pb2.TexToRequest.FromString,
+                    response_serializer=lily__pb2.File.SerializeToString,
+            ),
+    }
+    generic_handler = grpc.method_handlers_generic_handler(
+            'palm.lily.v1.Tex', rpc_method_handlers)
+    server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Tex(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    @staticmethod
+    def ToPdf(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/palm.lily.v1.Tex/ToPdf',
+            lily__pb2.TexToRequest.SerializeToString,
+            lily__pb2.File.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+    @staticmethod
+    def ToWord(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/palm.lily.v1.Tex/ToWord',
+            lily__pb2.TexToRequest.SerializeToString,
+            lily__pb2.File.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+
+class EpubStub(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def __init__(self, channel):
+        """Constructor.
+
+        Args:
+            channel: A grpc.Channel.
+        """
+        self.Build = channel.unary_unary(
+                '/palm.lily.v1.Epub/Build',
+                request_serializer=lily__pb2.EpubBuildRequest.SerializeToString,
+                response_deserializer=lily__pb2.File.FromString,
+                )
+
+
+class EpubServicer(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    def Build(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+
+def add_EpubServicer_to_server(servicer, server):
+    rpc_method_handlers = {
+            'Build': grpc.unary_unary_rpc_method_handler(
+                    servicer.Build,
+                    request_deserializer=lily__pb2.EpubBuildRequest.FromString,
+                    response_serializer=lily__pb2.File.SerializeToString,
+            ),
+    }
+    generic_handler = grpc.method_handlers_generic_handler(
+            'palm.lily.v1.Epub', rpc_method_handlers)
+    server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Epub(object):
+    """----------------------------------------------------------------------------
+
+    """
+
+    @staticmethod
+    def Build(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/palm.lily.v1.Epub/Build',
+            lily__pb2.EpubBuildRequest.SerializeToString,
+            lily__pb2.File.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

+ 45 - 0
clients/ruby/lily_pb.rb

@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: lily.proto
+
+require 'google/protobuf'
+
+
+descriptor_data = "\n\nlily.proto\x12\x0cpalm.lily.v1\"C\n\x04\x46ile\x12\x19\n\x0c\x63ontent_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x42\x0f\n\r_content_type\"\xb6\x01\n\nExcelModel\x12.\n\x06sheets\x18\x01 \x03(\x0b\x32\x1e.palm.lily.v1.ExcelModel.Sheet\x1ax\n\x05Sheet\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32#.palm.lily.v1.ExcelModel.Sheet.Cell\x1a-\n\x04\x43\x65ll\x12\x0b\n\x03row\x18\x01 \x01(\r\x12\x0b\n\x03\x63ol\x18\x02 \x01(\r\x12\x0b\n\x03val\x18\x03 \x01(\t\"r\n\x0cTexToRequest\x12\x34\n\x05\x66iles\x18\x01 \x03(\x0b\x32%.palm.lily.v1.TexToRequest.FilesEntry\x1a,\n\nFilesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\x12\n\x10\x45pubBuildRequest2|\n\x05\x45xcel\x12\x37\n\x05Parse\x12\x12.palm.lily.v1.File\x1a\x18.palm.lily.v1.ExcelModel\"\x00\x12:\n\x08Generate\x12\x18.palm.lily.v1.ExcelModel\x1a\x12.palm.lily.v1.File\"\x00\x32|\n\x03Tex\x12\x39\n\x05ToPdf\x12\x1a.palm.lily.v1.TexToRequest\x1a\x12.palm.lily.v1.File\"\x00\x12:\n\x06ToWord\x12\x1a.palm.lily.v1.TexToRequest\x1a\x12.palm.lily.v1.File\"\x00\x32\x45\n\x04\x45pub\x12=\n\x05\x42uild\x12\x1e.palm.lily.v1.EpubBuildRequest\x1a\x12.palm.lily.v1.File\"\x00\x42.\n*com.github.saturn_xiv.palm.plugins.lily.v1P\x01\x62\x06proto3"
+
+pool = Google::Protobuf::DescriptorPool.generated_pool
+
+begin
+  pool.add_serialized_file(descriptor_data)
+rescue TypeError => e
+  # Compatibility code: will be removed in the next major version.
+  require 'google/protobuf/descriptor_pb'
+  parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
+  parsed.clear_dependency
+  serialized = parsed.class.encode(parsed)
+  file = pool.add_serialized_file(serialized)
+  warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
+  imports = [
+  ]
+  imports.each do |type_name, expected_filename|
+    import_file = pool.lookup(type_name).file_descriptor
+    if import_file.name != expected_filename
+      warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
+    end
+  end
+  warn "Each proto file must use a consistent fully-qualified name."
+  warn "This will become an error in the next major version."
+end
+
+module Palm
+  module Lily
+    module V1
+      File = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.File").msgclass
+      ExcelModel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.ExcelModel").msgclass
+      ExcelModel::Sheet = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.ExcelModel.Sheet").msgclass
+      ExcelModel::Sheet::Cell = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.ExcelModel.Sheet.Cell").msgclass
+      TexToRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.TexToRequest").msgclass
+      EpubBuildRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("palm.lily.v1.EpubBuildRequest").msgclass
+    end
+  end
+end

+ 62 - 0
clients/ruby/lily_services_pb.rb

@@ -0,0 +1,62 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: lily.proto for package 'palm.lily.v1'
+
+require 'grpc'
+require 'lily_pb'
+
+module Palm
+  module Lily
+    module V1
+      module Excel
+        # ----------------------------------------------------------------------------
+        #
+        class Service
+
+          include ::GRPC::GenericService
+
+          self.marshal_class_method = :encode
+          self.unmarshal_class_method = :decode
+          self.service_name = 'palm.lily.v1.Excel'
+
+          rpc :Parse, ::Palm::Lily::V1::File, ::Palm::Lily::V1::ExcelModel
+          rpc :Generate, ::Palm::Lily::V1::ExcelModel, ::Palm::Lily::V1::File
+        end
+
+        Stub = Service.rpc_stub_class
+      end
+      module Tex
+        # ----------------------------------------------------------------------------
+        #
+        class Service
+
+          include ::GRPC::GenericService
+
+          self.marshal_class_method = :encode
+          self.unmarshal_class_method = :decode
+          self.service_name = 'palm.lily.v1.Tex'
+
+          rpc :ToPdf, ::Palm::Lily::V1::TexToRequest, ::Palm::Lily::V1::File
+          rpc :ToWord, ::Palm::Lily::V1::TexToRequest, ::Palm::Lily::V1::File
+        end
+
+        Stub = Service.rpc_stub_class
+      end
+      module Epub
+        # ----------------------------------------------------------------------------
+        #
+        class Service
+
+          include ::GRPC::GenericService
+
+          self.marshal_class_method = :encode
+          self.unmarshal_class_method = :decode
+          self.service_name = 'palm.lily.v1.Epub'
+
+          rpc :Build, ::Palm::Lily::V1::EpubBuildRequest, ::Palm::Lily::V1::File
+        end
+
+        Stub = Service.rpc_stub_class
+      end
+    end
+  end
+end

+ 0 - 68
clients/schema.sh

@@ -1,68 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export PROTOBUF_ROOT=$HOME/.local
-export WORKSPACE=$PWD
-
-# -----------------------------------------------------------------------------
-
-function generate_grpc_by_lang() {
-    local target=$WORKSPACE/$1
-    echo "generate code for $1"
-    if [ -d $target ]
-    then
-        rm -r $target
-    fi
-    mkdir -p $target
-    $PROTOBUF_ROOT/bin/protoc -I $WORKSPACE/../protocols \
-        -I $PROTOBUF_ROOT/include/google/protobuf \
-        --${1}_out=$target --grpc_out=$target \
-        --plugin=protoc-gen-grpc=$PROTOBUF_ROOT/bin/grpc_${1}_plugin \
-        $WORKSPACE/../protocols/*.proto
-}
-
-function generate_grpc_for_php() {
-    local target=$WORKSPACE/php
-    echo "generate code for php"
-
-    local -a folders=(
-        "GPBMetadata"
-        "Mint"
-    )
-
-    for f in "${folders[@]}"
-    do
-        if [ -d $target/$f ]
-        then
-            rm -r $target/$f
-        fi
-    done
-    mkdir -p $target
-    $PROTOBUF_ROOT/bin/protoc -I $WORKSPACE/../protocols \
-        -I $PROTOBUF_ROOT/include/google/protobuf \
-        --php_out=$target --grpc_out=generate_server:$target \
-        --plugin=protoc-gen-grpc=$PROTOBUF_ROOT/bin/grpc_php_plugin \
-        $WORKSPACE/../protocols/*.proto
-}
-
-# -----------------------------------------------------------------------------
-
-declare -a languages=(
-    "cpp"
-    "python"
-    "ruby"
-    "csharp"
-    "java"
-)
-
-for l in "${languages[@]}"
-do
-    generate_grpc_by_lang $l
-done
-
-generate_grpc_for_php
-# -----------------------------------------------------------------------------
-
-echo 'done.'
-exit 0

+ 300 - 0
dashboard/src/protocols/LilyServiceClientPb.ts

@@ -0,0 +1,300 @@
+/**
+ * @fileoverview gRPC-Web generated client stub for palm.lily.v1
+ * @enhanceable
+ * @public
+ */
+
+// Code generated by protoc-gen-grpc-web. DO NOT EDIT.
+// versions:
+// 	protoc-gen-grpc-web v1.4.2
+// 	protoc              v4.23.4
+// source: lily.proto
+
+
+/* eslint-disable */
+// @ts-nocheck
+
+
+import * as grpcWeb from 'grpc-web';
+
+import * as lily_pb from './lily_pb';
+
+
+export class ExcelClient {
+  client_: grpcWeb.AbstractClientBase;
+  hostname_: string;
+  credentials_: null | { [index: string]: string; };
+  options_: null | { [index: string]: any; };
+
+  constructor (hostname: string,
+               credentials?: null | { [index: string]: string; },
+               options?: null | { [index: string]: any; }) {
+    if (!options) options = {};
+    if (!credentials) credentials = {};
+    options['format'] = 'binary';
+
+    this.client_ = new grpcWeb.GrpcWebClientBase(options);
+    this.hostname_ = hostname.replace(/\/+$/, '');
+    this.credentials_ = credentials;
+    this.options_ = options;
+  }
+
+  methodDescriptorParse = new grpcWeb.MethodDescriptor(
+    '/palm.lily.v1.Excel/Parse',
+    grpcWeb.MethodType.UNARY,
+    lily_pb.File,
+    lily_pb.ExcelModel,
+    (request: lily_pb.File) => {
+      return request.serializeBinary();
+    },
+    lily_pb.ExcelModel.deserializeBinary
+  );
+
+  parse(
+    request: lily_pb.File,
+    metadata: grpcWeb.Metadata | null): Promise<lily_pb.ExcelModel>;
+
+  parse(
+    request: lily_pb.File,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: lily_pb.ExcelModel) => void): grpcWeb.ClientReadableStream<lily_pb.ExcelModel>;
+
+  parse(
+    request: lily_pb.File,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: lily_pb.ExcelModel) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/palm.lily.v1.Excel/Parse',
+        request,
+        metadata || {},
+        this.methodDescriptorParse,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/palm.lily.v1.Excel/Parse',
+    request,
+    metadata || {},
+    this.methodDescriptorParse);
+  }
+
+  methodDescriptorGenerate = new grpcWeb.MethodDescriptor(
+    '/palm.lily.v1.Excel/Generate',
+    grpcWeb.MethodType.UNARY,
+    lily_pb.ExcelModel,
+    lily_pb.File,
+    (request: lily_pb.ExcelModel) => {
+      return request.serializeBinary();
+    },
+    lily_pb.File.deserializeBinary
+  );
+
+  generate(
+    request: lily_pb.ExcelModel,
+    metadata: grpcWeb.Metadata | null): Promise<lily_pb.File>;
+
+  generate(
+    request: lily_pb.ExcelModel,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void): grpcWeb.ClientReadableStream<lily_pb.File>;
+
+  generate(
+    request: lily_pb.ExcelModel,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/palm.lily.v1.Excel/Generate',
+        request,
+        metadata || {},
+        this.methodDescriptorGenerate,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/palm.lily.v1.Excel/Generate',
+    request,
+    metadata || {},
+    this.methodDescriptorGenerate);
+  }
+
+}
+
+export class TexClient {
+  client_: grpcWeb.AbstractClientBase;
+  hostname_: string;
+  credentials_: null | { [index: string]: string; };
+  options_: null | { [index: string]: any; };
+
+  constructor (hostname: string,
+               credentials?: null | { [index: string]: string; },
+               options?: null | { [index: string]: any; }) {
+    if (!options) options = {};
+    if (!credentials) credentials = {};
+    options['format'] = 'binary';
+
+    this.client_ = new grpcWeb.GrpcWebClientBase(options);
+    this.hostname_ = hostname.replace(/\/+$/, '');
+    this.credentials_ = credentials;
+    this.options_ = options;
+  }
+
+  methodDescriptorToPdf = new grpcWeb.MethodDescriptor(
+    '/palm.lily.v1.Tex/ToPdf',
+    grpcWeb.MethodType.UNARY,
+    lily_pb.TexToRequest,
+    lily_pb.File,
+    (request: lily_pb.TexToRequest) => {
+      return request.serializeBinary();
+    },
+    lily_pb.File.deserializeBinary
+  );
+
+  toPdf(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null): Promise<lily_pb.File>;
+
+  toPdf(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void): grpcWeb.ClientReadableStream<lily_pb.File>;
+
+  toPdf(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/palm.lily.v1.Tex/ToPdf',
+        request,
+        metadata || {},
+        this.methodDescriptorToPdf,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/palm.lily.v1.Tex/ToPdf',
+    request,
+    metadata || {},
+    this.methodDescriptorToPdf);
+  }
+
+  methodDescriptorToWord = new grpcWeb.MethodDescriptor(
+    '/palm.lily.v1.Tex/ToWord',
+    grpcWeb.MethodType.UNARY,
+    lily_pb.TexToRequest,
+    lily_pb.File,
+    (request: lily_pb.TexToRequest) => {
+      return request.serializeBinary();
+    },
+    lily_pb.File.deserializeBinary
+  );
+
+  toWord(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null): Promise<lily_pb.File>;
+
+  toWord(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void): grpcWeb.ClientReadableStream<lily_pb.File>;
+
+  toWord(
+    request: lily_pb.TexToRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/palm.lily.v1.Tex/ToWord',
+        request,
+        metadata || {},
+        this.methodDescriptorToWord,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/palm.lily.v1.Tex/ToWord',
+    request,
+    metadata || {},
+    this.methodDescriptorToWord);
+  }
+
+}
+
+export class EpubClient {
+  client_: grpcWeb.AbstractClientBase;
+  hostname_: string;
+  credentials_: null | { [index: string]: string; };
+  options_: null | { [index: string]: any; };
+
+  constructor (hostname: string,
+               credentials?: null | { [index: string]: string; },
+               options?: null | { [index: string]: any; }) {
+    if (!options) options = {};
+    if (!credentials) credentials = {};
+    options['format'] = 'binary';
+
+    this.client_ = new grpcWeb.GrpcWebClientBase(options);
+    this.hostname_ = hostname.replace(/\/+$/, '');
+    this.credentials_ = credentials;
+    this.options_ = options;
+  }
+
+  methodDescriptorBuild = new grpcWeb.MethodDescriptor(
+    '/palm.lily.v1.Epub/Build',
+    grpcWeb.MethodType.UNARY,
+    lily_pb.EpubBuildRequest,
+    lily_pb.File,
+    (request: lily_pb.EpubBuildRequest) => {
+      return request.serializeBinary();
+    },
+    lily_pb.File.deserializeBinary
+  );
+
+  build(
+    request: lily_pb.EpubBuildRequest,
+    metadata: grpcWeb.Metadata | null): Promise<lily_pb.File>;
+
+  build(
+    request: lily_pb.EpubBuildRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void): grpcWeb.ClientReadableStream<lily_pb.File>;
+
+  build(
+    request: lily_pb.EpubBuildRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: lily_pb.File) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/palm.lily.v1.Epub/Build',
+        request,
+        metadata || {},
+        this.methodDescriptorBuild,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/palm.lily.v1.Epub/Build',
+    request,
+    metadata || {},
+    this.methodDescriptorBuild);
+  }
+
+}
+

+ 86 - 0
dashboard/src/protocols/MorusServiceClientPb.ts

@@ -0,0 +1,86 @@
+/**
+ * @fileoverview gRPC-Web generated client stub for mint.morus.v1
+ * @enhanceable
+ * @public
+ */
+
+// Code generated by protoc-gen-grpc-web. DO NOT EDIT.
+// versions:
+// 	protoc-gen-grpc-web v1.4.2
+// 	protoc              v4.23.4
+// source: morus.proto
+
+
+/* eslint-disable */
+// @ts-nocheck
+
+
+import * as grpcWeb from 'grpc-web';
+
+import * as morus_pb from './morus_pb';
+
+
+export class MarkdownClient {
+  client_: grpcWeb.AbstractClientBase;
+  hostname_: string;
+  credentials_: null | { [index: string]: string; };
+  options_: null | { [index: string]: any; };
+
+  constructor (hostname: string,
+               credentials?: null | { [index: string]: string; },
+               options?: null | { [index: string]: any; }) {
+    if (!options) options = {};
+    if (!credentials) credentials = {};
+    options['format'] = 'binary';
+
+    this.client_ = new grpcWeb.GrpcWebClientBase(options);
+    this.hostname_ = hostname.replace(/\/+$/, '');
+    this.credentials_ = credentials;
+    this.options_ = options;
+  }
+
+  methodDescriptorToHtml = new grpcWeb.MethodDescriptor(
+    '/mint.morus.v1.Markdown/ToHtml',
+    grpcWeb.MethodType.UNARY,
+    morus_pb.MarkdownToHtmlRequest,
+    morus_pb.MarkdownToHtmlResponse,
+    (request: morus_pb.MarkdownToHtmlRequest) => {
+      return request.serializeBinary();
+    },
+    morus_pb.MarkdownToHtmlResponse.deserializeBinary
+  );
+
+  toHtml(
+    request: morus_pb.MarkdownToHtmlRequest,
+    metadata: grpcWeb.Metadata | null): Promise<morus_pb.MarkdownToHtmlResponse>;
+
+  toHtml(
+    request: morus_pb.MarkdownToHtmlRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback: (err: grpcWeb.RpcError,
+               response: morus_pb.MarkdownToHtmlResponse) => void): grpcWeb.ClientReadableStream<morus_pb.MarkdownToHtmlResponse>;
+
+  toHtml(
+    request: morus_pb.MarkdownToHtmlRequest,
+    metadata: grpcWeb.Metadata | null,
+    callback?: (err: grpcWeb.RpcError,
+               response: morus_pb.MarkdownToHtmlResponse) => void) {
+    if (callback !== undefined) {
+      return this.client_.rpcCall(
+        this.hostname_ +
+          '/mint.morus.v1.Markdown/ToHtml',
+        request,
+        metadata || {},
+        this.methodDescriptorToHtml,
+        callback);
+    }
+    return this.client_.unaryCall(
+    this.hostname_ +
+      '/mint.morus.v1.Markdown/ToHtml',
+    request,
+    metadata || {},
+    this.methodDescriptorToHtml);
+  }
+
+}
+

+ 139 - 0
dashboard/src/protocols/lily_pb.d.ts

@@ -0,0 +1,139 @@
+import * as jspb from 'google-protobuf'
+
+
+
+export class File extends jspb.Message {
+  getContentType(): string;
+  setContentType(value: string): File;
+  hasContentType(): boolean;
+  clearContentType(): File;
+
+  getPayload(): Uint8Array | string;
+  getPayload_asU8(): Uint8Array;
+  getPayload_asB64(): string;
+  setPayload(value: Uint8Array | string): File;
+
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): File.AsObject;
+  static toObject(includeInstance: boolean, msg: File): File.AsObject;
+  static serializeBinaryToWriter(message: File, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): File;
+  static deserializeBinaryFromReader(message: File, reader: jspb.BinaryReader): File;
+}
+
+export namespace File {
+  export type AsObject = {
+    contentType?: string,
+    payload: Uint8Array | string,
+  }
+
+  export enum ContentTypeCase { 
+    _CONTENT_TYPE_NOT_SET = 0,
+    CONTENT_TYPE = 1,
+  }
+}
+
+export class ExcelModel extends jspb.Message {
+  getSheetsList(): Array<ExcelModel.Sheet>;
+  setSheetsList(value: Array<ExcelModel.Sheet>): ExcelModel;
+  clearSheetsList(): ExcelModel;
+  addSheets(value?: ExcelModel.Sheet, index?: number): ExcelModel.Sheet;
+
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): ExcelModel.AsObject;
+  static toObject(includeInstance: boolean, msg: ExcelModel): ExcelModel.AsObject;
+  static serializeBinaryToWriter(message: ExcelModel, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): ExcelModel;
+  static deserializeBinaryFromReader(message: ExcelModel, reader: jspb.BinaryReader): ExcelModel;
+}
+
+export namespace ExcelModel {
+  export type AsObject = {
+    sheetsList: Array<ExcelModel.Sheet.AsObject>,
+  }
+
+  export class Sheet extends jspb.Message {
+    getName(): string;
+    setName(value: string): Sheet;
+
+    getCellsList(): Array<ExcelModel.Sheet.Cell>;
+    setCellsList(value: Array<ExcelModel.Sheet.Cell>): Sheet;
+    clearCellsList(): Sheet;
+    addCells(value?: ExcelModel.Sheet.Cell, index?: number): ExcelModel.Sheet.Cell;
+
+    serializeBinary(): Uint8Array;
+    toObject(includeInstance?: boolean): Sheet.AsObject;
+    static toObject(includeInstance: boolean, msg: Sheet): Sheet.AsObject;
+    static serializeBinaryToWriter(message: Sheet, writer: jspb.BinaryWriter): void;
+    static deserializeBinary(bytes: Uint8Array): Sheet;
+    static deserializeBinaryFromReader(message: Sheet, reader: jspb.BinaryReader): Sheet;
+  }
+
+  export namespace Sheet {
+    export type AsObject = {
+      name: string,
+      cellsList: Array<ExcelModel.Sheet.Cell.AsObject>,
+    }
+
+    export class Cell extends jspb.Message {
+      getRow(): number;
+      setRow(value: number): Cell;
+
+      getCol(): number;
+      setCol(value: number): Cell;
+
+      getVal(): string;
+      setVal(value: string): Cell;
+
+      serializeBinary(): Uint8Array;
+      toObject(includeInstance?: boolean): Cell.AsObject;
+      static toObject(includeInstance: boolean, msg: Cell): Cell.AsObject;
+      static serializeBinaryToWriter(message: Cell, writer: jspb.BinaryWriter): void;
+      static deserializeBinary(bytes: Uint8Array): Cell;
+      static deserializeBinaryFromReader(message: Cell, reader: jspb.BinaryReader): Cell;
+    }
+
+    export namespace Cell {
+      export type AsObject = {
+        row: number,
+        col: number,
+        val: string,
+      }
+    }
+
+  }
+
+}
+
+export class TexToRequest extends jspb.Message {
+  getFilesMap(): jspb.Map<string, Uint8Array | string>;
+  clearFilesMap(): TexToRequest;
+
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): TexToRequest.AsObject;
+  static toObject(includeInstance: boolean, msg: TexToRequest): TexToRequest.AsObject;
+  static serializeBinaryToWriter(message: TexToRequest, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): TexToRequest;
+  static deserializeBinaryFromReader(message: TexToRequest, reader: jspb.BinaryReader): TexToRequest;
+}
+
+export namespace TexToRequest {
+  export type AsObject = {
+    filesMap: Array<[string, Uint8Array | string]>,
+  }
+}
+
+export class EpubBuildRequest extends jspb.Message {
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): EpubBuildRequest.AsObject;
+  static toObject(includeInstance: boolean, msg: EpubBuildRequest): EpubBuildRequest.AsObject;
+  static serializeBinaryToWriter(message: EpubBuildRequest, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): EpubBuildRequest;
+  static deserializeBinaryFromReader(message: EpubBuildRequest, reader: jspb.BinaryReader): EpubBuildRequest;
+}
+
+export namespace EpubBuildRequest {
+  export type AsObject = {
+  }
+}
+

+ 1133 - 0
dashboard/src/protocols/lily_pb.js

@@ -0,0 +1,1133 @@
+// source: lily.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {missingRequire} reports error on implicit type usages.
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global =
+    (typeof globalThis !== 'undefined' && globalThis) ||
+    (typeof window !== 'undefined' && window) ||
+    (typeof global !== 'undefined' && global) ||
+    (typeof self !== 'undefined' && self) ||
+    (function () { return this; }).call(null) ||
+    Function('return this')();
+
+goog.exportSymbol('proto.palm.lily.v1.EpubBuildRequest', null, global);
+goog.exportSymbol('proto.palm.lily.v1.ExcelModel', null, global);
+goog.exportSymbol('proto.palm.lily.v1.ExcelModel.Sheet', null, global);
+goog.exportSymbol('proto.palm.lily.v1.ExcelModel.Sheet.Cell', null, global);
+goog.exportSymbol('proto.palm.lily.v1.File', null, global);
+goog.exportSymbol('proto.palm.lily.v1.TexToRequest', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.File = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.palm.lily.v1.File, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.File.displayName = 'proto.palm.lily.v1.File';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.ExcelModel = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.palm.lily.v1.ExcelModel.repeatedFields_, null);
+};
+goog.inherits(proto.palm.lily.v1.ExcelModel, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.ExcelModel.displayName = 'proto.palm.lily.v1.ExcelModel';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.ExcelModel.Sheet = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.palm.lily.v1.ExcelModel.Sheet.repeatedFields_, null);
+};
+goog.inherits(proto.palm.lily.v1.ExcelModel.Sheet, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.ExcelModel.Sheet.displayName = 'proto.palm.lily.v1.ExcelModel.Sheet';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.palm.lily.v1.ExcelModel.Sheet.Cell, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.ExcelModel.Sheet.Cell.displayName = 'proto.palm.lily.v1.ExcelModel.Sheet.Cell';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.TexToRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.palm.lily.v1.TexToRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.TexToRequest.displayName = 'proto.palm.lily.v1.TexToRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.palm.lily.v1.EpubBuildRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.palm.lily.v1.EpubBuildRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.palm.lily.v1.EpubBuildRequest.displayName = 'proto.palm.lily.v1.EpubBuildRequest';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.File.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.File.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.File} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.File.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    contentType: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    payload: msg.getPayload_asB64()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.File}
+ */
+proto.palm.lily.v1.File.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.File;
+  return proto.palm.lily.v1.File.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.File} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.File}
+ */
+proto.palm.lily.v1.File.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setContentType(value);
+      break;
+    case 2:
+      var value = /** @type {!Uint8Array} */ (reader.readBytes());
+      msg.setPayload(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.File.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.File.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.File} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.File.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = /** @type {string} */ (jspb.Message.getField(message, 1));
+  if (f != null) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getPayload_asU8();
+  if (f.length > 0) {
+    writer.writeBytes(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional string content_type = 1;
+ * @return {string}
+ */
+proto.palm.lily.v1.File.prototype.getContentType = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.palm.lily.v1.File} returns this
+ */
+proto.palm.lily.v1.File.prototype.setContentType = function(value) {
+  return jspb.Message.setField(this, 1, value);
+};
+
+
+/**
+ * Clears the field making it undefined.
+ * @return {!proto.palm.lily.v1.File} returns this
+ */
+proto.palm.lily.v1.File.prototype.clearContentType = function() {
+  return jspb.Message.setField(this, 1, undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.palm.lily.v1.File.prototype.hasContentType = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+/**
+ * optional bytes payload = 2;
+ * @return {!(string|Uint8Array)}
+ */
+proto.palm.lily.v1.File.prototype.getPayload = function() {
+  return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
+};
+
+
+/**
+ * optional bytes payload = 2;
+ * This is a type-conversion wrapper around `getPayload()`
+ * @return {string}
+ */
+proto.palm.lily.v1.File.prototype.getPayload_asB64 = function() {
+  return /** @type {string} */ (jspb.Message.bytesAsB64(
+      this.getPayload()));
+};
+
+
+/**
+ * optional bytes payload = 2;
+ * Note that Uint8Array is not supported on all browsers.
+ * @see http://caniuse.com/Uint8Array
+ * This is a type-conversion wrapper around `getPayload()`
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.File.prototype.getPayload_asU8 = function() {
+  return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(
+      this.getPayload()));
+};
+
+
+/**
+ * @param {!(string|Uint8Array)} value
+ * @return {!proto.palm.lily.v1.File} returns this
+ */
+proto.palm.lily.v1.File.prototype.setPayload = function(value) {
+  return jspb.Message.setProto3BytesField(this, 2, value);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.palm.lily.v1.ExcelModel.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.ExcelModel.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.ExcelModel.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.ExcelModel} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    sheetsList: jspb.Message.toObjectList(msg.getSheetsList(),
+    proto.palm.lily.v1.ExcelModel.Sheet.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.ExcelModel}
+ */
+proto.palm.lily.v1.ExcelModel.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.ExcelModel;
+  return proto.palm.lily.v1.ExcelModel.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.ExcelModel} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.ExcelModel}
+ */
+proto.palm.lily.v1.ExcelModel.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.palm.lily.v1.ExcelModel.Sheet;
+      reader.readMessage(value,proto.palm.lily.v1.ExcelModel.Sheet.deserializeBinaryFromReader);
+      msg.addSheets(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.ExcelModel.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.ExcelModel.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.ExcelModel} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getSheetsList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      proto.palm.lily.v1.ExcelModel.Sheet.serializeBinaryToWriter
+    );
+  }
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.repeatedFields_ = [2];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.ExcelModel.Sheet.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    name: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    cellsList: jspb.Message.toObjectList(msg.getCellsList(),
+    proto.palm.lily.v1.ExcelModel.Sheet.Cell.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.ExcelModel.Sheet;
+  return proto.palm.lily.v1.ExcelModel.Sheet.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setName(value);
+      break;
+    case 2:
+      var value = new proto.palm.lily.v1.ExcelModel.Sheet.Cell;
+      reader.readMessage(value,proto.palm.lily.v1.ExcelModel.Sheet.Cell.deserializeBinaryFromReader);
+      msg.addCells(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.ExcelModel.Sheet.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getName();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getCellsList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      2,
+      f,
+      proto.palm.lily.v1.ExcelModel.Sheet.Cell.serializeBinaryToWriter
+    );
+  }
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.ExcelModel.Sheet.Cell.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    row: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    col: jspb.Message.getFieldWithDefault(msg, 2, 0),
+    val: jspb.Message.getFieldWithDefault(msg, 3, "")
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.ExcelModel.Sheet.Cell;
+  return proto.palm.lily.v1.ExcelModel.Sheet.Cell.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readUint32());
+      msg.setRow(value);
+      break;
+    case 2:
+      var value = /** @type {number} */ (reader.readUint32());
+      msg.setCol(value);
+      break;
+    case 3:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setVal(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.ExcelModel.Sheet.Cell.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getRow();
+  if (f !== 0) {
+    writer.writeUint32(
+      1,
+      f
+    );
+  }
+  f = message.getCol();
+  if (f !== 0) {
+    writer.writeUint32(
+      2,
+      f
+    );
+  }
+  f = message.getVal();
+  if (f.length > 0) {
+    writer.writeString(
+      3,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional uint32 row = 1;
+ * @return {number}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.getRow = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} returns this
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.setRow = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional uint32 col = 2;
+ * @return {number}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.getCol = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} returns this
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.setCol = function(value) {
+  return jspb.Message.setProto3IntField(this, 2, value);
+};
+
+
+/**
+ * optional string val = 3;
+ * @return {string}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.getVal = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell} returns this
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.Cell.prototype.setVal = function(value) {
+  return jspb.Message.setProto3StringField(this, 3, value);
+};
+
+
+/**
+ * optional string name = 1;
+ * @return {string}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.getName = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet} returns this
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.setName = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+/**
+ * repeated Cell cells = 2;
+ * @return {!Array<!proto.palm.lily.v1.ExcelModel.Sheet.Cell>}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.getCellsList = function() {
+  return /** @type{!Array<!proto.palm.lily.v1.ExcelModel.Sheet.Cell>} */ (
+    jspb.Message.getRepeatedWrapperField(this, proto.palm.lily.v1.ExcelModel.Sheet.Cell, 2));
+};
+
+
+/**
+ * @param {!Array<!proto.palm.lily.v1.ExcelModel.Sheet.Cell>} value
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet} returns this
+*/
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.setCellsList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 2, value);
+};
+
+
+/**
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet.Cell=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet.Cell}
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.addCells = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.palm.lily.v1.ExcelModel.Sheet.Cell, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet} returns this
+ */
+proto.palm.lily.v1.ExcelModel.Sheet.prototype.clearCellsList = function() {
+  return this.setCellsList([]);
+};
+
+
+/**
+ * repeated Sheet sheets = 1;
+ * @return {!Array<!proto.palm.lily.v1.ExcelModel.Sheet>}
+ */
+proto.palm.lily.v1.ExcelModel.prototype.getSheetsList = function() {
+  return /** @type{!Array<!proto.palm.lily.v1.ExcelModel.Sheet>} */ (
+    jspb.Message.getRepeatedWrapperField(this, proto.palm.lily.v1.ExcelModel.Sheet, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.palm.lily.v1.ExcelModel.Sheet>} value
+ * @return {!proto.palm.lily.v1.ExcelModel} returns this
+*/
+proto.palm.lily.v1.ExcelModel.prototype.setSheetsList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.palm.lily.v1.ExcelModel.Sheet=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.palm.lily.v1.ExcelModel.Sheet}
+ */
+proto.palm.lily.v1.ExcelModel.prototype.addSheets = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.palm.lily.v1.ExcelModel.Sheet, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.palm.lily.v1.ExcelModel} returns this
+ */
+proto.palm.lily.v1.ExcelModel.prototype.clearSheetsList = function() {
+  return this.setSheetsList([]);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.TexToRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.TexToRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.TexToRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.TexToRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    filesMap: (f = msg.getFilesMap()) ? f.toObject(includeInstance, undefined) : []
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.TexToRequest}
+ */
+proto.palm.lily.v1.TexToRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.TexToRequest;
+  return proto.palm.lily.v1.TexToRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.TexToRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.TexToRequest}
+ */
+proto.palm.lily.v1.TexToRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = msg.getFilesMap();
+      reader.readMessage(value, function(message, reader) {
+        jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readBytes, null, "", "");
+         });
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.TexToRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.TexToRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.TexToRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.TexToRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getFilesMap(true);
+  if (f && f.getLength() > 0) {
+    f.serializeBinary(1, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeBytes);
+  }
+};
+
+
+/**
+ * map<string, bytes> files = 1;
+ * @param {boolean=} opt_noLazyCreate Do not create the map if
+ * empty, instead returning `undefined`
+ * @return {!jspb.Map<string,!(string|Uint8Array)>}
+ */
+proto.palm.lily.v1.TexToRequest.prototype.getFilesMap = function(opt_noLazyCreate) {
+  return /** @type {!jspb.Map<string,!(string|Uint8Array)>} */ (
+      jspb.Message.getMapField(this, 1, opt_noLazyCreate,
+      null));
+};
+
+
+/**
+ * Clears values from the map. The map will be non-null.
+ * @return {!proto.palm.lily.v1.TexToRequest} returns this
+ */
+proto.palm.lily.v1.TexToRequest.prototype.clearFilesMap = function() {
+  this.getFilesMap().clear();
+  return this;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.palm.lily.v1.EpubBuildRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.palm.lily.v1.EpubBuildRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.palm.lily.v1.EpubBuildRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.EpubBuildRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.palm.lily.v1.EpubBuildRequest}
+ */
+proto.palm.lily.v1.EpubBuildRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.palm.lily.v1.EpubBuildRequest;
+  return proto.palm.lily.v1.EpubBuildRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.palm.lily.v1.EpubBuildRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.palm.lily.v1.EpubBuildRequest}
+ */
+proto.palm.lily.v1.EpubBuildRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.palm.lily.v1.EpubBuildRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.palm.lily.v1.EpubBuildRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.palm.lily.v1.EpubBuildRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.palm.lily.v1.EpubBuildRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+goog.object.extend(exports, proto.palm.lily.v1);

+ 44 - 0
dashboard/src/protocols/morus_pb.d.ts

@@ -0,0 +1,44 @@
+import * as jspb from 'google-protobuf'
+
+
+
+export class MarkdownToHtmlRequest extends jspb.Message {
+  getPayload(): string;
+  setPayload(value: string): MarkdownToHtmlRequest;
+
+  getSanitize(): boolean;
+  setSanitize(value: boolean): MarkdownToHtmlRequest;
+
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): MarkdownToHtmlRequest.AsObject;
+  static toObject(includeInstance: boolean, msg: MarkdownToHtmlRequest): MarkdownToHtmlRequest.AsObject;
+  static serializeBinaryToWriter(message: MarkdownToHtmlRequest, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): MarkdownToHtmlRequest;
+  static deserializeBinaryFromReader(message: MarkdownToHtmlRequest, reader: jspb.BinaryReader): MarkdownToHtmlRequest;
+}
+
+export namespace MarkdownToHtmlRequest {
+  export type AsObject = {
+    payload: string,
+    sanitize: boolean,
+  }
+}
+
+export class MarkdownToHtmlResponse extends jspb.Message {
+  getPayload(): string;
+  setPayload(value: string): MarkdownToHtmlResponse;
+
+  serializeBinary(): Uint8Array;
+  toObject(includeInstance?: boolean): MarkdownToHtmlResponse.AsObject;
+  static toObject(includeInstance: boolean, msg: MarkdownToHtmlResponse): MarkdownToHtmlResponse.AsObject;
+  static serializeBinaryToWriter(message: MarkdownToHtmlResponse, writer: jspb.BinaryWriter): void;
+  static deserializeBinary(bytes: Uint8Array): MarkdownToHtmlResponse;
+  static deserializeBinaryFromReader(message: MarkdownToHtmlResponse, reader: jspb.BinaryReader): MarkdownToHtmlResponse;
+}
+
+export namespace MarkdownToHtmlResponse {
+  export type AsObject = {
+    payload: string,
+  }
+}
+

+ 358 - 0
dashboard/src/protocols/morus_pb.js

@@ -0,0 +1,358 @@
+// source: morus.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {missingRequire} reports error on implicit type usages.
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global =
+    (typeof globalThis !== 'undefined' && globalThis) ||
+    (typeof window !== 'undefined' && window) ||
+    (typeof global !== 'undefined' && global) ||
+    (typeof self !== 'undefined' && self) ||
+    (function () { return this; }).call(null) ||
+    Function('return this')();
+
+goog.exportSymbol('proto.mint.morus.v1.MarkdownToHtmlRequest', null, global);
+goog.exportSymbol('proto.mint.morus.v1.MarkdownToHtmlResponse', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.mint.morus.v1.MarkdownToHtmlRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.mint.morus.v1.MarkdownToHtmlRequest.displayName = 'proto.mint.morus.v1.MarkdownToHtmlRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.mint.morus.v1.MarkdownToHtmlResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.mint.morus.v1.MarkdownToHtmlResponse.displayName = 'proto.mint.morus.v1.MarkdownToHtmlResponse';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.mint.morus.v1.MarkdownToHtmlRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    payload: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    sanitize: jspb.Message.getBooleanFieldWithDefault(msg, 2, false)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlRequest}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.mint.morus.v1.MarkdownToHtmlRequest;
+  return proto.mint.morus.v1.MarkdownToHtmlRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlRequest}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setPayload(value);
+      break;
+    case 2:
+      var value = /** @type {boolean} */ (reader.readBool());
+      msg.setSanitize(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.mint.morus.v1.MarkdownToHtmlRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getPayload();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getSanitize();
+  if (f) {
+    writer.writeBool(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional string payload = 1;
+ * @return {string}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.getPayload = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlRequest} returns this
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.setPayload = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+/**
+ * optional bool sanitize = 2;
+ * @return {boolean}
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.getSanitize = function() {
+  return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));
+};
+
+
+/**
+ * @param {boolean} value
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlRequest} returns this
+ */
+proto.mint.morus.v1.MarkdownToHtmlRequest.prototype.setSanitize = function(value) {
+  return jspb.Message.setProto3BooleanField(this, 2, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.mint.morus.v1.MarkdownToHtmlResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    payload: jspb.Message.getFieldWithDefault(msg, 1, "")
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlResponse}
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.mint.morus.v1.MarkdownToHtmlResponse;
+  return proto.mint.morus.v1.MarkdownToHtmlResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlResponse}
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setPayload(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.mint.morus.v1.MarkdownToHtmlResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.mint.morus.v1.MarkdownToHtmlResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getPayload();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional string payload = 1;
+ * @return {string}
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.prototype.getPayload = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.mint.morus.v1.MarkdownToHtmlResponse} returns this
+ */
+proto.mint.morus.v1.MarkdownToHtmlResponse.prototype.setPayload = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+goog.object.extend(exports, proto.mint.morus.v1);

+ 46 - 0
protocols/lily.proto

@@ -0,0 +1,46 @@
+syntax = "proto3";
+option java_multiple_files = true;
+option java_package = "com.github.saturn_xiv.palm.plugins.lily.v1";
+package palm.lily.v1;
+
+message File {
+  optional string content_type = 1;
+  bytes payload = 2;
+}
+
+// ----------------------------------------------------------------------------
+
+service Excel {
+  rpc Parse(File) returns (ExcelModel) {}
+  rpc Generate(ExcelModel) returns (File) {}
+}
+
+message ExcelModel {
+  message Sheet {
+    message Cell {
+      uint32 row = 1;
+      uint32 col = 2;
+      string val = 3;
+    }
+    string name = 1;
+    repeated Cell cells = 2;
+  }
+  repeated Sheet sheets = 1;
+}
+
+// ----------------------------------------------------------------------------
+
+service Tex {
+  rpc ToPdf(TexToRequest) returns (File) {}
+  rpc ToWord(TexToRequest) returns (File) {}
+}
+
+message TexToRequest { map<string, bytes> files = 1; }
+
+// ----------------------------------------------------------------------------
+
+service Epub {
+  rpc Build(EpubBuildRequest) returns (File) {}
+}
+
+message EpubBuildRequest {}

+ 24 - 9
scripts/schema.sh

@@ -8,11 +8,29 @@ export WORKSPACE=$PWD
 # -----------------------------------------------------------------------------
 
 function generate_grpc_by_lang() {
-    local target=$WORKSPACE/tmp/protocols/$1
+    local target=$WORKSPACE/clients/$1
     echo "generate code for grpc-$1"
+    
     if [ -d $target ]
     then
-        rm -r $target
+        if [[ "$1" == "php" ]]
+        then
+            declare -a folders=(
+                "GPBMetadata"
+                "Mint"
+                "Palm"
+            )
+            for f in "${folders[@]}"
+            do
+                local t=$target/$1/$f
+                if [ -d $t ]
+                then
+                    rm -f $t
+                fi
+            done            
+        else
+            rm -r $target
+        fi
     fi
     mkdir -p $target
     $PROTOBUF_ROOT/bin/protoc -I $WORKSPACE/protocols \
@@ -48,16 +66,13 @@ function generate_grpc_web() {
 
 # -----------------------------------------------------------------------------
 
-declare -a languages=(
-    # "node"
-    "php"
+declare -a languages=(    
     "python"
     "ruby"
     "cpp"
-    "csharp"
-    # https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/
-    "java" 
-    # "objective_c"
+    "csharp"    
+    "java"
+    "php"
 )
 
 for l in "${languages[@]}"