Pass ProtoWriteBuffer by reference instead of by value in virtual
encode() methods. This avoids copying both buffer_ and pos_ pointers
for every encode call - only a single pointer is passed.
Also simplifies encode_message since child writes directly advance
the shared pos_. Adds debug_check_size_ to verify calculate_size
matches actual encode output.
ProtoSize::calculate_size() already computes the exact encoded size
before encode() runs and is the boundary validation. The buffer is
pre-sized to match. Since the buffer size is always correct,
push_back() capacity checks on every byte are redundant overhead.
Rename ProtoWriteBuffer to ProtoWritePreSizedBuffer to document the
contract. Write through a raw uint8_t* pointer instead of push_back().
Pre-resize the buffer to include payload space before encoding.
Add ESPHOME_DEBUG_API bounds checks to validate writes stay within the
pre-sized region during development and integration testing.
ProtoSize::calculate_size() already computes the exact encoded size
before encode() runs and is the boundary validation. The buffer is
pre-sized to match. Since the buffer size is always correct,
push_back() capacity checks on every byte are redundant overhead.
Rename ProtoWriteBuffer to ProtoWritePreSizedBuffer to document the
contract. Write through a raw uint8_t* pointer instead of push_back().
Pre-resize the buffer to include payload space before encoding.
Add ESPHOME_DEBUG_API bounds checks to validate writes stay within the
pre-sized region during development and integration testing.
All send paths already call prepare_first_message_buffer which does
clear() + reserve() with the exact needed size, making the initial
reserve(64) redundant. Removing it saves 68 bytes of flash.
RAMAllocator with default flags is stateless — it's just a dispatch
wrapper over heap_caps_malloc/realloc/free. Remove the stored member
from SpiRamAllocator, using stack-local instances at each call site.
Also make RAMAllocator constructors constexpr so the compiler can
fully evaluate flag logic at compile time.
Note: SpiRamAllocator was initialized with RAMAllocator::NONE (0),
which is equivalent to default construction since the constructor
preserves the default ALLOC_INTERNAL | ALLOC_EXTERNAL flags when
no valid allocation flags are provided.
Co-Authored-By: J. Nick Koston <nick@koston.org>
RAMAllocator with default flags is stateless — it's just a dispatch
wrapper over heap_caps_malloc/realloc/free. There's no need to store
it as a class member. Use stack-local instances at each call site
instead, matching the pattern used in audio_transfer_buffer and
ring_buffer.
Co-Authored-By: J. Nick Koston <nick@koston.org>
RAMAllocator with default flags is stateless — it's just a dispatch
wrapper over heap_caps_malloc/realloc/free. There's no need to store
it as a class member. Use stack-local instances at each call site
instead, matching the pattern used in audio_transfer_buffer and
ring_buffer.
Co-Authored-By: J. Nick Koston <nick@koston.org>
RAMAllocator is stateless when using default flags — it's just a
dispatch wrapper over heap_caps_malloc/realloc/free. There's no need
to store it as a class member. Use stack-local instances at each call
site instead, matching the pattern used in audio_transfer_buffer and
ring_buffer.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Cannot confirm wifi_station_disconnect() synchronously clears the
lwIP netif LINK_UP flag on ESP8266 NONOS SDK. The comment doesn't
need to make claims about link state since the fix is simply that
the hostname never changes at runtime, making dhcp_renew() pointless.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dhcp_renew() loop was cargo-culted from Arduino ESP8266's
WiFi.hostname() which was designed for changing the hostname on
an already-connected system with multiple interfaces (WiFi+Ethernet).
In ESPHome, wifi_apply_hostname_() is only called from:
- setup_() — before WiFi connects (link never up)
- wifi_sta_connect_() — after wifi_disconnect_() (link always down)
The hostname is fixed at compile time and never changes at runtime.
Setting intf->hostname is sufficient — lwIP automatically includes
it in DHCP DISCOVER/REQUEST packets via LWIP_NETIF_HOSTNAME.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DHCP_STATE_BOUND alone is insufficient — during reconnection, DHCP
can remain BOUND from a previous connection while the link is down
(wifi_disconnect_() doesn't stop DHCP). Both conditions are needed:
DHCP must be BOUND and the interface must have link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>