Skip to content
Draft
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ cmake_minimum_required(VERSION 3.13)

project("SilKit")

# Root of the SIL Kit tree; used by components (e.g. SilKitYaml) to locate
# vendored sources independently of the current subdirectory.
set(SILKIT_TOP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")

option(SILKIT_BUILD_DEMOS "Build the SIL Kit Demos" ON)
option(SILKIT_BUILD_STATIC "Compile the SIL Kit as a static library" OFF)
option(SILKIT_BUILD_TESTS "Enable unit and integration tests for the SIL Kit" ON)
Expand Down Expand Up @@ -133,6 +137,10 @@ if(MINGW)
endif()
endif()

# Internal, self-contained YAML helper library (header-only). Must come before
# SilKit, which depends on it, and after ThirdParty, which provides rapidyaml.
add_subdirectory(SilKitYaml)

# Have both SIL Kit library and demo project in a single solution
add_subdirectory(SilKit)
if(SILKIT_BUILD_UTILITIES)
Expand All @@ -158,6 +166,7 @@ if(SILKIT_INSTALL_SOURCE)
${CMAKE_CURRENT_SOURCE_DIR}/cmake
${CMAKE_CURRENT_SOURCE_DIR}/Demos
${CMAKE_CURRENT_SOURCE_DIR}/SilKit
${CMAKE_CURRENT_SOURCE_DIR}/SilKitYaml
${CMAKE_CURRENT_SOURCE_DIR}/Utilities
DESTINATION ${INSTALL_SOURCE_DIR}
COMPONENT source
Expand Down
12 changes: 5 additions & 7 deletions SilKit/source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,11 @@ if (TARGET ${SILKIT_THIRD_PARTY_ASIO})
)
endif()

if (TARGET rapidyaml)
message(STATUS "SIL Kit: Third-Party Library: rapidyaml")

target_link_libraries(I_SilKit
INTERFACE $<BUILD_INTERFACE:rapidyaml>
)
endif()
# Internal, header-only YAML helper. BUILD_INTERFACE only -- it is not
# installed and its symbols are not exported from the SIL Kit library.
target_link_libraries(I_SilKit
INTERFACE $<BUILD_INTERFACE:SilKitYaml>
)


add_library(O_SilKit_CreateParticipantImpl OBJECT
Expand Down
4 changes: 2 additions & 2 deletions SilKit/source/config/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ add_library(O_SilKit_Config OBJECT
YamlWriter.hpp
YamlWriter.cpp

YamlParserUtils.hpp
YamlParserUtils.cpp
CapabilitiesParser.hpp
CapabilitiesParser.cpp

YamlValidator.hpp
YamlValidator.cpp
Expand Down
55 changes: 55 additions & 0 deletions SilKit/source/config/CapabilitiesParser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: 2026 Vector Informatik GmbH
//
// SPDX-License-Identifier: MIT

#include "config/CapabilitiesParser.hpp"

#include "silkit/participant/exception.hpp"

#include "SilKitYaml/BasicYamlReader.hpp"
#include "SilKitYaml/YamlSerdes.hpp"

namespace VSilKit {

using ValueT = std::vector<std::map<std::string, std::string>>;

namespace {
struct CapabilityReader: SilKitYaml::BasicYamlReader<CapabilityReader>
{
using BasicYamlReader::BasicYamlReader;
void Read(ValueT& value)
{
if(!IsSequence())
{
throw SilKitYaml::YamlError{"First element in Capabilities string is not a sequence"};
}

if(_node.has_children())
{
for(auto&& i: _node.cchildren())
{
auto&& parser = MakeImpl(i);
if(!parser.IsMap())
{
throw SilKitYaml::YamlError{"Capabilities should be a sequence of map objects."};
}
std::map<std::string, std::string> element;
static_cast<SilKitYaml::BasicYamlReader<CapabilityReader>&>(parser).Read(element);
value.emplace_back(std::move(element));
}
}
}
};

} // end namespace
auto ParseCapabilities(const std::string& input) -> std::vector<std::map<std::string, std::string>>
{
try {
return SilKitYaml::Deserialize<ValueT, CapabilityReader>(input);
} catch(const SilKitYaml::YamlError& ex)
{
throw SilKit::ConfigurationError{ex.what()};
}
}

} // namespace VSilKit
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@
#include <string>
#include <vector>

#include "silkit/participant/exception.hpp"

#include "rapidyaml.hpp"

namespace VSilKit {

// Utility for parsing key-value lists for protocol capabilities
auto ParseCapabilities(const std::string& input) -> std::vector<std::map<std::string, std::string>>;

auto MakeConfigurationError(ryml::Location location, const std::string_view message) -> SilKit::ConfigurationError;

auto GetRapidyamlCallbacks() -> ryml::Callbacks;

} // namespace VSilKit
66 changes: 26 additions & 40 deletions SilKit/source/config/YamlParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

#include <string>

#include "silkit/participant/exception.hpp"

#include "config/YamlReader.hpp"
#include "config/YamlWriter.hpp"
#include "config/YamlParserUtils.hpp"

#include "SilKitYaml/YamlSerdes.hpp"

#include "rapidyaml.hpp"

Expand All @@ -17,67 +20,50 @@ namespace Config {

//////////////////////////////////////////////////////////////////////
// Configuration Parsing
//
// Thin wrappers around the generic SilKitYaml serdes templates, defaulting to the
// SilKit concrete reader/writer for the in-tree configuration types. They form
// the boundary that translates SilKitYaml::YamlError into the public
// SilKit::ConfigurationError, preserving SIL Kit's exception contract.
//////////////////////////////////////////////////////////////////////

template <typename T, typename R = VSilKit::YamlReader>
auto Deserialize(const std::string& input) -> T
{
if (input.empty())
{
return {};
}

const auto rapidyamlCallbacks = VSilKit::GetRapidyamlCallbacks();

ryml::ParserOptions options{};
options.locations(true);

ryml::EventHandlerTree eventHandler{};
auto parser = ryml::Parser(&eventHandler, options);
parser.reserve_locations(100u);
auto&& cinput = ryml::to_csubstr(input);
try
{
auto tree = ryml::parse_in_arena(&parser, cinput);

// Install the error-handling callbacks. This will nicely format errors and throw an exception.
tree.callbacks(rapidyamlCallbacks);

// Extract a reference to the root node of the document tree.
auto root = tree.crootref();

R reader{parser, root};
T result{};
reader.Read(result);
return result;
return SilKitYaml::Deserialize<T, R>(input);
}
catch (const std::exception& ex)
{
throw SilKit::ConfigurationError{ex.what()};
}
catch (...)
{
throw;
}
}


template <typename T, typename W = VSilKit::YamlWriter>
auto Serialize(const T& input) -> std::string
{
ryml::Tree t;
W writer{t.rootref()};
writer.Write(input);
return ryml::emitrs_yaml<std::string>(t);
try
{
return SilKitYaml::Serialize<T, W>(input);
}
catch (const std::exception& ex)
{
throw SilKit::ConfigurationError{ex.what()};
}
}

template <typename T, typename W = VSilKit::YamlWriter>
auto SerializeAsJson(const T& input) -> std::string
{
ryml::Tree t;
W writer{t.rootref()};
writer.Write(input);
return ryml::emitrs_json<std::string>(t);
try
{
return SilKitYaml::SerializeAsJson<T, W>(input);
}
catch (const std::exception& ex)
{
throw SilKit::ConfigurationError{ex.what()};
}
}

} // namespace Config
Expand Down
93 changes: 0 additions & 93 deletions SilKit/source/config/YamlParserUtils.cpp

This file was deleted.

Loading
Loading