LogCabin
|
00001 /* Copyright (c) 2012 Stanford University 00002 * Copyright (c) 2015 Diego Ongaro 00003 * 00004 * Permission to use, copy, modify, and distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 #include <google/protobuf/message.h> 00018 #include <memory> 00019 #include <string> 00020 00021 #include "Core/Buffer.h" 00022 00023 /** 00024 * \file 00025 * Utilities for dealing with protocol buffers. 00026 */ 00027 00028 #ifndef LOGCABIN_CORE_PROTOBUF_H 00029 #define LOGCABIN_CORE_PROTOBUF_H 00030 00031 namespace google { 00032 namespace protobuf { 00033 00034 /** 00035 * Equality for protocol buffers so that they can be used in EXPECT_EQ. 00036 * This is useful for testing. 00037 */ 00038 bool operator==(const Message& a, const Message& b); 00039 00040 /** 00041 * Inequality for protocol buffers so that they can be used in EXPECT_NE. 00042 * This is useful for testing. 00043 */ 00044 bool operator!=(const Message& a, const Message& b); 00045 00046 // Equality and inequality between protocol buffers and their text format 00047 // representations. These are useful for testing. 00048 bool operator==(const Message& a, const std::string& b); 00049 bool operator==(const std::string& a, const Message& b); 00050 bool operator!=(const Message& a, const std::string& b); 00051 bool operator!=(const std::string& a, const Message& b); 00052 00053 } // namespace google::protobuf 00054 } // namespace google 00055 00056 namespace LogCabin { 00057 namespace Core { 00058 namespace ProtoBuf { 00059 00060 namespace Internal { 00061 00062 /// Helper for fromString template. 00063 void fromString(const std::string& str, google::protobuf::Message& protoBuf); 00064 00065 } // namespace LogCabin::ProtoBuf::Internal 00066 00067 /** 00068 * Create a protocol buffer message form a text format. 00069 * This is useful for testing. 00070 * \tparam ProtoBuf 00071 * A derived class of ProtoBuf::Message. 00072 * \param str 00073 * The string representation of the protocol buffer message. 00074 * Fields that are missing will not throw an error, but the resulting 00075 * protocol buffer may be less useful. 00076 * \return 00077 * The parsed protocol buffer. 00078 */ 00079 template<typename ProtoBuf> 00080 ProtoBuf 00081 fromString(const std::string& str) 00082 { 00083 ProtoBuf protoBuf; 00084 Internal::fromString(str, protoBuf); 00085 return protoBuf; 00086 } 00087 00088 /** 00089 * Dumps a protocol buffer message. 00090 * This is useful for debugging and for testing. 00091 * 00092 * \param protoBuf 00093 * The protocol buffer message to dump out. It is safe to call this even 00094 * if you haven't filled in all required fields, but the generated string 00095 * will not be directly parse-able. 00096 * \param forCopyingIntoTest 00097 * If set to true, this will return a string in a format most useful for 00098 * writing unit tests. You can basically copy and paste this from your 00099 * terminal into your test file without manual processing. If set to false 00100 * (default), the output will be nicer to read but harder to copy into a 00101 * test file. 00102 * \return 00103 * Textual representation. This will be printable ASCII; binary will be 00104 * escaped. 00105 */ 00106 std::string 00107 dumpString(const google::protobuf::Message& protoBuf, 00108 bool forCopyingIntoTest = false); 00109 00110 /** 00111 * Copy the contents of a protocol buffer into a new one. 00112 */ 00113 std::unique_ptr<google::protobuf::Message> 00114 copy(const google::protobuf::Message& protoBuf); 00115 00116 /** 00117 * Parse a protocol buffer message out of a Core::Buffer. 00118 * \param from 00119 * The Core::Buffer from which to extract a protocol buffer. 00120 * \param[out] to 00121 * The empty protocol buffer to fill in with the contents of the 00122 * Core::Buffer. 00123 * \param skipBytes 00124 * The number of bytes to skip at the beginning of 'from' (defaults to 0). 00125 * \return 00126 * True if the protocol buffer was parsed successfully; false otherwise 00127 * (for example, if a required field is missing). 00128 */ 00129 bool 00130 parse(const Core::Buffer& from, 00131 google::protobuf::Message& to, 00132 uint32_t skipBytes = 0); 00133 00134 /** 00135 * Serialize a protocol buffer message into a Core::Buffer. 00136 * \param from 00137 * The protocol buffer containing the contents to serialize into the 00138 * Core::Buffer. All required fields must be set or this will PANIC. 00139 * \param[out] to 00140 * The Core::Buffer to fill in with the contents of the protocol buffer. 00141 * \param skipBytes 00142 * The number of bytes to allocate at the beginning of 'to' but leave 00143 * uninitialized for someone else to fill in (defaults to 0). 00144 */ 00145 void 00146 serialize(const google::protobuf::Message& from, 00147 Core::Buffer& to, 00148 uint32_t skipBytes = 0); 00149 00150 /** 00151 * An abstract stream from which ProtoBufs may be read. 00152 */ 00153 struct InputStream { 00154 /** 00155 * Destructor. 00156 */ 00157 virtual ~InputStream() {} 00158 /** 00159 * Return the number of bytes read so far. 00160 */ 00161 virtual uint64_t getBytesRead() const = 0; 00162 /** 00163 * Read a ProtoBuf message from the stream. 00164 * \return 00165 * Empty string if successful, otherwise an error message if an error 00166 * occurred. The stream is probably no longer usable after an error. 00167 */ 00168 virtual std::string readMessage(google::protobuf::Message& message) = 0; 00169 /** 00170 * Read some raw bytes from the stream. 00171 * \return 00172 * The number of bytes read before the end of the stream was reached, 00173 * up to 'length'. 00174 */ 00175 virtual uint64_t readRaw(void* data, uint64_t length) = 0; 00176 }; 00177 00178 /** 00179 * An abstract stream to which ProtoBufs may be written. 00180 */ 00181 struct OutputStream { 00182 /** 00183 * Destructor. 00184 */ 00185 virtual ~OutputStream() {} 00186 /** 00187 * Return the number of bytes written so far. 00188 */ 00189 virtual uint64_t getBytesWritten() const = 0; 00190 /** 00191 * Write the given ProtoBuf message to the stream. 00192 */ 00193 virtual void writeMessage(const google::protobuf::Message& message) = 0; 00194 /** 00195 * Write some raw bytes to the stream. 00196 */ 00197 virtual void writeRaw(const void* data, uint64_t length) = 0; 00198 }; 00199 00200 } // namespace LogCabin::Core::ProtoBuf 00201 } // namespace LogCabin::Core 00202 } // namespace LogCabin 00203 00204 #endif /* LOGCABIN_CORE_PROTOBUF_H */