serialization.cpp
Go to the documentation of this file.
3 
4 namespace foxglove {
5 
6 void to_json(nlohmann::json& j, const Channel& c) {
7  j = {
8  {"id", c.id},
9  {"topic", c.topic},
10  {"encoding", c.encoding},
11  {"schemaName", c.schemaName},
12  {"schema", c.schema},
13  };
14 
15  if (c.schemaEncoding.has_value()) {
16  j["schemaEncoding"] = c.schemaEncoding.value();
17  }
18 }
19 void from_json(const nlohmann::json& j, Channel& c) {
20  const auto schemaEncoding =
21  j.find("schemaEncoding") == j.end()
22  ? std::optional<std::string>(std::nullopt)
23  : std::optional<std::string>(j["schemaEncoding"].get<std::string>());
24 
25  ChannelWithoutId channelWithoutId{j["topic"].get<std::string>(), j["encoding"].get<std::string>(),
26  j["schemaName"].get<std::string>(),
27  j["schema"].get<std::string>(), schemaEncoding};
28  c = Channel(j["id"].get<ChannelId>(), channelWithoutId);
29 }
30 
32  const auto paramType = p.getType();
33  if (paramType == ParameterType::PARAMETER_BOOL) {
34  j = p.getValue<bool>();
35  } else if (paramType == ParameterType::PARAMETER_INTEGER) {
36  j = p.getValue<int64_t>();
37  } else if (paramType == ParameterType::PARAMETER_DOUBLE) {
38  j = p.getValue<double>();
39  } else if (paramType == ParameterType::PARAMETER_STRING) {
40  j = p.getValue<std::string>();
41  } else if (paramType == ParameterType::PARAMETER_BYTE_ARRAY) {
42  const auto& paramValue = p.getValue<std::vector<unsigned char>>();
43  const std::string_view strValue(reinterpret_cast<const char*>(paramValue.data()),
44  paramValue.size());
45  j = base64Encode(strValue);
46  } else if (paramType == ParameterType::PARAMETER_STRUCT) {
47  j = p.getValue<std::unordered_map<std::string, ParameterValue>>();
48  } else if (paramType == ParameterType::PARAMETER_ARRAY) {
49  j = p.getValue<std::vector<ParameterValue>>();
50  } else if (paramType == ParameterType::PARAMETER_NOT_SET) {
51  // empty value.
52  }
53 }
54 
56  const auto jsonType = j.type();
57 
58  if (jsonType == nlohmann::detail::value_t::string) {
59  p = ParameterValue(j.get<std::string>());
60  } else if (jsonType == nlohmann::detail::value_t::boolean) {
61  p = ParameterValue(j.get<bool>());
62  } else if (jsonType == nlohmann::detail::value_t::number_integer) {
63  p = ParameterValue(j.get<int64_t>());
64  } else if (jsonType == nlohmann::detail::value_t::number_unsigned) {
65  p = ParameterValue(j.get<int64_t>());
66  } else if (jsonType == nlohmann::detail::value_t::number_float) {
67  p = ParameterValue(j.get<double>());
68  } else if (jsonType == nlohmann::detail::value_t::object) {
69  p = ParameterValue(j.get<std::unordered_map<std::string, ParameterValue>>());
70  } else if (jsonType == nlohmann::detail::value_t::array) {
71  p = ParameterValue(j.get<std::vector<ParameterValue>>());
72  }
73 }
74 
75 void to_json(nlohmann::json& j, const Parameter& p) {
76  to_json(j["value"], p.getValue());
77  j["name"] = p.getName();
79  j["type"] = "byte_array";
80  } else if (p.getType() == ParameterType::PARAMETER_DOUBLE) {
81  j["type"] = "float64";
82  } else if (p.getType() == ParameterType::PARAMETER_ARRAY) {
83  const auto& vec = p.getValue().getValue<std::vector<ParameterValue>>();
84  if (!vec.empty() && vec.front().getType() == ParameterType::PARAMETER_DOUBLE) {
85  j["type"] = "float64_array";
86  }
87  }
88 }
89 
90 void from_json(const nlohmann::json& j, Parameter& p) {
91  const auto name = j["name"].get<std::string>();
92 
93  if (j.find("value") == j.end()) {
94  p = Parameter(name); // Value is not set (undefined).
95  return;
96  }
97 
98  ParameterValue pValue;
99  from_json(j["value"], pValue);
100  const auto typeIt = j.find("type");
101  const std::string type = typeIt != j.end() ? typeIt->get<std::string>() : "";
102 
103  if (pValue.getType() == ParameterType::PARAMETER_STRING && type == "byte_array") {
104  p = Parameter(name, base64Decode(pValue.getValue<std::string>()));
105  } else if (pValue.getType() == ParameterType::PARAMETER_INTEGER && type == "float64") {
106  // Explicitly cast integer value to double.
107  p = Parameter(name, static_cast<double>(pValue.getValue<int64_t>()));
108  } else if (pValue.getType() == ParameterType::PARAMETER_ARRAY && type == "float64_array") {
109  // Explicitly cast elements to double, if possible.
110  auto values = pValue.getValue<std::vector<ParameterValue>>();
111  for (ParameterValue& value : values) {
112  if (value.getType() == ParameterType::PARAMETER_INTEGER) {
113  value = ParameterValue(static_cast<double>(value.getValue<int64_t>()));
114  } else if (value.getType() != ParameterType::PARAMETER_DOUBLE) {
115  throw std::runtime_error("Parameter '" + name +
116  "' (float64_array) contains non-numeric elements.");
117  }
118  }
119  p = Parameter(name, values);
120  } else {
121  p = Parameter(name, pValue);
122  }
123 }
124 
125 void to_json(nlohmann::json& j, const Service& service) {
126  j = {
127  {"id", service.id},
128  {"name", service.name},
129  {"type", service.type},
130  {"requestSchema", service.requestSchema},
131  {"responseSchema", service.responseSchema},
132  };
133 }
134 
135 void from_json(const nlohmann::json& j, Service& p) {
136  p.id = j["id"].get<ServiceId>();
137  p.name = j["name"].get<std::string>();
138  p.type = j["type"].get<std::string>();
139  p.requestSchema = j["requestSchema"].get<std::string>();
140  p.responseSchema = j["responseSchema"].get<std::string>();
141 }
142 
143 void ServiceResponse::read(const uint8_t* data, size_t dataLength) {
144  size_t offset = 0;
145  this->serviceId = ReadUint32LE(data + offset);
146  offset += 4;
147  this->callId = ReadUint32LE(data + offset);
148  offset += 4;
149  const size_t encondingLength = static_cast<size_t>(ReadUint32LE(data + offset));
150  offset += 4;
151  this->encoding = std::string(reinterpret_cast<const char*>(data + offset), encondingLength);
152  offset += encondingLength;
153  const auto payloadLength = dataLength - offset;
154  this->data.resize(payloadLength);
155  std::memcpy(this->data.data(), data + offset, payloadLength);
156 }
157 
158 void ServiceResponse::write(uint8_t* data) const {
159  size_t offset = 0;
160  foxglove::WriteUint32LE(data + offset, this->serviceId);
161  offset += 4;
162  foxglove::WriteUint32LE(data + offset, this->callId);
163  offset += 4;
164  foxglove::WriteUint32LE(data + offset, static_cast<uint32_t>(this->encoding.size()));
165  offset += 4;
166  std::memcpy(data + offset, this->encoding.data(), this->encoding.size());
167  offset += this->encoding.size();
168  std::memcpy(data + offset, this->data.data(), this->data.size());
169 }
170 
171 } // namespace foxglove
foxglove::ParameterValue::getType
ParameterType getType() const
Definition: parameter.hpp:40
foxglove::ChannelWithoutId::encoding
std::string encoding
Definition: common.hpp:53
foxglove::Service::id
ServiceId id
Definition: common.hpp:122
foxglove
Definition: base64.hpp:8
foxglove::Channel
Definition: common.hpp:64
foxglove::ParameterType::PARAMETER_STRING
@ PARAMETER_STRING
foxglove::ServiceResponse::encoding
std::string encoding
Definition: common.hpp:133
foxglove::ParameterType::PARAMETER_ARRAY
@ PARAMETER_ARRAY
foxglove::ReadUint32LE
uint32_t ReadUint32LE(const uint8_t *buf)
Definition: serialization.hpp:38
foxglove::ServiceWithoutId::responseSchema
std::string responseSchema
Definition: common.hpp:118
foxglove::ParameterType::PARAMETER_BYTE_ARRAY
@ PARAMETER_BYTE_ARRAY
foxglove::ServiceResponse::callId
uint32_t callId
Definition: common.hpp:132
foxglove::ParameterType::PARAMETER_BOOL
@ PARAMETER_BOOL
foxglove::Channel::id
ChannelId id
Definition: common.hpp:65
foxglove::ChannelWithoutId::topic
std::string topic
Definition: common.hpp:52
foxglove::ParameterType::PARAMETER_STRUCT
@ PARAMETER_STRUCT
foxglove::ServiceWithoutId::name
std::string name
Definition: common.hpp:115
foxglove::ServiceResponse::data
std::vector< uint8_t > data
Definition: common.hpp:134
foxglove::Parameter::getType
ParameterType getType() const
Definition: parameter.hpp:64
serialization.hpp
foxglove::ServiceWithoutId::type
std::string type
Definition: common.hpp:116
foxglove::ParameterValue
Definition: parameter.hpp:27
foxglove::Parameter::getName
const std::string & getName() const
Definition: parameter.hpp:60
foxglove::ParameterType::PARAMETER_NOT_SET
@ PARAMETER_NOT_SET
foxglove::Parameter
Definition: parameter.hpp:54
foxglove::json
nlohmann::json json
Definition: websocket_server.hpp:66
foxglove::ServiceResponse::serviceId
ServiceId serviceId
Definition: common.hpp:131
foxglove::WriteUint32LE
void WriteUint32LE(uint8_t *buf, uint32_t val)
Definition: serialization.hpp:27
foxglove::to_json
void to_json(nlohmann::json &j, const Channel &c)
Definition: serialization.cpp:6
foxglove::ChannelWithoutId
Definition: common.hpp:51
foxglove::ChannelWithoutId::schema
std::string schema
Definition: common.hpp:55
foxglove::ServiceWithoutId::requestSchema
std::string requestSchema
Definition: common.hpp:117
foxglove::from_json
void from_json(const nlohmann::json &j, Channel &c)
Definition: serialization.cpp:19
base64.hpp
foxglove::Parameter::getValue
const ParameterValue & getValue() const
Definition: parameter.hpp:68
foxglove::ParameterType::PARAMETER_DOUBLE
@ PARAMETER_DOUBLE
foxglove::base64Encode
std::string base64Encode(const std::string_view &input)
Definition: base64.cpp:10
foxglove::base64Decode
std::vector< unsigned char > base64Decode(const std::string &input)
Definition: base64.cpp:47
foxglove::ChannelWithoutId::schemaEncoding
std::optional< std::string > schemaEncoding
Definition: common.hpp:56
foxglove::ParameterType::PARAMETER_INTEGER
@ PARAMETER_INTEGER
foxglove::ServiceResponse::write
void write(uint8_t *data) const
Definition: serialization.cpp:158
foxglove::ChannelWithoutId::schemaName
std::string schemaName
Definition: common.hpp:54
foxglove::ServiceId
uint32_t ServiceId
Definition: common.hpp:29
foxglove::ParameterValue::getValue
const T & getValue() const
Definition: parameter.hpp:45
foxglove::ServiceResponse::read
void read(const uint8_t *data, size_t size)
Definition: serialization.cpp:143
foxglove::Service
Definition: common.hpp:121


foxglove_bridge
Author(s): Foxglove
autogenerated on Tue May 20 2025 02:34:26