conn, err := net.Dial("tcp", "localhost:8080")
if err != nil ...gzipWriter := gzip.NewWriter(conn) message := "Hello, this is compressed data!" _, err = gzipWriter.Write([]byte(message))
similary in rust: .. code-block:: rust
let stream = TcpStream::connect("127.0.0.1:8080")?; let mut encoder = GzEncoder::new(stream, Compression::default());
let message = "Hello, this is compressed data!"; encoder.write_all(message.as_bytes())?;
Well, these examples use a separate construct/writer for encapsulating the compression operations, but perhaps there's ways around to make it transparent, so that you'd use the standard syntax to write to sockets and get compressed data.
Could we have something like this in nim as well, given that it doesn't seem to support interfaces ? Inherit from Socket type maybe and add custom procs that wrap around the existing send/recv ? Use socketstreams instead of socket to write, but nim-lang/zip module only seems to expose a filestream ? zippy also doesn't support streams yet.
You have explicit example of that in zippy :
https://github.com/guzba/zippy/blob/master/examples/http_server.nim https://github.com/guzba/zippy/blob/master/examples/http_client.nim
that is not relevant to the topic
You can use the exact same logic shown in the example with std/socksts, who had send / recv proc on string
See : https://nim-lang.org/docs/net.html#send%2CSocket%2Cstring%2Cint https://nim-lang.org/docs/net.html#recv%2CSocket%2Cstring%2Cint%2Cint
I tried to get a proc as field in my client object, so i can swap it at runtime without having if else everywhere.
I have these definitions:
proc sendProcU(nntp: NNTP | AsyncNNTP, data: string) {.multisync.} =
await nntp.sock.send(data)
NNTPClientBase*[SocketType] = ref object
...
sendProc*: proc(nntp: NNTP | AsyncNNTP, data: string)
NNTP* = NNTPClientBase[Socket]
AsyncNNTP* = NNTPClientBase[AsyncSocket]
proc new(T: typedesc[NNTP | AsyncNNTP], host: string, port: Port, tlsPort = port, user, pass: string, tls: bool): T =
result = T(host: host, port: port, tlsPort: tlsPort, user: user, pass: pass)
when T is NNTP:
result.sock = newSocket()
result.sendProc = (proc (nntp: NNTP, data: string))sendProcU
else:
result.sock = newAsyncSocket()
result.sendProc = (proc (nntp: AsyncNNTP, data: string))sendProcU
This results in the error: ` Error: generic instantiation too nested` at the last line where the sendProc field is assigned. Any idea what I am doing wrong and how to fix it ?
Any idea what I am doing wrong and how to fix it ?
Instead of storing the proc as a field, why not use the type for static dispatch ?
proc sendProc(s: AsyncNNTP, ...) = discard
proc sendProc(s: NNTP, ...) = discard
proc new(T: typedesc[NNTP | AsyncNNTP], host: string, port: Port, tlsPort = port, user, pass: string, tls: bool): T =
result = T(host: host, port: port, tlsPort: tlsPort, user: user, pass: pass)
when T is NNTP:
result.sock = newSocket()
else:
result.sock = newAsyncSocket() # no need to store the proc
Here is the corrected version with improved spelling and grammar:
I’m not sure what you’re trying to do. Do you have an HTTP server and want to add compression to it? Mummy (https://github.com/guzba/mummy) already does this and is super performant in other ways. Do you have some sort of TCP protocol that needs ZIP compression? Just create a sendZipped/recvZipped and use Zippy (https://github.com/guzba/zippy) — it’s really fast, even faster than zlib in most cases. You probably don’t need streams; their overhead is significant. Are you worried about a single if? It likely won’t show up in your profiles, while streaming and compression will.
If you want ultimate speed, I recommend Supersnappy (https://github.com/guzba/supersnappy) instead; it’s a really fast compression for the amount of bytes you save. If you’re making a new protocol, I suggest going with UDP instead of TCP. Check out https://github.com/treeform/netty.
And all socket sends are handled by client.sendProc(data: string)
type
Compression = enum
uncompressed, gzip, deflate
NNTPContext = object
c: NNTP
comp: Compression
AsyncNNTPContext = object
c: AsyncNNTP
comp: Compression
proc sendGzip(c: NNTP, data: string) = ...
proc sendDeflate(c: NNTP, data: string) = ...
proc sendRaw(c: NNTP, data: string) = ...
proc send(ctx: NNTPContext, data: string) =
switch(ctx.comp)
case(uncompressed):
ctx.c.sendRaw(data)
case(gzip):
ctx.c.sendGzip(data)
case(deflate):
ctx.c.sendDeflate(data)
proc sendGzip(c: AsyncNNTP, data: string) = ...
proc sendDeflate(c: AyncNNTP, data: string) = ...
proc sendRaw(c: AsyncNNTP, data: string) = ...
proc send(ctx: AsyncNNTPContext, data: string) =
switch(ctx.comp)
case(uncompressed):
ctx.c.sendRaw(data)
case(gzip):
ctx.c.sendGzip(data)
case(deflate):
ctx.c.sendDeflate(data)