I am currently working on translating some old exercises I did during a university course from C to Zig for the reason that you can get through quite a few edge cases there (this course was actually pretty darn good, especially in retrospective). In case you ask why I’m doing that: late night procrastination mostly.
In one exercise one needs to read in from stdin line by line and do something with each line. And if the line is above a certain length, ignore that line, log it and continue.
That sounds simple, and with fgets actually is.
With std.Io.Reader as it turns out, not so much.
Discarding is quite easy, call discardDelimiterInclusive and you are done (if you didn’t take the delimiter of that line already).
But for getting there, you have two choices: peekDelimiter* and takeDelimiter*. These don’t make much difference, but the real problem comes from choosing either the inclusive or the exclusive variant.
Let’s go over the inclusive one first. It is fine for the common case. But if the last line does not end with a line feed, you suddenly get an error.EndOfStream without receiving the last line. So now I have to figure out from the buffer of the reader if that’s because it’s at the end, or because the last line doesn’t end with a line feed.
So, what about the exclusive one? It is also fine for the common case and does not have the problem from the inclusive variants. But it gets a new problem. If a line is empty, you get error.EndOfStream instead of a slice of length 0. So now I have to figure out in the buffer of the reader if that’s because I am at the end of the stream, or because the current line is empty.
Both things are really annoying to deal with. Doable (in my case a lot of error handling was put into the condition of the while loop instead of the while’s else clause), but imo unnecessarily complicated.
I can maybe understand why one might want the behaviour of the inclusive variant (even if I think that people will silently loose data from not noticing that). But the exclusive one? Why not just return a slice of length 0 or a different error if a slice of length 0 isn’t wanted? That way you could separate both cases a lot easier.
So, what do the others think about this?