#include "ProtoParse.h" proto_error_t parseClientFrame(const char *text, size_t len, JsonDocument &doc, proto_message_t &out) { out = proto_message_t(); if(len > PROTO_MAX_CLIENT_FRAME) return proto_error_t::badRequest; if(deserializeJson(doc, text, len) != DeserializationError::Ok) return proto_error_t::badRequest; if(!doc.is()) return proto_error_t::badRequest; JsonVariantConst id = doc["id"]; if(id.is()) out.id = id.as(); else if(!id.isNull()) return proto_error_t::badRequest; if(!doc["v"].is() || doc["v"].as() != PROTO_VERSION) return proto_error_t::badRequest; JsonVariantConst t = doc["t"]; if(!t.is() || t.as() < 1 || t.as() > 255) return proto_error_t::badRequest; out.type = static_cast(t.as()); if(!protoClientMaySend(out.type)) return proto_error_t::unknownOp; if(protoIsOp(out.type) && out.id == 0) return proto_error_t::badRequest; JsonVariantConst d = doc["d"]; if(!d.isNull() && !d.is()) return proto_error_t::badRequest; return proto_error_t::none; } int32_t protoInt(JsonObjectConst d, proto_field_t field) { const proto_field_info_t &f = protoField(field); JsonVariantConst v = d[f.key]; return v.is() ? v.as() : f.def; } bool protoBool(JsonObjectConst d, proto_field_t field) { const proto_field_info_t &f = protoField(field); JsonVariantConst v = d[f.key]; return v.is() ? v.as() != 0 : f.def != 0; } const char *protoString(JsonObjectConst d, proto_field_t field) { JsonVariantConst v = d[protoField(field).key]; return v.is() ? v.as() : nullptr; } bool protoHas(JsonObjectConst d, proto_field_t field) { return !d[protoField(field).key].isNull(); } bool protoRouteValue(const proto_field_info_t &f, JsonVariantConst v, JsonVariant out) { switch(f.kind) { case 'b': // Booleans are 1 and 0; the routes read true and false. if(!v.is() || (v.as() != 0 && v.as() != 1)) return false; out.set(v.as() == 1); return true; case 'i': if(v.is() || v.is()) return out.set(v); return false; case 'n': if(v.is()) return out.set(v); return false; case 's': if(v.is()) return out.set(v); return false; default: return false; } } const char *protoKindName(char kind) { switch(kind) { case 'b': return "boolean (1 or 0)"; case 'i': return "whole number"; case 'n': return "number"; case 's': return "string"; case 'l': return "list"; default: return "object"; } }