String/Stream/Serial strangeness (in a good way?)

I recently was playing around trying to make serial reception work more reliably, and found that the following command was much better about dropping packets and eliminating framing errors than anything I've previously done.

if (Serial.available()) evaluateCommand(Serial.readStringUntil(0x0D));

evaluateCommand() is a string parser that interprets a received command, and this reliably (for now) frames commands terminated with carriage return (0x0D) and interprets them. And fast!

I've been using this for almost a year in all my projects, but I realized today after talking with some friends that this REALLY is strange that it works. Even with interactively typed commands and a 10ms timeout setting. Weirder, it's faster than when I just read bytes upon a Serial.available() and put them one by one in a buffer. Even weirder, the Serial Stream must be reading the data without clearing it from the Serial Stream buffer because the full command is definitely being passed to evaluateCommand()!

For one, readStringUntil() is probably hitting the the timeout constantly, and the return from that as best I can tell should be the string so far as it's been received so far. Yet my evaluateCommand() code is definitely not constantly evaluating partial commands because I'd see them echoed back with an error for the incomplete command.

But the fact that as best I can tell the Stream is keeping the data in its buffer when the readStringUntil() times out is exceedingly weird.

I've been able to use this to get ~1kHz commands over USB serial to parse reliably, but it also works fine interactively. Does anyone know how on earth this is an acceptable situation?

I definitely don't want to rely on undocumented or undefined behavior in my functions, so a better way to do this is also welcome =)

Aha!

The examples in Serial Input Basics are simple, reliable and non-blocking - they don't need any timeout setting.

...R

You're making some bad assumptions about how things work.

I assume you are typing into a keyboard on a PC? If so, then nothing gets sent to the Arduino until you hit Enter, then the entire line of text is sent as quickly as possible, based on the BAUD rate you set. Even at 9600 BAUD, you'll never see a 10mSec timeout.

Regards,
Ray L.

RayLivingston:
You're making some bad assumptions about how things work.

I assume you are typing into a keyboard on a PC? If so, then nothing gets sent to the Arduino until you hit Enter, then the entire line of text is sent as quickly as possible, based on the BAUD rate you set. Even at 9600 BAUD, you'll never see a 10mSec timeout.

Regards,
Ray L.

I think that is accurate.

If you do actually interant with your sketch through a console terminal like Realterm (just hitting the keyboard, not at the "send" tab), perhaps your evaluateCommand callback needs to handle readStringUntil timeout return value.

By the way, does anyone knows how to do that? I mean, which is the String type return value of readStringUntil since timeout asigns String ret = (char)c;
c is declared as int, valued -1

Thanks.
Regards,
M!