void TemplightProtobufWriter::printEntry(const PrintableTemplightEntryBegin& aEntry) {
  
  std::string entry_contents;
  {
    llvm::raw_string_ostream OS_inner(entry_contents);
    
    /*
  message Begin {
    required InstantiationKind kind = 1;
    required string name = 2;
    required SourceLocation location = 3;
    optional double time_stamp = 4;
    optional uint64 memory_usage = 5;
    optional SourceLocation template_origin = 6;
  }
    */
    
    llvm::protobuf::saveVarInt(OS_inner, 1, aEntry.InstantiationKind);    // kind
    llvm::protobuf::saveString(OS_inner, 2, 
                         printTemplateName(aEntry.Name));                 // name
    llvm::protobuf::saveString(OS_inner, 3, 
                               printEntryLocation(aEntry.FileName, 
                                                  aEntry.Line, 
                                                  aEntry.Column)); // location
    llvm::protobuf::saveDouble(OS_inner, 4, aEntry.TimeStamp);            // time_stamp
    if ( aEntry.MemoryUsage > 0 )
      llvm::protobuf::saveVarInt(OS_inner, 5, aEntry.MemoryUsage);        // memory_usage
    if ( !aEntry.TempOri_FileName.empty() )
      llvm::protobuf::saveString(OS_inner, 6, 
                                 printEntryLocation(aEntry.TempOri_FileName, 
                                                    aEntry.TempOri_Line, 
                                                    aEntry.TempOri_Column)); // template_origin
  }
  
  std::string oneof_contents;
  {
    llvm::raw_string_ostream OS_inner(oneof_contents);
    
    /*
  oneof begin_or_end {
    Begin begin = 1;
    End end = 2;
  } 
     */
    
    llvm::protobuf::saveString(OS_inner, 1, entry_contents); // begin
    
  }
  
  llvm::raw_string_ostream OS(buffer);
  
  // repeated TemplightEntry entries = 2;
  llvm::protobuf::saveString(OS, 2, oneof_contents);
  
}
std::string
TemplightProtobufWriter::printEntryLocation(const std::string &FileName,
                                            int Line, int Column) {

  /*
  message SourceLocation {
    optional string file_name = 1;
    required uint32 file_id = 2;
    required uint32 line = 3;
    optional uint32 column = 4;
  }
  */

  std::string location_contents;
  llvm::raw_string_ostream OS_inner(location_contents);

  std::unordered_map<std::string, std::size_t>::iterator it =
      fileNameMap.find(FileName);

  if (it == fileNameMap.end()) {
    llvm::protobuf::saveString(OS_inner, 1, FileName); // file_name
    std::size_t file_id = fileNameMap.size();
    llvm::protobuf::saveVarInt(OS_inner, 2, file_id); // file_id
    fileNameMap[FileName] = file_id;
  } else {
    llvm::protobuf::saveVarInt(OS_inner, 2, it->second); // file_id
  }

  llvm::protobuf::saveVarInt(OS_inner, 3, Line);   // line
  llvm::protobuf::saveVarInt(OS_inner, 4, Column); // column

  OS_inner.str();

  return location_contents; // NRVO
}
void TemplightProtobufWriter::printEntry(const PrintableTemplightEntryEnd& aEntry) {
  
  std::string entry_contents;
  {
    llvm::raw_string_ostream OS_inner(entry_contents);
    
    /*
  message End {
    optional double time_stamp = 1;
    optional uint64 memory_usage = 2;
  }
    */
    
    llvm::protobuf::saveDouble(OS_inner, 1, aEntry.TimeStamp);     // time_stamp
    if ( aEntry.MemoryUsage > 0 )
      llvm::protobuf::saveVarInt(OS_inner, 2, aEntry.MemoryUsage); // memory_usage
    
  }
  
  std::string oneof_contents;
  {
    llvm::raw_string_ostream OS_inner(oneof_contents);
    
    /*
  oneof begin_or_end {
    Begin begin = 1;
    End end = 2;
  } 
     */
    
    llvm::protobuf::saveString(OS_inner, 2, entry_contents); // end
    
  }
  
  llvm::raw_string_ostream OS(buffer);
  
  // repeated TemplightEntry entries = 2;
  llvm::protobuf::saveString(OS, 2, oneof_contents);
  
}
std::string
TemplightProtobufWriter::printTemplateName(const std::string &Name) {

  /*
  message TemplateName {
    optional string name = 1;
    optional bytes compressed_name = 2;
  }
  */

  std::string tname_contents;
  llvm::raw_string_ostream OS_inner(tname_contents);

  switch (compressionMode) {
  case 1: { // zlib-compressed name:
    llvm::SmallVector<char, 32> CompressedBuffer;
    if (llvm::zlib::compress(llvm::StringRef(Name), CompressedBuffer)) {
      // optional bytes compressed_name = 2;
      llvm::protobuf::saveString(
          OS_inner, 2,
          llvm::StringRef(CompressedBuffer.begin(), CompressedBuffer.size()));
      break;
    } // else, go to case 0:
  }
    LLVM_FALLTHROUGH;
  case 0:
    // optional string name = 1;
    llvm::protobuf::saveString(OS_inner, 1, Name); // name
    break;
  case 2:
  default:
    // optional uint32 dict_id = 3;
    llvm::protobuf::saveVarInt(OS_inner, 3, createDictionaryEntry(Name));
    break;
  }

  OS_inner.str();

  return tname_contents; // NRVO
}
void TemplightProtobufWriter::initialize(const std::string &aSourceName) {

  std::string hdr_contents;
  {
    llvm::raw_string_ostream OS_inner(hdr_contents);

    /*
  message TemplightHeader {
    required uint32 version = 1;
    optional string source_file = 2;
  }
    */

    llvm::protobuf::saveVarInt(OS_inner, 1, 1); // version
    if (!aSourceName.empty())
      llvm::protobuf::saveString(OS_inner, 2, aSourceName); // source_file
  }

  llvm::raw_string_ostream OS(buffer);

  // required TemplightHeader header = 1;
  llvm::protobuf::saveString(OS, 1, hdr_contents);
}