20 #include "rcl/error_handling.h"
21 #include "rcl/type_hash.h"
22 #include "rcutils/types/char_array.h"
23 #include "rcutils/sha256.h"
24 #include "type_description_interfaces/msg/type_description.h"
28 static int yaml_write_handler(
void * ext, uint8_t * buffer,
size_t size)
30 rcutils_char_array_t * repr = (rcutils_char_array_t *)ext;
31 rcutils_ret_t res = rcutils_char_array_strncat(repr, (
char *)buffer, size);
35 static inline int start_sequence(yaml_emitter_t * emitter)
39 yaml_sequence_start_event_initialize(&event, NULL, NULL, 1, YAML_FLOW_SEQUENCE_STYLE) &&
40 yaml_emitter_emit(emitter, &event);
43 static inline int end_sequence(yaml_emitter_t * emitter)
47 yaml_sequence_end_event_initialize(&event) &&
48 yaml_emitter_emit(emitter, &event);
51 static inline int start_mapping(yaml_emitter_t * emitter)
55 yaml_mapping_start_event_initialize(&event, NULL, NULL, 1, YAML_FLOW_MAPPING_STYLE) &&
56 yaml_emitter_emit(emitter, &event);
59 static inline int end_mapping(yaml_emitter_t * emitter)
63 yaml_mapping_end_event_initialize(&event) &&
64 yaml_emitter_emit(emitter, &event);
67 static int emit_key(yaml_emitter_t * emitter,
const char * key)
71 yaml_scalar_event_initialize(
73 (yaml_char_t *)key, (
int)strlen(key),
74 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE) &&
75 yaml_emitter_emit(emitter, &event);
78 static int emit_int(yaml_emitter_t * emitter,
size_t val,
const char * fmt)
83 int ret = snprintf(decimal_buf,
sizeof(decimal_buf), fmt, val);
85 emitter->problem =
"Failed expanding integer";
88 if ((
size_t)ret >=
sizeof(decimal_buf)) {
89 emitter->problem =
"Decimal buffer overflow";
93 yaml_scalar_event_initialize(
95 (yaml_char_t *)decimal_buf, (
int)strlen(decimal_buf),
96 1, 0, YAML_PLAIN_SCALAR_STYLE) &&
97 yaml_emitter_emit(emitter, &event);
100 static int emit_str(yaml_emitter_t * emitter,
const rosidl_runtime_c__String * val)
104 yaml_scalar_event_initialize(
106 (yaml_char_t *)val->data, (
int)val->size,
107 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE) &&
108 yaml_emitter_emit(emitter, &event);
111 static int emit_field_type(
112 yaml_emitter_t * emitter,
113 const type_description_interfaces__msg__FieldType * field_type)
116 start_mapping(emitter) &&
118 emit_key(emitter,
"type_id") &&
119 emit_int(emitter, field_type->type_id,
"%d") &&
121 emit_key(emitter,
"capacity") &&
122 emit_int(emitter, field_type->capacity,
"%zu") &&
124 emit_key(emitter,
"string_capacity") &&
125 emit_int(emitter, field_type->string_capacity,
"%zu") &&
127 emit_key(emitter,
"nested_type_name") &&
128 emit_str(emitter, &field_type->nested_type_name) &&
130 end_mapping(emitter);
133 static int emit_field(
134 yaml_emitter_t * emitter,
135 const type_description_interfaces__msg__Field * field)
138 start_mapping(emitter) &&
140 emit_key(emitter,
"name") &&
141 emit_str(emitter, &field->name) &&
143 emit_key(emitter,
"type") &&
144 emit_field_type(emitter, &field->type) &&
146 end_mapping(emitter);
149 static int emit_individual_type_description(
150 yaml_emitter_t * emitter,
151 const type_description_interfaces__msg__IndividualTypeDescription * individual_type_description)
154 start_mapping(emitter) &&
156 emit_key(emitter,
"type_name") &&
157 emit_str(emitter, &individual_type_description->type_name) &&
159 emit_key(emitter,
"fields") &&
160 start_sequence(emitter)))
164 for (
size_t i = 0; i < individual_type_description->fields.size; i++) {
165 if (!emit_field(emitter, &individual_type_description->fields.data[i])) {
169 return end_sequence(emitter) && end_mapping(emitter);
172 static int emit_type_description(
173 yaml_emitter_t * emitter,
174 const type_description_interfaces__msg__TypeDescription * type_description)
177 start_mapping(emitter) &&
179 emit_key(emitter,
"type_description") &&
180 emit_individual_type_description(emitter, &type_description->type_description) &&
182 emit_key(emitter,
"referenced_type_descriptions") &&
183 start_sequence(emitter)))
187 for (
size_t i = 0; i < type_description->referenced_type_descriptions.size; i++) {
188 if (!emit_individual_type_description(
189 emitter, &type_description->referenced_type_descriptions.data[i]))
194 return end_sequence(emitter) && end_mapping(emitter);
198 rcl_type_description_to_hashable_json(
199 const type_description_interfaces__msg__TypeDescription * type_description,
200 rcutils_char_array_t * output_repr)
205 yaml_emitter_t emitter;
208 if (!yaml_emitter_initialize(&emitter)) {
213 yaml_emitter_set_width(&emitter, -1);
215 yaml_emitter_set_break(&emitter, -1);
216 yaml_emitter_set_output(&emitter, yaml_write_handler, output_repr);
219 yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING) &&
220 yaml_emitter_emit(&emitter, &event) &&
222 yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 1) &&
223 yaml_emitter_emit(&emitter, &event) &&
225 emit_type_description(&emitter, type_description) &&
227 yaml_document_end_event_initialize(&event, 1) &&
228 yaml_emitter_emit(&emitter, &event) &&
230 yaml_stream_end_event_initialize(&event) &&
231 yaml_emitter_emit(&emitter, &event)))
236 yaml_emitter_delete(&emitter);
240 rcl_set_error_state(emitter.problem, __FILE__, __LINE__);
241 yaml_emitter_delete(&emitter);
246 rcl_calculate_type_hash(
247 const type_description_interfaces__msg__TypeDescription * type_description,
248 rosidl_type_hash_t * output_hash)
255 rcutils_char_array_t msg_repr = rcutils_get_zero_initialized_char_array();
256 rcutils_ret_t rcutils_result = rcutils_char_array_init(&msg_repr, 0, &allocator);
259 return rcl_convert_rcutils_ret_to_rcl_ret(rcutils_result);
262 output_hash->version = 1;
263 result = rcl_type_description_to_hashable_json(type_description, &msg_repr);
265 rcutils_sha256_ctx_t sha_ctx;
266 rcutils_sha256_init(&sha_ctx);
268 rcutils_sha256_update(&sha_ctx, (
const uint8_t *)msg_repr.buffer, msg_repr.buffer_length - 1);
269 rcutils_sha256_final(&sha_ctx, output_hash->value);
271 result = rcutils_char_array_fini(&msg_repr);
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
#define RCL_RET_OK
Success return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.