Redesign (simplify) top-level avclan interface to use expected/nullable unique_ptr

- Peripheral::read/send now return `expected<unique_ptr<Frame>, Error>`
for a unified success/error interface.
- Peripheral::route returns `expected<unique_ptr<Frame>, Error>` to
distinguish intent: (intentional) non-response vs unable to respond
- Other functions with optional message semantics (handle,poll,react)
return a unique_ptr whose ownership-state indicates response intent
(i.e. send new message)

Bundled necessary changes:
- Switch Frame allocation from global to local (enabled via member
  function new/delete)
- Add new header-library tl::expected to shim avr-libstdcpp

Unrelated: Defensive `continue` added after `route`, to reduce Bus
activity check latency

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Allen Hill
2026-07-17 14:24:03 -07:00
parent 200a225add
commit 5208e083f3
17 changed files with 536 additions and 187 deletions
+70
View File
@@ -7,6 +7,7 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
add_compile_options(
-Wall -Wswitch-enum -Werror
@@ -76,6 +77,75 @@ target_include_directories(avclan PUBLIC
# flashing target. Added after the targets above so it can extend them.
add_subdirectory(src/avclan/target/${AVCLAN_TARGET})
# --- Polyfill headers for std facilities the toolchain may lack -------------
# tl::expected / tl::optional back-fill std::expected / std::optional (with
# C++23 monadic ops) when the build's stdlib predates them. Runs after the port
# subdirectory to provide a port-supplied freestanding stdlib via
# CMAKE_REQUIRED_INCLUDES, if necessary.
include(CheckCXXSourceCompiles)
include(FetchContent)
find_program(GIT_EXECUTABLE git REQUIRED)
if(TARGET libstdcpp)
get_target_property(_stdlib_incs libstdcpp INTERFACE_INCLUDE_DIRECTORIES)
set(CMAKE_REQUIRED_INCLUDES ${_stdlib_incs})
endif()
check_cxx_source_compiles("
#include <version>
#if !defined(__cpp_lib_expected) || __cpp_lib_expected < 202211L
#error no std::expected
#endif
int main() { return 0; }" HAVE_STD_EXPECTED)
# check_cxx_source_compiles("
# #include <version>
# #if !defined(__cpp_lib_optional) || __cpp_lib_optional < 202110L
# #error no C++23 std::optional
# #endif
# int main() { return 0; }" HAVE_STD_OPTIONAL)
unset(CMAKE_REQUIRED_INCLUDES)
if(NOT HAVE_STD_EXPECTED)
FetchContent_Declare(
tl_expected
GIT_REPOSITORY https://github.com/TartanLlama/expected.git
GIT_TAG 1770e3559f2f6ea4a5fb4f577ad22aeb30fbd8e4
PATCH_COMMAND ${CMAKE_COMMAND}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-DPATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/tl-expected-no-exception-header.patch
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/apply-patch.cmake
SYSTEM
)
set(EXPECTED_BUILD_TESTS OFF)
set(EXPECTED_BUILD_PACKAGE OFF)
FetchContent_MakeAvailable(tl_expected)
add_library(tl_expected_hdr INTERFACE)
target_include_directories(tl_expected_hdr
INTERFACE ${tl_expected_SOURCE_DIR}/include)
target_link_libraries(avclan PUBLIC tl_expected_hdr)
endif()
# std/tl::optional not currently used
# if(NOT HAVE_STD_OPTIONAL)
# FetchContent_Declare(
# tl_optional
# GIT_REPOSITORY https://github.com/TartanLlama/optional.git
# GIT_TAG 3a1209de8370bf5fe16362934956144b49591565
# PATCH_COMMAND ${CMAKE_COMMAND}
# -DGIT_EXECUTABLE=${GIT_EXECUTABLE}
# -DPATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/tl-optional-no-exception-header.patch
# -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/apply-patch.cmake
# SYSTEM
# )
# set(OPTIONAL_BUILD_TESTS OFF)
# set(OPTIONAL_BUILD_PACKAGE OFF)
# FetchContent_MakeAvailable(tl_optional)
# add_library(tl_optional_hdr INTERFACE)
# target_include_directories(tl_optional_hdr
# INTERFACE ${tl_optional_SOURCE_DIR}/include)
# target_link_libraries(avclan PUBLIC tl_optional_hdr)
# endif()
add_executable(mockingboard
src/sniffer.cc
)