Repository navigation
feat(xpp): introduce xpp::io::Error (bit-packed, replaces SocketError) - #206
Merged
Merged
Conversation
Bring net error reporting in line with std::io::Error:
- New xpp::io::Error in libx++/xpp/io/error.{h,cpp}. Single
uintptr_t storage; tag bits in the low 2 bits encode one of four
variants (SimpleMessage / Custom / Os / Simple). sizeof(Error) ==
sizeof(void*) and sizeof(Option<Error>) == sizeof(void*) via a
niche specialization.
- 26-variant ErrorKind covering std's cross-platform set plus
ResolveFailed / NoAddress (DNS-specific). errno_to_kind() maps
the POSIX subset; raw_os_error() preserves the original code so
callers can distinguish ECONNREFUSED from EHOSTUNREACH (which
the old SocketError collapsed into BindFailed/ConnectFailed).
- Custom variant uses a single allocation with a flexible-array
payload, so with_message(Kind, str) costs 1 alloc, not 2.
- XPP_IO_DEFINE_MSG macro for ODR-safe static (kind, message)
pairs — zero allocation at use sites.
- Migrated tcp / udp / dns / their tests. TcpListener::bind_addr,
TcpStream::connect_addr, accept(), and UdpSocket::bind_addr now
capture errno via from_errno(); the hostname overloads bubble up
the underlying io::Error. socket.h's old SocketError enum and
socket_error_message() helper are gone.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adopt the codebase's m_-prefix convention for the lone storage field of io::Error, the matching field on Option<io::Error>, and pick up the incidental clang-format pass on the io/ headers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
xpp::io::Errorinlibx++/xpp/io/error.{h,cpp}modeled afterstd::io::Error. Singleuintptr_tof storage, four variants packed into the two low tag bits:SimpleMessage— pointer to a static(kind, msg), zero allocationCustom— heap-allocated(kind, len, char[]), one allocationOs—i32errno +kind()derived viaerrno_to_kindSimple— bareErrorKindErrorKindmirrorsstd::io::ErrorKindplusResolveFailed/NoAddress.Option<io::Error>niche specialization keeps it at one pointer.SocketErrorenum. Net failure paths now carry the underlying errno (so callers can distinguishECONNREFUSEDfromEHOSTUNREACH, which the old enum lumped together).Why
SocketError's 8 categories collapsed every connect / bind / accept failure into one ofCreateFailed/BindFailed/ConnectFailed. Tokio usesstd::io::Erroreverywhere because that single type carries the OS errno, the cross-platform kind, and an optional message all in 8 bytes — debuggability and unification in one shot.Static guarantees
Allocation table
io::Error(ErrorKind)(implicit)io::Error::from_errno(int)io::Error::from_static(SimpleMessage*)io::Error::with_message(Kind, str)Test plan
build/xpp_test: 671 pass (was 649; +22 IoErrorTest).build-cxx20/xpp_test: 702 pass.build-cxx20/xpp_coro_test: 31 pass.IoErrorTest(22 cases): size invariants, every variant constructor, errno mapping (POSIX subset), Option niche, move semantics,to_stringgolden output, long messages, edge cases (from_errno(0), negative, null message).EXPECT_EQ(err, SocketError::X)→EXPECT_EQ(err.kind(), io::ErrorKind::Y).Notable behavior changes
TcpListener::bind,TcpStream::connect,UdpSocket::bind/connect,accept,set_nodelay/nodelaynow returnResult<…, io::Error>instead ofResult<…, SocketError>.err.raw_os_error()returnsSome(EADDRINUSE),err.kind()isErrorKind::AddrInUse.socket.h'sSocketErrorenum andsocket_error_message()helper are deleted.🤖 Generated with Claude Code