diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b44be2c..d38998f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: shell: bash run: | set -euo pipefail - cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=OFF -DQTTY_FFI_FEATURES="serde" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: clang-format check shell: bash @@ -156,7 +156,7 @@ jobs: shell: bash run: | set -euo pipefail - cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=ON -DQTTY_FFI_FEATURES="serde" + cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=ON - name: Build shell: bash @@ -214,7 +214,6 @@ jobs: set -euo pipefail cmake -S . -B build-coverage -G Ninja \ -DQTTY_BUILD_DOCS=OFF \ - -DQTTY_FFI_FEATURES="serde" \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="--coverage" \ -DCMAKE_EXE_LINKER_FLAGS="--coverage" diff --git a/CMakeLists.txt b/CMakeLists.txt index ff5e16a..a788665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,15 +16,13 @@ set(QTTY_ARTIFACT_DIR ${QTTY_SUBMODULE_DIR}/target/release) # Allow enabling Cargo features for qtty-ffi (e.g., serde) # Use a STRING cache var (not BOOL) so users can set: "serde", "", or custom lists. -set(QTTY_FFI_FEATURES "serde" CACHE STRING "Cargo features for qtty-ffi (e.g., 'serde' or empty)") +set(QTTY_FFI_FEATURES "" CACHE STRING "Cargo features for qtty-ffi (e.g., 'serde' or empty)") -# Normalize feature args: treat OFF/FALSE/0 as empty; ON means default 'serde'. +# Normalize feature args: treat OFF/FALSE/0 as empty. set(_QTTY_FEATURES_ARGS "") string(TOUPPER "${QTTY_FFI_FEATURES}" _QTTY_FEATURES_UP) if("${_QTTY_FEATURES_UP}" STREQUAL "OFF" OR "${_QTTY_FEATURES_UP}" STREQUAL "FALSE" OR "${_QTTY_FEATURES_UP}" STREQUAL "0") # No features -elseif("${_QTTY_FEATURES_UP}" STREQUAL "ON") - set(_QTTY_FEATURES_ARGS --features serde) elseif(NOT "${QTTY_FFI_FEATURES}" STREQUAL "") set(_QTTY_FEATURES_ARGS --features ${QTTY_FFI_FEATURES}) endif() diff --git a/build-coverage/CMakeDoxyfile.in b/build-coverage/CMakeDoxyfile.in new file mode 100644 index 0000000..041b254 --- /dev/null +++ b/build-coverage/CMakeDoxyfile.in @@ -0,0 +1,298 @@ +# +# DO NOT EDIT! THIS FILE WAS GENERATED BY CMAKE! +# + +DOXYFILE_ENCODING = @DOXYGEN_DOXYFILE_ENCODING@ +PROJECT_NAME = @DOXYGEN_PROJECT_NAME@ +PROJECT_NUMBER = @DOXYGEN_PROJECT_NUMBER@ +PROJECT_BRIEF = @DOXYGEN_PROJECT_BRIEF@ +PROJECT_LOGO = @DOXYGEN_PROJECT_LOGO@ +OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT_DIRECTORY@ +CREATE_SUBDIRS = @DOXYGEN_CREATE_SUBDIRS@ +CREATE_SUBDIRS_LEVEL = @DOXYGEN_CREATE_SUBDIRS_LEVEL@ +ALLOW_UNICODE_NAMES = @DOXYGEN_ALLOW_UNICODE_NAMES@ +OUTPUT_LANGUAGE = @DOXYGEN_OUTPUT_LANGUAGE@ +BRIEF_MEMBER_DESC = @DOXYGEN_BRIEF_MEMBER_DESC@ +REPEAT_BRIEF = @DOXYGEN_REPEAT_BRIEF@ +ABBREVIATE_BRIEF = @DOXYGEN_ABBREVIATE_BRIEF@ +ALWAYS_DETAILED_SEC = @DOXYGEN_ALWAYS_DETAILED_SEC@ +INLINE_INHERITED_MEMB = @DOXYGEN_INLINE_INHERITED_MEMB@ +FULL_PATH_NAMES = @DOXYGEN_FULL_PATH_NAMES@ +STRIP_FROM_PATH = @DOXYGEN_STRIP_FROM_PATH@ +STRIP_FROM_INC_PATH = @DOXYGEN_STRIP_FROM_INC_PATH@ +SHORT_NAMES = @DOXYGEN_SHORT_NAMES@ +JAVADOC_AUTOBRIEF = @DOXYGEN_JAVADOC_AUTOBRIEF@ +JAVADOC_BANNER = @DOXYGEN_JAVADOC_BANNER@ +QT_AUTOBRIEF = @DOXYGEN_QT_AUTOBRIEF@ +MULTILINE_CPP_IS_BRIEF = @DOXYGEN_MULTILINE_CPP_IS_BRIEF@ +PYTHON_DOCSTRING = @DOXYGEN_PYTHON_DOCSTRING@ +INHERIT_DOCS = @DOXYGEN_INHERIT_DOCS@ +SEPARATE_MEMBER_PAGES = @DOXYGEN_SEPARATE_MEMBER_PAGES@ +TAB_SIZE = @DOXYGEN_TAB_SIZE@ +ALIASES = @DOXYGEN_ALIASES@ +OPTIMIZE_OUTPUT_FOR_C = @DOXYGEN_OPTIMIZE_OUTPUT_FOR_C@ +OPTIMIZE_OUTPUT_JAVA = @DOXYGEN_OPTIMIZE_OUTPUT_JAVA@ +OPTIMIZE_FOR_FORTRAN = @DOXYGEN_OPTIMIZE_FOR_FORTRAN@ +OPTIMIZE_OUTPUT_VHDL = @DOXYGEN_OPTIMIZE_OUTPUT_VHDL@ +OPTIMIZE_OUTPUT_SLICE = @DOXYGEN_OPTIMIZE_OUTPUT_SLICE@ +EXTENSION_MAPPING = @DOXYGEN_EXTENSION_MAPPING@ +MARKDOWN_SUPPORT = @DOXYGEN_MARKDOWN_SUPPORT@ +TOC_INCLUDE_HEADINGS = @DOXYGEN_TOC_INCLUDE_HEADINGS@ +MARKDOWN_ID_STYLE = @DOXYGEN_MARKDOWN_ID_STYLE@ +AUTOLINK_SUPPORT = @DOXYGEN_AUTOLINK_SUPPORT@ +BUILTIN_STL_SUPPORT = @DOXYGEN_BUILTIN_STL_SUPPORT@ +CPP_CLI_SUPPORT = @DOXYGEN_CPP_CLI_SUPPORT@ +SIP_SUPPORT = @DOXYGEN_SIP_SUPPORT@ +IDL_PROPERTY_SUPPORT = @DOXYGEN_IDL_PROPERTY_SUPPORT@ +DISTRIBUTE_GROUP_DOC = @DOXYGEN_DISTRIBUTE_GROUP_DOC@ +GROUP_NESTED_COMPOUNDS = @DOXYGEN_GROUP_NESTED_COMPOUNDS@ +SUBGROUPING = @DOXYGEN_SUBGROUPING@ +INLINE_GROUPED_CLASSES = @DOXYGEN_INLINE_GROUPED_CLASSES@ +INLINE_SIMPLE_STRUCTS = @DOXYGEN_INLINE_SIMPLE_STRUCTS@ +TYPEDEF_HIDES_STRUCT = @DOXYGEN_TYPEDEF_HIDES_STRUCT@ +LOOKUP_CACHE_SIZE = @DOXYGEN_LOOKUP_CACHE_SIZE@ +NUM_PROC_THREADS = @DOXYGEN_NUM_PROC_THREADS@ +TIMESTAMP = @DOXYGEN_TIMESTAMP@ +EXTRACT_ALL = @DOXYGEN_EXTRACT_ALL@ +EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@ +EXTRACT_PRIV_VIRTUAL = @DOXYGEN_EXTRACT_PRIV_VIRTUAL@ +EXTRACT_PACKAGE = @DOXYGEN_EXTRACT_PACKAGE@ +EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@ +EXTRACT_LOCAL_CLASSES = @DOXYGEN_EXTRACT_LOCAL_CLASSES@ +EXTRACT_LOCAL_METHODS = @DOXYGEN_EXTRACT_LOCAL_METHODS@ +EXTRACT_ANON_NSPACES = @DOXYGEN_EXTRACT_ANON_NSPACES@ +RESOLVE_UNNAMED_PARAMS = @DOXYGEN_RESOLVE_UNNAMED_PARAMS@ +HIDE_UNDOC_MEMBERS = @DOXYGEN_HIDE_UNDOC_MEMBERS@ +HIDE_UNDOC_CLASSES = @DOXYGEN_HIDE_UNDOC_CLASSES@ +HIDE_FRIEND_COMPOUNDS = @DOXYGEN_HIDE_FRIEND_COMPOUNDS@ +HIDE_IN_BODY_DOCS = @DOXYGEN_HIDE_IN_BODY_DOCS@ +INTERNAL_DOCS = @DOXYGEN_INTERNAL_DOCS@ +CASE_SENSE_NAMES = @DOXYGEN_CASE_SENSE_NAMES@ +HIDE_SCOPE_NAMES = @DOXYGEN_HIDE_SCOPE_NAMES@ +HIDE_COMPOUND_REFERENCE= @DOXYGEN_HIDE_COMPOUND_REFERENCE@ +SHOW_HEADERFILE = @DOXYGEN_SHOW_HEADERFILE@ +SHOW_INCLUDE_FILES = @DOXYGEN_SHOW_INCLUDE_FILES@ +SHOW_GROUPED_MEMB_INC = @DOXYGEN_SHOW_GROUPED_MEMB_INC@ +FORCE_LOCAL_INCLUDES = @DOXYGEN_FORCE_LOCAL_INCLUDES@ +INLINE_INFO = @DOXYGEN_INLINE_INFO@ +SORT_MEMBER_DOCS = @DOXYGEN_SORT_MEMBER_DOCS@ +SORT_BRIEF_DOCS = @DOXYGEN_SORT_BRIEF_DOCS@ +SORT_MEMBERS_CTORS_1ST = @DOXYGEN_SORT_MEMBERS_CTORS_1ST@ +SORT_GROUP_NAMES = @DOXYGEN_SORT_GROUP_NAMES@ +SORT_BY_SCOPE_NAME = @DOXYGEN_SORT_BY_SCOPE_NAME@ +STRICT_PROTO_MATCHING = @DOXYGEN_STRICT_PROTO_MATCHING@ +GENERATE_TODOLIST = @DOXYGEN_GENERATE_TODOLIST@ +GENERATE_TESTLIST = @DOXYGEN_GENERATE_TESTLIST@ +GENERATE_BUGLIST = @DOXYGEN_GENERATE_BUGLIST@ +GENERATE_DEPRECATEDLIST= @DOXYGEN_GENERATE_DEPRECATEDLIST@ +ENABLED_SECTIONS = @DOXYGEN_ENABLED_SECTIONS@ +MAX_INITIALIZER_LINES = @DOXYGEN_MAX_INITIALIZER_LINES@ +SHOW_USED_FILES = @DOXYGEN_SHOW_USED_FILES@ +SHOW_FILES = @DOXYGEN_SHOW_FILES@ +SHOW_NAMESPACES = @DOXYGEN_SHOW_NAMESPACES@ +FILE_VERSION_FILTER = @DOXYGEN_FILE_VERSION_FILTER@ +LAYOUT_FILE = @DOXYGEN_LAYOUT_FILE@ +CITE_BIB_FILES = @DOXYGEN_CITE_BIB_FILES@ +QUIET = @DOXYGEN_QUIET@ +WARNINGS = @DOXYGEN_WARNINGS@ +WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ +WARN_IF_DOC_ERROR = @DOXYGEN_WARN_IF_DOC_ERROR@ +WARN_IF_INCOMPLETE_DOC = @DOXYGEN_WARN_IF_INCOMPLETE_DOC@ +WARN_NO_PARAMDOC = @DOXYGEN_WARN_NO_PARAMDOC@ +WARN_IF_UNDOC_ENUM_VAL = @DOXYGEN_WARN_IF_UNDOC_ENUM_VAL@ +WARN_AS_ERROR = @DOXYGEN_WARN_AS_ERROR@ +WARN_FORMAT = @DOXYGEN_WARN_FORMAT@ +WARN_LINE_FORMAT = @DOXYGEN_WARN_LINE_FORMAT@ +WARN_LOGFILE = @DOXYGEN_WARN_LOGFILE@ +INPUT = @DOXYGEN_INPUT@ +INPUT_ENCODING = @DOXYGEN_INPUT_ENCODING@ +INPUT_FILE_ENCODING = @DOXYGEN_INPUT_FILE_ENCODING@ +FILE_PATTERNS = @DOXYGEN_FILE_PATTERNS@ +RECURSIVE = @DOXYGEN_RECURSIVE@ +EXCLUDE = @DOXYGEN_EXCLUDE@ +EXCLUDE_SYMLINKS = @DOXYGEN_EXCLUDE_SYMLINKS@ +EXCLUDE_PATTERNS = @DOXYGEN_EXCLUDE_PATTERNS@ +EXCLUDE_SYMBOLS = @DOXYGEN_EXCLUDE_SYMBOLS@ +EXAMPLE_PATH = @DOXYGEN_EXAMPLE_PATH@ +EXAMPLE_PATTERNS = @DOXYGEN_EXAMPLE_PATTERNS@ +EXAMPLE_RECURSIVE = @DOXYGEN_EXAMPLE_RECURSIVE@ +IMAGE_PATH = @DOXYGEN_IMAGE_PATH@ +INPUT_FILTER = @DOXYGEN_INPUT_FILTER@ +FILTER_PATTERNS = @DOXYGEN_FILTER_PATTERNS@ +FILTER_SOURCE_FILES = @DOXYGEN_FILTER_SOURCE_FILES@ +FILTER_SOURCE_PATTERNS = @DOXYGEN_FILTER_SOURCE_PATTERNS@ +USE_MDFILE_AS_MAINPAGE = @DOXYGEN_USE_MDFILE_AS_MAINPAGE@ +FORTRAN_COMMENT_AFTER = @DOXYGEN_FORTRAN_COMMENT_AFTER@ +SOURCE_BROWSER = @DOXYGEN_SOURCE_BROWSER@ +INLINE_SOURCES = @DOXYGEN_INLINE_SOURCES@ +STRIP_CODE_COMMENTS = @DOXYGEN_STRIP_CODE_COMMENTS@ +REFERENCED_BY_RELATION = @DOXYGEN_REFERENCED_BY_RELATION@ +REFERENCES_RELATION = @DOXYGEN_REFERENCES_RELATION@ +REFERENCES_LINK_SOURCE = @DOXYGEN_REFERENCES_LINK_SOURCE@ +SOURCE_TOOLTIPS = @DOXYGEN_SOURCE_TOOLTIPS@ +USE_HTAGS = @DOXYGEN_USE_HTAGS@ +VERBATIM_HEADERS = @DOXYGEN_VERBATIM_HEADERS@ +CLANG_ASSISTED_PARSING = @DOXYGEN_CLANG_ASSISTED_PARSING@ +CLANG_ADD_INC_PATHS = @DOXYGEN_CLANG_ADD_INC_PATHS@ +CLANG_OPTIONS = @DOXYGEN_CLANG_OPTIONS@ +CLANG_DATABASE_PATH = @DOXYGEN_CLANG_DATABASE_PATH@ +ALPHABETICAL_INDEX = @DOXYGEN_ALPHABETICAL_INDEX@ +IGNORE_PREFIX = @DOXYGEN_IGNORE_PREFIX@ +GENERATE_HTML = @DOXYGEN_GENERATE_HTML@ +HTML_OUTPUT = @DOXYGEN_HTML_OUTPUT@ +HTML_FILE_EXTENSION = @DOXYGEN_HTML_FILE_EXTENSION@ +HTML_HEADER = @DOXYGEN_HTML_HEADER@ +HTML_FOOTER = @DOXYGEN_HTML_FOOTER@ +HTML_STYLESHEET = @DOXYGEN_HTML_STYLESHEET@ +HTML_EXTRA_STYLESHEET = @DOXYGEN_HTML_EXTRA_STYLESHEET@ +HTML_EXTRA_FILES = @DOXYGEN_HTML_EXTRA_FILES@ +HTML_COLORSTYLE = @DOXYGEN_HTML_COLORSTYLE@ +HTML_COLORSTYLE_HUE = @DOXYGEN_HTML_COLORSTYLE_HUE@ +HTML_COLORSTYLE_SAT = @DOXYGEN_HTML_COLORSTYLE_SAT@ +HTML_COLORSTYLE_GAMMA = @DOXYGEN_HTML_COLORSTYLE_GAMMA@ +HTML_DYNAMIC_MENUS = @DOXYGEN_HTML_DYNAMIC_MENUS@ +HTML_DYNAMIC_SECTIONS = @DOXYGEN_HTML_DYNAMIC_SECTIONS@ +HTML_CODE_FOLDING = @DOXYGEN_HTML_CODE_FOLDING@ +HTML_INDEX_NUM_ENTRIES = @DOXYGEN_HTML_INDEX_NUM_ENTRIES@ +GENERATE_DOCSET = @DOXYGEN_GENERATE_DOCSET@ +DOCSET_FEEDNAME = @DOXYGEN_DOCSET_FEEDNAME@ +DOCSET_FEEDURL = @DOXYGEN_DOCSET_FEEDURL@ +DOCSET_BUNDLE_ID = @DOXYGEN_DOCSET_BUNDLE_ID@ +DOCSET_PUBLISHER_ID = @DOXYGEN_DOCSET_PUBLISHER_ID@ +DOCSET_PUBLISHER_NAME = @DOXYGEN_DOCSET_PUBLISHER_NAME@ +GENERATE_HTMLHELP = @DOXYGEN_GENERATE_HTMLHELP@ +CHM_FILE = @DOXYGEN_CHM_FILE@ +HHC_LOCATION = @DOXYGEN_HHC_LOCATION@ +GENERATE_CHI = @DOXYGEN_GENERATE_CHI@ +CHM_INDEX_ENCODING = @DOXYGEN_CHM_INDEX_ENCODING@ +BINARY_TOC = @DOXYGEN_BINARY_TOC@ +TOC_EXPAND = @DOXYGEN_TOC_EXPAND@ +SITEMAP_URL = @DOXYGEN_SITEMAP_URL@ +GENERATE_QHP = @DOXYGEN_GENERATE_QHP@ +QCH_FILE = @DOXYGEN_QCH_FILE@ +QHP_NAMESPACE = @DOXYGEN_QHP_NAMESPACE@ +QHP_VIRTUAL_FOLDER = @DOXYGEN_QHP_VIRTUAL_FOLDER@ +QHP_CUST_FILTER_NAME = @DOXYGEN_QHP_CUST_FILTER_NAME@ +QHP_CUST_FILTER_ATTRS = @DOXYGEN_QHP_CUST_FILTER_ATTRS@ +QHP_SECT_FILTER_ATTRS = @DOXYGEN_QHP_SECT_FILTER_ATTRS@ +QHG_LOCATION = @DOXYGEN_QHG_LOCATION@ +GENERATE_ECLIPSEHELP = @DOXYGEN_GENERATE_ECLIPSEHELP@ +ECLIPSE_DOC_ID = @DOXYGEN_ECLIPSE_DOC_ID@ +DISABLE_INDEX = @DOXYGEN_DISABLE_INDEX@ +GENERATE_TREEVIEW = @DOXYGEN_GENERATE_TREEVIEW@ +FULL_SIDEBAR = @DOXYGEN_FULL_SIDEBAR@ +ENUM_VALUES_PER_LINE = @DOXYGEN_ENUM_VALUES_PER_LINE@ +TREEVIEW_WIDTH = @DOXYGEN_TREEVIEW_WIDTH@ +EXT_LINKS_IN_WINDOW = @DOXYGEN_EXT_LINKS_IN_WINDOW@ +OBFUSCATE_EMAILS = @DOXYGEN_OBFUSCATE_EMAILS@ +HTML_FORMULA_FORMAT = @DOXYGEN_HTML_FORMULA_FORMAT@ +FORMULA_FONTSIZE = @DOXYGEN_FORMULA_FONTSIZE@ +FORMULA_MACROFILE = @DOXYGEN_FORMULA_MACROFILE@ +USE_MATHJAX = @DOXYGEN_USE_MATHJAX@ +MATHJAX_VERSION = @DOXYGEN_MATHJAX_VERSION@ +MATHJAX_FORMAT = @DOXYGEN_MATHJAX_FORMAT@ +MATHJAX_RELPATH = @DOXYGEN_MATHJAX_RELPATH@ +MATHJAX_EXTENSIONS = @DOXYGEN_MATHJAX_EXTENSIONS@ +MATHJAX_CODEFILE = @DOXYGEN_MATHJAX_CODEFILE@ +SEARCHENGINE = @DOXYGEN_SEARCHENGINE@ +SERVER_BASED_SEARCH = @DOXYGEN_SERVER_BASED_SEARCH@ +EXTERNAL_SEARCH = @DOXYGEN_EXTERNAL_SEARCH@ +SEARCHENGINE_URL = @DOXYGEN_SEARCHENGINE_URL@ +SEARCHDATA_FILE = @DOXYGEN_SEARCHDATA_FILE@ +EXTERNAL_SEARCH_ID = @DOXYGEN_EXTERNAL_SEARCH_ID@ +EXTRA_SEARCH_MAPPINGS = @DOXYGEN_EXTRA_SEARCH_MAPPINGS@ +GENERATE_LATEX = @DOXYGEN_GENERATE_LATEX@ +LATEX_OUTPUT = @DOXYGEN_LATEX_OUTPUT@ +LATEX_CMD_NAME = @DOXYGEN_LATEX_CMD_NAME@ +MAKEINDEX_CMD_NAME = @DOXYGEN_MAKEINDEX_CMD_NAME@ +LATEX_MAKEINDEX_CMD = @DOXYGEN_LATEX_MAKEINDEX_CMD@ +COMPACT_LATEX = @DOXYGEN_COMPACT_LATEX@ +PAPER_TYPE = @DOXYGEN_PAPER_TYPE@ +EXTRA_PACKAGES = @DOXYGEN_EXTRA_PACKAGES@ +LATEX_HEADER = @DOXYGEN_LATEX_HEADER@ +LATEX_FOOTER = @DOXYGEN_LATEX_FOOTER@ +LATEX_EXTRA_STYLESHEET = @DOXYGEN_LATEX_EXTRA_STYLESHEET@ +LATEX_EXTRA_FILES = @DOXYGEN_LATEX_EXTRA_FILES@ +PDF_HYPERLINKS = @DOXYGEN_PDF_HYPERLINKS@ +USE_PDFLATEX = @DOXYGEN_USE_PDFLATEX@ +LATEX_BATCHMODE = @DOXYGEN_LATEX_BATCHMODE@ +LATEX_HIDE_INDICES = @DOXYGEN_LATEX_HIDE_INDICES@ +LATEX_BIB_STYLE = @DOXYGEN_LATEX_BIB_STYLE@ +LATEX_EMOJI_DIRECTORY = @DOXYGEN_LATEX_EMOJI_DIRECTORY@ +GENERATE_RTF = @DOXYGEN_GENERATE_RTF@ +RTF_OUTPUT = @DOXYGEN_RTF_OUTPUT@ +COMPACT_RTF = @DOXYGEN_COMPACT_RTF@ +RTF_HYPERLINKS = @DOXYGEN_RTF_HYPERLINKS@ +RTF_STYLESHEET_FILE = @DOXYGEN_RTF_STYLESHEET_FILE@ +RTF_EXTENSIONS_FILE = @DOXYGEN_RTF_EXTENSIONS_FILE@ +GENERATE_MAN = @DOXYGEN_GENERATE_MAN@ +MAN_OUTPUT = @DOXYGEN_MAN_OUTPUT@ +MAN_EXTENSION = @DOXYGEN_MAN_EXTENSION@ +MAN_SUBDIR = @DOXYGEN_MAN_SUBDIR@ +MAN_LINKS = @DOXYGEN_MAN_LINKS@ +GENERATE_XML = @DOXYGEN_GENERATE_XML@ +XML_OUTPUT = @DOXYGEN_XML_OUTPUT@ +XML_PROGRAMLISTING = @DOXYGEN_XML_PROGRAMLISTING@ +XML_NS_MEMB_FILE_SCOPE = @DOXYGEN_XML_NS_MEMB_FILE_SCOPE@ +GENERATE_DOCBOOK = @DOXYGEN_GENERATE_DOCBOOK@ +DOCBOOK_OUTPUT = @DOXYGEN_DOCBOOK_OUTPUT@ +GENERATE_AUTOGEN_DEF = @DOXYGEN_GENERATE_AUTOGEN_DEF@ +GENERATE_SQLITE3 = @DOXYGEN_GENERATE_SQLITE3@ +SQLITE3_OUTPUT = @DOXYGEN_SQLITE3_OUTPUT@ +SQLITE3_RECREATE_DB = @DOXYGEN_SQLITE3_RECREATE_DB@ +GENERATE_PERLMOD = @DOXYGEN_GENERATE_PERLMOD@ +PERLMOD_LATEX = @DOXYGEN_PERLMOD_LATEX@ +PERLMOD_PRETTY = @DOXYGEN_PERLMOD_PRETTY@ +PERLMOD_MAKEVAR_PREFIX = @DOXYGEN_PERLMOD_MAKEVAR_PREFIX@ +ENABLE_PREPROCESSING = @DOXYGEN_ENABLE_PREPROCESSING@ +MACRO_EXPANSION = @DOXYGEN_MACRO_EXPANSION@ +EXPAND_ONLY_PREDEF = @DOXYGEN_EXPAND_ONLY_PREDEF@ +SEARCH_INCLUDES = @DOXYGEN_SEARCH_INCLUDES@ +INCLUDE_PATH = @DOXYGEN_INCLUDE_PATH@ +INCLUDE_FILE_PATTERNS = @DOXYGEN_INCLUDE_FILE_PATTERNS@ +PREDEFINED = @DOXYGEN_PREDEFINED@ +EXPAND_AS_DEFINED = @DOXYGEN_EXPAND_AS_DEFINED@ +SKIP_FUNCTION_MACROS = @DOXYGEN_SKIP_FUNCTION_MACROS@ +TAGFILES = @DOXYGEN_TAGFILES@ +GENERATE_TAGFILE = @DOXYGEN_GENERATE_TAGFILE@ +ALLEXTERNALS = @DOXYGEN_ALLEXTERNALS@ +EXTERNAL_GROUPS = @DOXYGEN_EXTERNAL_GROUPS@ +EXTERNAL_PAGES = @DOXYGEN_EXTERNAL_PAGES@ +HIDE_UNDOC_RELATIONS = @DOXYGEN_HIDE_UNDOC_RELATIONS@ +HAVE_DOT = @DOXYGEN_HAVE_DOT@ +DOT_NUM_THREADS = @DOXYGEN_DOT_NUM_THREADS@ +DOT_COMMON_ATTR = @DOXYGEN_DOT_COMMON_ATTR@ +DOT_EDGE_ATTR = @DOXYGEN_DOT_EDGE_ATTR@ +DOT_NODE_ATTR = @DOXYGEN_DOT_NODE_ATTR@ +DOT_FONTPATH = @DOXYGEN_DOT_FONTPATH@ +CLASS_GRAPH = @DOXYGEN_CLASS_GRAPH@ +COLLABORATION_GRAPH = @DOXYGEN_COLLABORATION_GRAPH@ +GROUP_GRAPHS = @DOXYGEN_GROUP_GRAPHS@ +UML_LOOK = @DOXYGEN_UML_LOOK@ +UML_LIMIT_NUM_FIELDS = @DOXYGEN_UML_LIMIT_NUM_FIELDS@ +DOT_UML_DETAILS = @DOXYGEN_DOT_UML_DETAILS@ +DOT_WRAP_THRESHOLD = @DOXYGEN_DOT_WRAP_THRESHOLD@ +TEMPLATE_RELATIONS = @DOXYGEN_TEMPLATE_RELATIONS@ +INCLUDE_GRAPH = @DOXYGEN_INCLUDE_GRAPH@ +INCLUDED_BY_GRAPH = @DOXYGEN_INCLUDED_BY_GRAPH@ +CALL_GRAPH = @DOXYGEN_CALL_GRAPH@ +CALLER_GRAPH = @DOXYGEN_CALLER_GRAPH@ +GRAPHICAL_HIERARCHY = @DOXYGEN_GRAPHICAL_HIERARCHY@ +DIRECTORY_GRAPH = @DOXYGEN_DIRECTORY_GRAPH@ +DIR_GRAPH_MAX_DEPTH = @DOXYGEN_DIR_GRAPH_MAX_DEPTH@ +DOT_IMAGE_FORMAT = @DOXYGEN_DOT_IMAGE_FORMAT@ +INTERACTIVE_SVG = @DOXYGEN_INTERACTIVE_SVG@ +DOT_PATH = @DOXYGEN_DOT_PATH@ +DOTFILE_DIRS = @DOXYGEN_DOTFILE_DIRS@ +DIA_PATH = @DOXYGEN_DIA_PATH@ +DIAFILE_DIRS = @DOXYGEN_DIAFILE_DIRS@ +PLANTUML_JAR_PATH = @DOXYGEN_PLANTUML_JAR_PATH@ +PLANTUML_CFG_FILE = @DOXYGEN_PLANTUML_CFG_FILE@ +PLANTUML_INCLUDE_PATH = @DOXYGEN_PLANTUML_INCLUDE_PATH@ +DOT_GRAPH_MAX_NODES = @DOXYGEN_DOT_GRAPH_MAX_NODES@ +MAX_DOT_GRAPH_DEPTH = @DOXYGEN_MAX_DOT_GRAPH_DEPTH@ +DOT_MULTI_TARGETS = @DOXYGEN_DOT_MULTI_TARGETS@ +GENERATE_LEGEND = @DOXYGEN_GENERATE_LEGEND@ +DOT_CLEANUP = @DOXYGEN_DOT_CLEANUP@ +MSCGEN_TOOL = @DOXYGEN_MSCGEN_TOOL@ +MSCFILE_DIRS = @DOXYGEN_MSCFILE_DIRS@ diff --git a/build-coverage/Doxyfile.qtty_cpp b/build-coverage/Doxyfile.qtty_cpp new file mode 100644 index 0000000..beddd9e --- /dev/null +++ b/build-coverage/Doxyfile.qtty_cpp @@ -0,0 +1,65 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "qtty-cpp" +PROJECT_NUMBER = "0.1.0" +PROJECT_BRIEF = "Header-only C++ wrapper for qtty" +PROJECT_LOGO = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/../../public/logo.png" +OUTPUT_DIRECTORY = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/build-coverage/docs/doxygen" +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp" +STRIP_FROM_INC_PATH = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/include" + +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = YES + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +INTERNAL_DOCS = NO + +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO + +INPUT = \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/docs" \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/docs/mainpage.md" \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/docs/README.md" \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/include/qtty" +FILE_PATTERNS = *.hpp *.md +RECURSIVE = YES +EXAMPLE_PATH = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/examples" +EXAMPLE_PATTERNS = *.cpp +USE_MDFILE_AS_MAINPAGE = "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/docs/mainpage.md" + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +SKIP_FUNCTION_MACROS = YES +INCLUDE_PATH = \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/include" \ + "/home/valles/workspace/siderust/siderust-cpp/qtty-cpp/qtty/qtty-ffi/include" + +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES + +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_DYNAMIC_MENUS = YES +GENERATE_TREEVIEW = YES +TOC_INCLUDE_HEADINGS = 2 + +GENERATE_LATEX = NO +GENERATE_XML = NO diff --git a/gen_cpp_units/src/main.rs b/gen_cpp_units/src/main.rs index 520c951..9a3f689 100644 --- a/gen_cpp_units/src/main.rs +++ b/gen_cpp_units/src/main.rs @@ -138,10 +138,10 @@ fn parse_csv(path: &Path) -> Vec { continue; } - // Split on (at most) 5 commas to protect ratio values that may - // themselves contain commas (defensive, though none currently do). - let parts: Vec<&str> = line.splitn(5, ',').collect(); - if parts.len() != 5 { + // Split on commas — we need at least 5 fields, but allow extra + // (e.g. an optional 6th field for Rust type path used by qtty-ffi). + let parts: Vec<&str> = line.splitn(6, ',').collect(); + if parts.len() < 5 { eprintln!("Warning: skipping malformed line: {line}"); continue; } diff --git a/include/qtty/ffi_core.hpp b/include/qtty/ffi_core.hpp index ba364e4..c25daaa 100644 --- a/include/qtty/ffi_core.hpp +++ b/include/qtty/ffi_core.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -101,12 +102,27 @@ inline void check_status(int32_t status, const char *operation) { // Forward declarations template class Quantity; +template struct CompoundTag; + +// Type trait to detect compound (derived) unit tags +template struct is_compound : std::false_type {}; +template +struct is_compound> : std::true_type {}; +template +inline constexpr bool is_compound_v = is_compound::value; // Template trait to get unit ID from unit tag // Each unit tag (e.g., MeterTag) must specialize this template to provide // its corresponding C FFI unit ID constant (e.g., UNIT_ID_METER). // Specializations are auto-generated in include/qtty/units/*.hpp -template struct UnitTraits; +// +// For compound tags, specializations provide numerator_unit_id() and +// denominator_unit_id() instead of a single unit_id(). +template struct UnitTraits { + // Default symbol returns empty string. Specialize for units that have + // symbols. + static constexpr std::string_view symbol() { return ""; } +}; // Helper to extract tag from either a tag or Quantity // This allows .to<>() to accept both Quantity and KilometerTag, @@ -167,17 +183,39 @@ template class Quantity { template Quantity::type> to() const { using TargetTag = typename ExtractTag::type; - qtty_quantity_t src_qty; - qtty_quantity_t dst_qty; - - int32_t status = qtty_quantity_make(m_value, unit_id(), &src_qty); - check_status(status, "Creating source quantity"); - - status = qtty_quantity_convert(src_qty, UnitTraits::unit_id(), - &dst_qty); - check_status(status, "Converting units"); - return Quantity(dst_qty.value); + if constexpr (is_compound_v) { + // Compound → compound conversion via qtty_derived_convert + static_assert(is_compound_v, + "Cannot convert compound unit to simple unit"); + qtty_derived_quantity_t src_qty; + qtty_derived_quantity_t dst_qty; + + int32_t status = qtty_derived_make( + m_value, UnitTraits::numerator_unit_id(), + UnitTraits::denominator_unit_id(), &src_qty); + check_status(status, "Creating derived source quantity"); + + status = qtty_derived_convert( + src_qty, UnitTraits::numerator_unit_id(), + UnitTraits::denominator_unit_id(), &dst_qty); + check_status(status, "Converting derived units"); + + return Quantity(dst_qty.value); + } else { + // Simple unit conversion via qtty_quantity_convert + qtty_quantity_t src_qty; + qtty_quantity_t dst_qty; + + int32_t status = qtty_quantity_make(m_value, unit_id(), &src_qty); + check_status(status, "Creating source quantity"); + + status = qtty_quantity_convert(src_qty, UnitTraits::unit_id(), + &dst_qty); + check_status(status, "Converting units"); + + return Quantity(dst_qty.value); + } } // ======================================================================== @@ -283,7 +321,8 @@ template class Quantity { // ============================================================================ // Stream Insertion Operator // ============================================================================ -// Prints a quantity with its unit symbol, e.g., "1500 m" or "42.5 km" +// Prints a quantity's value (with unit symbol support for units that define +// it). template std::ostream &operator<<(std::ostream &os, const Quantity &q) { diff --git a/include/qtty/serialization.hpp b/include/qtty/serialization.hpp index 4a77ef9..76182fd 100644 --- a/include/qtty/serialization.hpp +++ b/include/qtty/serialization.hpp @@ -26,6 +26,8 @@ int32_t qtty_quantity_from_json_value(UnitId unit, const char *json, qtty_quantity_t *out); int32_t qtty_quantity_to_json(qtty_quantity_t src, char **out_json); int32_t qtty_quantity_from_json(const char *json, qtty_quantity_t *out); +int32_t qtty_derived_to_json(qtty_derived_quantity_t src, char **out); +int32_t qtty_derived_from_json(const char *json, qtty_derived_quantity_t *out); void qtty_string_free(char *s); } @@ -140,4 +142,62 @@ Quantity::type> from_json(std::string_view json) { } } // namespace serialization + +// ============================================================================ +// Compound Quantity Serialization +// ============================================================================ +// Serialize/deserialize derived quantities (e.g., velocity) via the Rust FFI. + +namespace derived_serialization { + +/** + * @brief Serialize a compound quantity as JSON. + * @tparam Tag CompoundTag type of the quantity. + * @param q Source compound quantity. + * @return JSON string. + */ +template std::string to_json(const Quantity &q) { + static_assert(is_compound_v, + "derived_serialization::to_json requires a compound quantity"); + qtty_derived_quantity_t src{}; + int32_t status = + qtty_derived_make(q.value(), UnitTraits::numerator_unit_id(), + UnitTraits::denominator_unit_id(), &src); + check_status(status, "Creating derived quantity for serialization"); + + char *out = nullptr; + status = qtty_derived_to_json(src, &out); + check_status(status, "Serializing derived quantity to JSON"); + return serialization::from_owned_c(out); +} + +/** + * @brief Deserialize a JSON string into a compound quantity. + * @tparam T CompoundTag or Quantity type. + * @param json JSON input string view. + * @return Deserialized compound quantity, converted to requested target units. + */ +template +Quantity::type> from_json(std::string_view json) { + using Tag = typename ExtractTag::type; + static_assert(is_compound_v, + "derived_serialization::from_json requires a compound type"); + qtty_derived_quantity_t out_qty{}; + int32_t status = qtty_derived_from_json(json.data(), &out_qty); + check_status(status, "Deserializing derived quantity from JSON"); + + // Convert to requested units if needed + if (out_qty.numerator != UnitTraits::numerator_unit_id() || + out_qty.denominator != UnitTraits::denominator_unit_id()) { + qtty_derived_quantity_t conv{}; + status = + qtty_derived_convert(out_qty, UnitTraits::numerator_unit_id(), + UnitTraits::denominator_unit_id(), &conv); + check_status(status, "Converting deserialized derived quantity"); + return Quantity(conv.value); + } + return Quantity(out_qty.value); +} + +} // namespace derived_serialization } // namespace qtty diff --git a/include/qtty/units/velocity.hpp b/include/qtty/units/velocity.hpp index c4077ba..88540ca 100644 --- a/include/qtty/units/velocity.hpp +++ b/include/qtty/units/velocity.hpp @@ -13,20 +13,16 @@ namespace qtty { // Compound Units: Velocity // ============================================================================ // Velocity is a derived quantity representing length divided by time. -// Unlike base dimensions (length, time, mass, etc.), compound units are not -// directly supported by the C FFI layer. Instead, we use C++ template -// metaprogramming to encode the compound relationship in the type system. +// Compound units are fully supported through the FFI layer via +// qtty_derived_make() and qtty_derived_convert(), which independently convert +// numerator and denominator units to produce the correct result. // // Design: CompoundTag encodes a quotient of -// two unit types. The division operator (/) creates instances by dividing -// the raw values, while the type system tracks the unit relationship. +// two unit types. The type system tracks the unit relationship at compile +// time, while the Rust FFI layer handles conversions at runtime. // -// Limitation: Conversions between different compound units (e.g., m/s to km/h) -// are not automatically supported. Users must manually convert numerator and -// denominator separately, then recombine. - -// Template for compound units (e.g., velocity = length/time) -template struct CompoundTag {}; +// Conversions between different compound units (e.g., m/s to km/h) are +// fully supported via the .to<>() method, just like simple unit conversions. // Velocity type alias using compound units // This is a template alias, not a concrete type. Instantiate with specific @@ -35,10 +31,6 @@ template using Velocity = Quantity< CompoundTag>; -// Note: The C API doesn't have explicit velocity unit IDs -// We create velocity by dividing length by time, operating on raw values -// No unit conversion is available for compound units through the C API - // ============================================================================ // Division Operator: Create Compound Units // ============================================================================ @@ -64,51 +56,56 @@ operator/(const Quantity &length, const Quantity &time) { // ============================================================================ // UnitTraits for Compound Units // ============================================================================ -// Provides symbols for common compound units. +// Compound tags expose numerator_unit_id() and denominator_unit_id() instead +// of a single unit_id(). The Quantity::to<>() template detects compound tags +// via is_compound_v<> and dispatches to qtty_derived_convert() accordingly. -// Generic template specialization for CompoundTag (requires units to have -// symbols) +// Generic template: derives unit IDs from the component tags template struct UnitTraits> { - // Compound units don't have a direct FFI unit ID - // Use UNIT_ID_METER as a placeholder (never actually used for conversion) - static constexpr UnitId unit_id() { return UNIT_ID_METER; } - static constexpr std::string_view symbol() { - // This is a compile-time symbol construction for compound units - // For runtime construction, we'd need to use std::string - // For now, we provide empty string as a fallback - return ""; + static constexpr UnitId numerator_unit_id() { + return UnitTraits::unit_id(); + } + static constexpr UnitId denominator_unit_id() { + return UnitTraits::unit_id(); } + static constexpr std::string_view symbol() { return ""; } }; -// Specializations for common velocity types +// Specializations for common velocity types: provide human-readable symbols template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_METER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_SECOND; } static constexpr std::string_view symbol() { return "m/s"; } }; template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_KILOMETER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_HOUR; } static constexpr std::string_view symbol() { return "km/h"; } }; template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_METER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_HOUR; } static constexpr std::string_view symbol() { return "m/h"; } }; template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_KILOMETER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_SECOND; } static constexpr std::string_view symbol() { return "km/s"; } }; template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_METER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_MINUTE; } static constexpr std::string_view symbol() { return "m/min"; } }; template <> struct UnitTraits> { - static constexpr UnitId unit_id() { return UNIT_ID_METER; } + static constexpr UnitId numerator_unit_id() { return UNIT_ID_KILOMETER; } + static constexpr UnitId denominator_unit_id() { return UNIT_ID_MINUTE; } static constexpr std::string_view symbol() { return "km/min"; } }; @@ -119,8 +116,11 @@ template <> struct UnitTraits> { // These improve readability but are purely convenience types—they're just // specific instantiations of Quantity>. -// Common velocity type aliases (constructed from division, not convertible) using MeterPerSecond = Quantity>; using KilometerPerHour = Quantity>; +using KilometerPerSecond = Quantity>; +using MeterPerHour = Quantity>; +using MeterPerMinute = Quantity>; +using KilometerPerMinute = Quantity>; } // namespace qtty diff --git a/qtty b/qtty index 8140428..b2e0c39 160000 --- a/qtty +++ b/qtty @@ -1 +1 @@ -Subproject commit 814042804bce724720662bd77158b1052e922450 +Subproject commit b2e0c39b99ad097e22088860e322d018682952ed diff --git a/tests/test_derived.cpp b/tests/test_derived.cpp index ce8bb47..12efd80 100644 --- a/tests/test_derived.cpp +++ b/tests/test_derived.cpp @@ -13,3 +13,48 @@ TEST_F(DerivedQuantityTest, VelocityCreation) { Velocity v1(10.0); EXPECT_EQ(v1.value(), 10.0); } + +TEST_F(DerivedQuantityTest, VelocityConversion) { + // 100 m/s should be 360 km/h + MeterPerSecond v_ms(100.0); + auto v_kmh = v_ms.to(); + EXPECT_NEAR(v_kmh.value(), 360.0, 1e-9); + + // Round-trip: 360 km/h → m/s + auto v_back = v_kmh.to(); + EXPECT_NEAR(v_back.value(), 100.0, 1e-9); +} + +TEST_F(DerivedQuantityTest, VelocityConversionKmToM) { + // 1 km/s should be 3600 km/h + KilometerPerSecond v_ks(1.0); + auto v_kmh = v_ks.to(); + EXPECT_NEAR(v_kmh.value(), 3600.0, 1e-9); +} + +TEST_F(DerivedQuantityTest, VelocityArithmetic) { + MeterPerSecond v1(10.0); + MeterPerSecond v2(5.0); + + auto sum = v1 + v2; + EXPECT_NEAR(sum.value(), 15.0, 1e-12); + + auto diff = v1 - v2; + EXPECT_NEAR(diff.value(), 5.0, 1e-12); + + auto scaled = v1 * 3.0; + EXPECT_NEAR(scaled.value(), 30.0, 1e-12); +} + +TEST_F(DerivedQuantityTest, VelocityFromDivision) { + // Create velocity from actual division + Kilometer dist(180.0); + Hour t(2.0); + auto v = dist / t; // type: KilometerPerHour + + EXPECT_NEAR(v.value(), 90.0, 1e-12); + + // Convert to m/s + auto v_ms = v.to(); + EXPECT_NEAR(v_ms.value(), 25.0, 1e-9); +}