I'm just a bit confused by the Wire reference and examples. The slave_receiver checks Wire.available() for the bytes remaining in the stream. But the reference says that Wire.available() is for use by a master, obsolete when onReceive() gets the number of received bytes as an argument. So why are you guessing that 1 byte is sent instead of the supplied byte count?
The original code uses
where it's unclear how many bytes (if ever) are transferred for a
Can you tell what is confusing in the official reference of Wire.available() ? I could make an issue at Github to make it more clear.
There are no bytes remaining in the stream. There is a (already received) package of data in a buffer. That package is always one byte if the Master sends a package of one byte, regardless how many packages the Master sends.
The data that should be transferred is a byte with a integer value between 1 and 50. That is what I use.
I know that the official examples are not okay. Ignore them.
I explain the Wire library in my Github wiki. My explanation should not even be needed, I only do that because the official Wire library reference is so confusing.
The return type of Wire.write() is confusing. A returned value has a type and meaning, else nothing remains to explain.
You miss to explain the slave side that always is part of any I2C transfer. It's clear that a master sends packages of an implied byte count, but the handling in the slave is unclear. I guess that onReceive() is called only after the transmission ends, and that a transmission overrides any preceding transmission data - as opposed to the Stream inheritance.
I'd expect something like "the returned value is garbage, don't use it". Else with a string write() it may be interesting to know how many bytes have been written, or a truncated write() due to a buffer overflow.
C allows to ignore returned data, that feature should not deserve a repetition with every function.