-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ByteStream and generic read
proc to streams
#7481
Conversation
This adds a ByteStream that reads and writes `seq[byte]` to and from a stream. Might be useful for cryptography, or serialization. Along with that it also adds a generic `read` proc that takes the type you want to read instead of the old pattern of `read<typeName>`. This means that things like macros can easier create read statements, and it means that type aliases can be used as well like this `type MyInt = int16; stream.read(MyInt)`. The old read procs have been marked as deprecated, however since these are used in so many different libraries around it would be helpful to after a while put them behind a compile-time switch instead of removing them outright.
I'm for generic "read". ByteStream is identical to StringStream (which, as I understand, is intentional), so I don't really see how it is useful. Maybe StringStream should just expose |
Well, they aren't exactly equal. They work on different types, but both seq[byte] and string behave almost exactly the same (it might even be possible to do a dodgy cast between them). The reason to have seq[byte] as well is that all the crypto libraries are switching to it, along with probably many low-level serialisation and other IO related libraries. It's just a nice convenience. |
Maybe to add variant with Endian? |
I don't know if this is members of the D community trying to avoid Nim's square bracket generics syntax or not, but I've been seeing lots of use of typedesc recently. I always saw typedesc as a side feature for edge cases and cool tricks. Anyway, this isn't lovable: proc read*(s: Stream, kind: typedesc[bool]): bool =
read(s, result)
proc peek*(s: Stream, kind: typedesc[bool]): bool =
peek(s, result)
proc read*(s: Stream, kind: typedesc[int8]): int8 =
read(s, result)
proc peek*(s: Stream, kind: typedesc[int8]): int8 =
peek(s, result)
proc read*(s: Stream, kind: typedesc[int16]): int16 =
read(s, result)
proc peek*(s: Stream, kind: typedesc[int16]): int16 =
peek(s, result)
# goes for about 100 lines Instead, you can leverage generics: proc read*[T: bool|int8|int16|...](s: Stream): T =
read(s, result)
proc peek*[T: bool|int8|int16|...](s: Stream): T =
peek(s, result) On top of that, you can keep the char procs: proc read*[T: bool|int8|int16|...](s: Stream): T =
read(s, result)
proc peek*[T: bool|int8|int16|...](s: Stream): T =
peek(s, result)
proc read*[T: char](s: Stream): T =
if readData(s, addr(result), sizeof(result)) != 1: result = '\0'
proc peek*[T: char](s: Stream): T =
if peekData(s, addr(result), sizeof(result)) != 1: result = '\0' |
@hlaaftana I don't think it's is about D, it just subjective. It seems some people think It's possible to avoid the repetition even when using |
It's also a matter of runtime vs. compile time. Generics with |
It's not true, typedesc exists only during compile time (e.g. you can't do |
You can't claim generics are flawed just because the current syntax has ambiguities. In fact, I'd argue using typedesc in the call arguments adds more ambiguities. Some programmers could probably have trouble remembering whether if it was I also don't think you can write a proc variable like Speaking of var data: seq[int] = @[s.read(), s.read(), s.read()]
let name = s.readStr(length = s.read())
data.add(s.read()) Also;
This is essentially what generics are. Unrelated: about the line |
@zielmicha, sorry I was wrong about typedesc. To be honest most of this implementation is based on https://github.com/nim-lang/Nim/issues/7430#comment-376804300 and following the discussion there made it seem like typedesc was the best way to go. @hlaftaana, when it comes to ByteStreams most of the code is a verbatim copy of StringStreams. I didn't actually look at the code all that much other than making sure it would behave the same as a StringStream. |
My two cents: I also dislike this sudden trend to use |
let's move the side-discussion on when to use generics vs typedesc to here: #7517 ([RFC] guidelines for when to use typedesc vs generics) |
Can you add |
@data-man you can just add it yourself :) Just rip the code from this commit or my branch and create a new PR |
@PMunch |
result.readDataImpl = bsReadData | ||
result.peekDataImpl = bsPeekData | ||
result.writeDataImpl = bsWriteData | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we get a readBytes
or something for ByteStream
that returns seq[byte]
?
So, what is the conclusion about this?
|
Sorry, rejected. |
This adds a ByteStream that reads and writes
seq[byte]
to and from a stream. Might be useful for cryptography, or serialization.Along with that it also adds a generic
read
proc that takes the type you want to read instead of the old pattern ofread<typeName>
. This means that things like macros can easier create read statements, and it means that type aliases can be used as well like thistype MyInt = int16; stream.read(MyInt)
. The old read procs have been marked as deprecated, however since these are used in so many different libraries around it would be helpful to after a while put them behind a compile-time switch instead of removing them outright.