| 184 | } |
| 185 | |
| 186 | MessagePtr ProtobufCodec::parse(const char* buf, int len, ErrorCode* error) |
| 187 | { |
| 188 | MessagePtr message; |
| 189 | |
| 190 | // check sum |
| 191 | int32_t expectedCheckSum = asInt32(buf + len - kHeaderLen); |
| 192 | int32_t checkSum = static_cast<int32_t>( |
| 193 | ::adler32(1, |
| 194 | reinterpret_cast<const Bytef*>(buf), |
| 195 | static_cast<int>(len - kHeaderLen))); |
| 196 | if (checkSum == expectedCheckSum) |
| 197 | { |
| 198 | // get message type name |
| 199 | int32_t nameLen = asInt32(buf); |
| 200 | if (nameLen >= 2 && nameLen <= len - 2*kHeaderLen) |
| 201 | { |
| 202 | std::string typeName(buf + kHeaderLen, buf + kHeaderLen + nameLen - 1); |
| 203 | // create message object |
| 204 | message.reset(createMessage(typeName)); |
| 205 | if (message) |
| 206 | { |
| 207 | // parse from buffer |
| 208 | const char* data = buf + kHeaderLen + nameLen; |
| 209 | int32_t dataLen = len - nameLen - 2*kHeaderLen; |
| 210 | if (message->ParseFromArray(data, dataLen)) |
| 211 | { |
| 212 | *error = kNoError; |
| 213 | } |
| 214 | else |
| 215 | { |
| 216 | *error = kParseError; |
| 217 | } |
| 218 | } |
| 219 | else |
| 220 | { |
| 221 | *error = kUnknownMessageType; |
| 222 | } |
| 223 | } |
| 224 | else |
| 225 | { |
| 226 | *error = kInvalidNameLen; |
| 227 | } |
| 228 | } |
| 229 | else |
| 230 | { |
| 231 | *error = kCheckSumError; |
| 232 | } |
| 233 | |
| 234 | return message; |
| 235 | } |