Skip to content

Commit

Permalink
Calculate type hash from TypeDescription (rep2011) (#1027)
Browse files Browse the repository at this point in the history
* Convert TypeDescription to YAML and hash

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>
  • Loading branch information
emersonknapp committed Mar 29, 2023
1 parent fae1a01 commit 973951d
Show file tree
Hide file tree
Showing 6 changed files with 585 additions and 0 deletions.
8 changes: 8 additions & 0 deletions rcl/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@ project(rcl)

find_package(ament_cmake_ros REQUIRED)

find_package(libyaml_vendor REQUIRED)
find_package(rcl_interfaces REQUIRED)
find_package(rcl_logging_interface REQUIRED)
find_package(rcl_yaml_param_parser REQUIRED)
Expand All @@ -13,6 +14,8 @@ find_package(rmw_implementation REQUIRED)
find_package(rosidl_runtime_c REQUIRED)
find_package(service_msgs REQUIRED)
find_package(tracetools REQUIRED)
find_package(type_description_interfaces REQUIRED)
find_package(yaml REQUIRED)

include(cmake/rcl_set_symbol_visibility_hidden.cmake)
include(cmake/get_default_rcl_logging_implementation.cmake)
Expand Down Expand Up @@ -64,6 +67,7 @@ set(${PROJECT_NAME}_sources
src/rcl/subscription.c
src/rcl/time.c
src/rcl/timer.c
src/rcl/type_hash.c
src/rcl/validate_enclave_name.c
src/rcl/validate_topic_name.c
src/rcl/wait.c
Expand All @@ -76,6 +80,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
# specific order: dependents before dependencies
ament_target_dependencies(${PROJECT_NAME}
"libyaml_vendor"
"rcl_interfaces"
"rcl_logging_interface"
"rcl_yaml_param_parser"
Expand All @@ -86,6 +91,7 @@ ament_target_dependencies(${PROJECT_NAME}
"rosidl_runtime_c"
"service_msgs"
"tracetools"
"type_description_interfaces"
)

# Causes the visibility macros to use dllexport rather than dllimport,
Expand Down Expand Up @@ -127,6 +133,8 @@ ament_export_dependencies(${RCL_LOGGING_IMPL})
ament_export_dependencies(rosidl_runtime_c)
ament_export_dependencies(service_msgs)
ament_export_dependencies(tracetools)
ament_export_dependencies(type_description_interfaces)
ament_export_dependencies(libyaml_vendor)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
Expand Down
79 changes: 79 additions & 0 deletions rcl/include/rcl/type_hash.h
@@ -0,0 +1,79 @@
// Copyright 2023 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCL__TYPE_HASH_H_
#define RCL__TYPE_HASH_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "rcl/types.h"
#include "rcl/visibility_control.h"
#include "rcutils/sha256.h"
#include "rosidl_runtime_c/type_hash.h"
#include "type_description_interfaces/msg/type_description.h"

/// Given a TypeDescription, output a string of the hashable JSON representation of that data.
/**
* The output here is generally hashed via rcl_calculate_type_hash() below.
* Compare this reference implementation with the .json output files from
* `rosidl_generator_type_description.generate_type_hash`.
* Both must produce the same output for the same types, providing a stable reference for
* external implementations of the ROS 2 Type Version Hash.
*
* The JSON representation contains all types and fields of the original message, but excludes:
* - Default values
* - Comments
* - The input plaintext files that generated the TypeDescription
*
* \param[in] type_description Prefilled TypeDescription message to be translated
* \param[out] output_repr An initialized empty char array that will be filled with
* the JSON representation of type_description. Note that output_repr will have a
* terminating null character, which should be omitted from hashing. To do so, use
* (output_repr.buffer_length - 1) or strlen(output_repr.buffer) for the size of data to hash.
* \return #RCL_RET_OK on success, or
* \return #RCL_RET_ERROR if any problems occur in translation.
*/
RCL_PUBLIC
rcl_ret_t
rcl_type_description_to_hashable_json(
const type_description_interfaces__msg__TypeDescription * type_description,
rcutils_char_array_t * output_repr);

/// Calculate the Type Version Hash for a given TypeDescription.
/**
* This function produces a stable hash value for a ROS communication interface type.
* For design motivations leading to this implementation, see REP-2011.
*
* This convenience wrapper calls rcl_type_description_to_hashable_json,
* then runs sha256 hash on the result.
*
* \param[in] msg Prefilled TypeDescription message describing the type to be hashed
* \param[out] message_digest Preallocated buffer, to be filled with calculated checksum
* \return #RCL_RET_OK on success, or
* \return #RCL_RET_ERROR if any problems occur while hashing.
*/
RCL_PUBLIC
rcl_ret_t
rcl_calculate_type_hash(
const type_description_interfaces__msg__TypeDescription * type_description,
rosidl_type_hash_t * out_type_hash);

#ifdef __cplusplus
}
#endif

#endif // RCL__TYPE_HASH_H_
3 changes: 3 additions & 0 deletions rcl/package.xml
Expand Up @@ -19,6 +19,7 @@

<build_export_depend>rmw</build_export_depend>

<depend>libyaml_vendor</depend>
<depend>rcl_interfaces</depend>
<depend>rcl_logging_interface</depend>
<depend>rcl_logging_spdlog</depend> <!-- the default logging impl -->
Expand All @@ -28,6 +29,8 @@
<depend>rosidl_runtime_c</depend>
<depend>service_msgs</depend>
<depend>tracetools</depend>
<depend>type_description_interfaces</depend>
<depend>yaml</depend>

<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>
Expand Down

0 comments on commit 973951d

Please sign in to comment.