Which snippet is more performant and "better" for this situation? (Both deliver the exactly same result.) Slice:
let
result_raw = raw_string
tailLen = result_raw[0..0].parseHexInt()
result = result_raw[1..^1]
result.removeSuffix(spaces(tailLen))
Stream:
let
result_strm = raw_string.newStringStream()
tailLen = result_strm.readStr(1).parseHexInt()
result = result_strm.readAll()
result_strm.close()
result.removeSuffix(spaces(tailLen))
I generally found StringStream to be kind of slow (that is why I made the flatty/binny library).
But really what you want to do is profile, profile, profile. If this is not on a hot path it does not matter how slow it is. I recommend vTune. I have had a ton of success with vTune. Just compile your nim file with --debugger:native and run your exe with vTune. After a bit of getting used to it tells you where the hot paths are and how long stuff takes.
Well, your operations are a bit suspicious here. result_raw[0..0].parseHexInt() could be replaced with something like result_raw[0].parseHexDigit() where parseHexDigit is defined like:
proc parseHexDigit(ch: char): int =
case ch
of '0'..'9': ch.ord - '0'.ord
of 'a'..'f': ch.ord - 'a'.ord + 10
of 'A'..'F': ch.ord - 'A'.ord + 10
else: raise some error
Although this wouldn't be monstrously faster than parsing the string, you are talking about optimizing simple slice operations here, so might as well go for the most.
When you do result.removeSuffix(spaces(tailLen)), are you purposefully also accounting for the case where result doesn't exactly end with tailLen spaces? If you are sure that result ends with tailLen spaces and you have to remove those spaces, then you could just do result.setLen(result.len - tailLen). Even further, you can reduce the last 2 statements to result = result_raw[1..^(tailLen + 1)].
I don't know if Nim has any comprehensive ways of viewing string slices without copying yet despite all the work done on borrow checking, but I'm guessing you do want result to be a new, unique string so it wouldn't matter. What I will say is that newStringStream always creates a copy of a string, so you could create only 1 copy without using it (let result_raw = raw_string is an extra copy), but you must create 2 copies in this case if you want to use a stringstream.