01:52:21  * DarkGodquit (Write error: Broken pipe)
04:00:16  * SkyRocknRolljoined
07:25:10  * SkyRocknRollquit (Ping timeout: 240 seconds)
08:30:28  * DarkGodjoined
10:07:03  * rendarjoined
11:02:24  * rendarquit (Ping timeout: 255 seconds)
11:21:24  * DarkGodquit (Quit: Leaving)
11:24:43  * rendarjoined
13:52:07  * DarkGodjoined
15:21:00  * Go-use-CTCP-Schanged nick to CTCP-User
15:53:50  * LuaStonedquit (Remote host closed the connection)
15:54:04  * LuaStonedjoined
17:29:18  <CTCP-User>I hate reverse-engineering :/
17:30:24  <rphillips>CTCP-User: what are you reversing?
17:30:29  <CTCP-User>coro-net
17:30:34  <rphillips>ah
17:30:43  <CTCP-User>not even a single comment
17:30:46  <CTCP-User>>.>
17:40:48  <SinisterRectus>have you had a look at the other files that use it
17:41:10  <SinisterRectus>not that they are documented, but at least there are some examples
17:45:05  <CTCP-User>https://themissingdocs.tumblr.com/post/156361295623/luvit-creationixcoro-net-api
17:45:34  <CTCP-User>things I learned while writing that: tumblr sucks.
18:23:41  * DarkGodquit (Ping timeout: 240 seconds)
19:02:38  <creationix>I found some bugs in rphillips/options. Published to lit by rphillips but authored by pancake
19:02:58  <creationix>there is no homepage in the lit metadata? Do you know where the source is?
19:04:09  <rphillips>creationix: https://github.com/rphillips/luvit-options
19:04:21  <rphillips>forked from https://github.com/radare/luvit-options
19:07:52  <creationix>thanks
19:07:52  <creationix>PR incoming
19:09:03  <creationix>https://github.com/rphillips/luvit-options/pull/1
19:09:54  <rphillips>thanks
19:09:57  <rphillips>merged
19:11:08  <creationix>btw, how do you test new agent checks?
19:11:14  <creationix>I ran it locally and it output the JSON data
19:11:27  <creationix>what's the lifecycle for hostinfo checks
19:22:25  <CTCP-User>creationix, what do you think of my docs?
19:23:10  <creationix>CTCP-User neat, I'll look at it later when I'm done with my meetin
19:24:00  <CTCP-User>creationix, also how do I read terminal input in a nonblocking way?
19:24:17  <creationix>convert stdin to a coro stream
19:24:36  <creationix>do you want to read data or write a interactive terminal?
19:24:42  <CTCP-User>just read lines
19:25:35  <creationix>wrapStream will turn a libuv stream (tty, tcp, pipe, etc) into a coroutine based read/write functions https://github.com/luvit/lit/blob/master/deps/coro-net.lua#L18
19:26:07  <CTCP-User>and how do I turn stdin into a libuv stream?
19:26:08  <creationix>if you want input line delimited, you might need a codec that buffers till new line and breaks at newlines
19:26:28  <creationix>you're in luvit or raw luvi or normal lua with luv?
19:26:33  <CTCP-User>luvit
19:29:31  <creationix>CTCP-User: ok, in luvit it's wrapped to either a TCP or PIPE libuv object here https://github.com/luvit/luvit/blob/master/deps/pretty-print.lua#L322-L324
19:29:46  <creationix>which is then exported here https://github.com/luvit/luvit/blob/master/deps/pretty-print.lua#L361
19:29:57  <creationix>so `require('pretty-print').stdin` should give you the raw libuv stream
19:30:50  <creationix>or easier, it's at `process.stdin.handle`
19:30:56  <creationix>CTCP-User ^
19:31:36  <CTCP-User>creationix, does wrapStream yield?
19:31:46  <creationix>no
19:32:06  <creationix>https://github.com/luvit/lit/blob/master/deps/coro-net.lua#L105-L106
19:32:35  <creationix>it does have half a dozen return values though
19:33:16  <creationix>if you don't give it a decoder, it will emit raw chunks which may or may not be line delimited
19:34:06  <CTCP-User>I have no idea how decoders work, look at the "themissingdocs" thing I linked
19:35:19  <CTCP-User>local b = "" while true do while not b:find("\r\n", 1, true) do local v, e = r() if v then b = b .. v else print("ERROR", e) end end DO_STUFF_HERE end
19:35:23  <CTCP-User>creationix, ^
19:35:45  <CTCP-User>where "r" is the read function
19:35:54  <creationix>ok, almost done. I'll write a decoder that supports arbitrary delimiters and check your docs
19:36:30  <CTCP-User>I even put "decode = nil, -- unknown" and "updateDecoder(decoder) -- unknown"
19:36:40  <CTCP-User>because, as I said, idk what they do
19:38:51  <CTCP-User>and yes I know this is horrifying
19:40:11  <creationix>do decoders are optional
19:40:25  <creationix>by default it emits raw chunks as they come from the system as lua strings
19:40:30  <creationix>so tcp packets, etc
19:40:47  <creationix>decoders let you convert that to anything and change the number of events
19:41:00  <creationix>one tcp packet could contain 50.5 lines of text
19:41:13  <creationix>it would emit 50 events and keep the extra half line to merge with the next tcp packet
19:41:49  <creationix>the http codec reads tcp packets and converts to one big lua table for headers and status and then events for body chunks
19:42:03  <creationix>if it was chuncked-encoding they are turned into plain chunks
19:42:13  <CTCP-User>TCP packets aren't a thing
19:42:14  <creationix>and then it emits an empty string to signal end of http body
19:42:32  <CTCP-User>or rather, they are
19:42:35  <CTCP-User>but not the way you're thinking
19:43:04  <CTCP-User>when you send a line and it's split in 20 packets, the other end could receive the packets out of order
19:43:19  <CTCP-User>it then reorders the packets and once all packets are received it triggers the event
19:43:26  <creationix>well whatever you call them, but at the libuv level you get arbitrarily sized pieces of the data stream
19:43:40  <CTCP-User>yes, but they're not packets
19:43:49  <creationix>you're right it's a little higher abstraction than raw tcp packets
19:44:30  <CTCP-User>you could say "raw data" I guess?
19:44:37  <creationix>stream chunk
19:45:08  <creationix>either way, the point of decoders is to take these arbitrarily chopped up chunks and reassemble them into something more convenient
19:45:14  <creationix>and also optionally parse them into objects
19:45:29  <CTCP-User>stream chunk doesn't apply to UDP because UDP is packets instead of streams
19:45:46  <creationix>udp isn't a stream in llibuv
19:45:50  <creationix>used to be, but they fixed that
19:45:50  <creationix>:)
19:46:09  <CTCP-User>oh alright
19:46:13  <creationix>so if you give my code a udp_t it will fail since the methods at the C level are different
19:46:34  <CTCP-User>so no udp coroutines?
19:46:57  <CTCP-User>anyway uh
19:47:10  <CTCP-User>please describe decoders as short as possible
19:47:21  <CTCP-User>including function signatures
19:47:32  <CTCP-User>(what goes in, what comes out, what it's expected to do, etc)
19:47:45  <creationix>uv_tty_t, uv_tcp_t, and uv_pipe_t are the three that support uv_stream_t
19:47:56  <creationix>I could probably add support for uv_udp_t and just emit events as they come
19:48:05  <creationix>it would be custom code though, a different wrapper
19:49:11  <creationix>here is a simpler codec for redis protocol https://github.com/creationix/redis-luvit/blob/master/libs/redis-codec.lua
19:49:32  <creationix>decode takes chunk
19:49:46  <creationix>and returns either:
19:49:51  <creationix>1. nothing if more data is needed to parse
19:50:01  <creationix>2. the first event and the leftover data
19:50:05  <creationix>It
19:50:28  <creationix>It's not the best API since it means slicing up data and doing lots of memcpy internally, but it works fairly well in practice
19:50:54  <creationix>I should have designed it to take (chunk, offset) and return (data, offset)
19:51:29  <creationix>the code calling the decoder is responsible for concatenating the leftover data with new events
19:51:46  <creationix>also it's responsible for re-feeding the leftover data to the decoder till it returns nil
19:59:06  * ldubjoined
19:59:23  <CTCP-User>creationix, what do you mean it's easier to do what I did? .-.
20:00:17  <creationix>?
20:00:38  <creationix>let me write up a decoder for line delimited strings. That seems to be a common request anyway
20:00:59  <creationix>and I'll pair it with an encoder that simply adds newlines
20:01:09  <creationix>for symmetry
20:08:05  <CTCP-User>creationix, you're basically telling me it's easier to use this: (1 sec let me tweak it a bit
20:08:36  <CTCP-User>local b = "" while true do while not b:find("\r\n", 1, true) do local v, e = r() if v then b = b .. v else print("ERROR", e) end end local v = b:sub(1, b:find('\r\n', 1, true) - 1) b = b:sub(b:find('\r\n', 1, true) + 2) DO_STUFF_WITH_v_HERE end
20:08:42  <CTCP-User>creationix, right?
20:09:09  <CTCP-User>uh r returns "ok, err" right?
20:09:23  <creationix>not sure, hard to read in that format
20:09:25  <CTCP-User>(r is the first value of wrapStream, or read)
20:09:56  <CTCP-User> F 02,99localF 99,99 b = F 05,99"F 99,99F 05,99"F 99,99 F 02,99whileF 99,99 F 02,99trueF 99,99 F 02,99doF 99,99 F 02,99whileF 99,99 F 06,99notF 99,99 b:find(F 05,99"F 99,99F 05,99\rF 99,99F 05,99\nF 99,99F 05,99"F 99,99, F 02,991F 99,99, F 02,99trueF 99,99) F 02,99doF 99,99 F 02,99localF 99,99 v, e = r() F 02,99ifF 99,99 v F 02,99thenF 99,99 b = b .. v F 02,99elseF 99,99
20:09:56  <CTCP-User>F 10,99printF 99,99(F 05,99"F 99,99F 05,99EF 99,99F 05,99RF 99,99F 05,99RF 99,99F 05,99OF 99,99F 05,99RF 99,99F 05,99"F 99,99, e) F 02,99endF 99,99 F 02,99endF 99,99 F 02,99localF 99,99 v = b:sub(F 02,991F 99,99, b:find(F 05,99'F 99,99F 05,99\rF 99,99F 05,99\nF 99,99F 05,99'F 99,99, F 02,991F 99,99, F 02,99trueF 99,99) - F 02,991F 99,99) b = b:sub(b:find(F 05,99'F
20:09:57  <CTCP-User>99,99F 05,99\rF 99,99F 05,99\nF 99,99F 05,99'F 99,99, F 02,991F 99,99, F 02,99trueF 99,99) + F 02,992F 99,99) DO_STUFF_WITH_v_HERE F 02,99endF 99,99
20:10:02  <CTCP-User>creationix, better?
20:10:18  <inex>what the fuck
20:10:35  <CTCP-User>uh looks like my IRC client didn't split it correctly
20:10:41  <CTCP-User>that was supposed to be syntax hilighted
20:10:49  <creationix>no worries, I reformatted it in my editor
20:11:06  <creationix>colored IRC text doesn't work in many clients anyway
20:11:29  <creationix>https://gist.github.com/creationix/70936904f18d496cd1a9e7706f54974d
20:11:59  <creationix>CTCP-User if you use a decoder you don't need this code
20:12:03  <creationix>just a sec...
20:12:13  <CTCP-User>creationix, show me what it looks like with a decoder
20:12:48  <creationix>for line in read do
20:12:48  <creationix> -- do stuff with line
20:12:48  <creationix>end
20:13:15  <CTCP-User>uh neat
20:16:35  <creationix>CTCP-User a line codec is easy https://gist.github.com/creationix/00d31eda01bb2aaca1091666b1c39f31
20:17:04  <creationix>could even make it configurable where instead of "\n" it allows any delimeter
20:17:31  <CTCP-User>creationix, how about this
20:17:37  <CTCP-User>switch that "" with a {}
20:17:42  <CTCP-User>(in the buffer code)
20:17:56  <creationix>buffer code?
20:18:06  <CTCP-User>then call the decoder with the new chunk and have it return an index
20:18:15  <CTCP-User>creationix, yeah in the wrapReader or w/e
20:18:31  <creationix>oh, you're talking about changing the interface to decoders
20:18:37  <CTCP-User>the one that does b = b .. raw
20:18:42  <CTCP-User>creationix, yeah, for performance
20:18:51  <creationix>yeah, it can be improved, but changing it breaks all the existing code using it
20:19:06  <creationix>basically we'll just need to add a new library that performs better and start migrating libs to it one at a time
20:19:08  <CTCP-User>creationix, true, but it's a third party lib so make it version 2.x
20:19:34  <creationix>or do a 2.x like you say
20:19:53  <creationix>you're still going to need concat in case of data being split across two chunks
20:20:11  <creationix>I don't want decoders to have to worry about a list of chunks for input
20:20:34  <CTCP-User>creationix, you give them the new chunk
20:20:41  <CTCP-User>if they return an index, you split
20:20:50  <creationix>I've done this before for something, not sure where the code went
20:20:54  <CTCP-User>since that's the most common use-case
20:21:23  <creationix>but `decode(chunk, offset) -> data, offset` is much better than `decode(chunk) -> data, extra`
20:21:32  <creationix>the wrapper is slightly more complex, but not much
20:21:42  <creationix>and decoders need to take offset into account, but that's not too bad
20:22:07  <creationix>actually decoders tend to get simpler since you can return offsets instead of constantly slicing to return extra
20:22:24  <CTCP-User>creationix, except you save a large amount of allocations and can use table.concat
20:22:51  <creationix>tables have overhead
20:23:01  <creationix>if I switch to string + offset it's pretty good actually
20:23:01  <CTCP-User>creationix, minimal compared to .. over and over again
20:23:21  <creationix>in string + offset as proposed, you only concat for cases where a value is split across chunks
20:23:21  <CTCP-User>with table.concat you allocate the full buffer once
20:23:41  <CTCP-User>yes, most cases
20:24:12  <creationix>I wouldn't say that's most cases
20:24:31  <creationix>besides, unless the decoder has to be aware of how to read into a table of chunks, tables won't help any
20:24:54  <CTCP-User>meh
20:25:03  <CTCP-User>I guess if you want performance you just have to do everything yourself
20:25:42  <creationix>and then it's really messy, you have `decode(vector,vector_offset,byte_offset)->data,vector_offset,byte_offset`
20:26:16  <creationix>and every read into the data is `vector[vector_offset]` on top of the byte_offset passed to string methods
20:26:31  <creationix>also you have to watch for boundaries and thus constantly query for the lengths of the vector pieces
20:26:51  <creationix>it's way too much overhead and complexity just to avoid small concats in case of crossed boundaries
20:27:26  <creationix>I'm sure there are cases where this does perform better, but generally it will perform worse and be *far* more complicated and error prone
20:28:02  <creationix>the cost/benefit ratio of string+offset is good, the ratio for table of strings is bad
20:30:05  <CTCP-User>return vector[vector_offset]:find("\r\n", 1, true)
20:30:10  <CTCP-User>is what I was hoping for
20:30:25  <creationix>it's not that simple
20:30:26  <CTCP-User>actually, return last_chunk:find("\r\n", 1, true)
20:30:32  <CTCP-User>and it'd concat all previous chunks for you
20:31:04  <CTCP-User>creationix, how often do you need to skip new data?
20:32:02  <creationix>what do you mean?
20:32:20  <CTCP-User>creationix, I saw that, also most of my CTCPs are broken
20:32:33  <CTCP-User>I'm too lazy to fix them tho
20:32:45  <CTCP-User>creationix, I mean, how often do you need to skip data in one of those decoders?
20:32:52  <CTCP-User>hmm
20:32:53  <CTCP-User>wait
20:32:56  <CTCP-User>here's a better idea
20:33:03  <CTCP-User>creationix, why not have decoders and splitters?
20:33:11  <creationix>yes with decoder you re-parse data you've already parsed
20:33:19  <creationix>that's why I was initially against this style
20:33:26  <creationix>but experience has told me that it's better overall
20:33:27  <CTCP-User>splitters just split the stream, decoders just parse the stream
20:33:46  <creationix>you can do both
20:33:55  <CTCP-User>splitters are blazing fast since they only care about the last_chunk (the one you get from the read call)
20:33:57  <creationix>just organize the order of code in your codec to bail as early as possible
20:34:09  <creationix>for example, a decoder that did line-delimited JSON
20:34:15  <creationix>scan for newline, if not there, bail
20:34:22  <creationix>next iteration is just scan again
20:34:26  <CTCP-User>decoders would be faster since the splitter would be doing the splitting and the decoder wouldn't have to worry about that as much
20:34:31  <creationix>you don't parse JSON till your'e sure it's all there
20:35:35  <CTCP-User>and it'd do things like skip part of the stream
20:35:35  <CTCP-User>reducing a ton of allocations
20:35:36  <CTCP-User>(and using a table as a buffer)
20:35:38  <creationix>much faster *and* simpler than interruptible/resumable streaming JSON parsers
20:35:39  <creationix>I've written them, I would know
20:36:21  <creationix>I understand what you want and can imagine cases where it's worth the cost
20:36:50  <creationix>but this generic coro-channel interface is not a good place
20:37:14  <creationix>a common example would be a REST service that returns a giant JSON body
20:37:37  <creationix>the HTTP codec would pass the http body chunks through as-is where you can collect them into a lua table
20:37:46  <creationix>then you can use table.concat once and JSON.parse once
20:37:52  <CTCP-User>creationix, the cost is minimal, I already have the whole code in my head
20:38:01  <CTCP-User>and the performance improvement would be fairly large
20:38:22  <creationix>I've written these and measured them
20:38:30  <creationix>the performance was not what I expected
20:38:51  <creationix>but you're welcome to write a fork or coro-wrapper that uses tables for buffer
20:38:55  <creationix>your decoders will be much more complicated
20:38:57  <CTCP-User>creationix, you talked about calling it with a table, you talked about calling it with a string
20:39:13  <CTCP-User>you didn't talk about having "splitters" and "decoders" as separate units that operate in sync with eachother
20:39:33  <CTCP-User>splitters would take a string, return a point where to split it
20:39:42  <creationix>I did actually, the HTTP + REST + giant JSON body example
20:39:44  <CTCP-User>decoders would take a string, return a string
20:40:07  <CTCP-User>creationix, is this actually much more complicated?
20:41:03  <creationix>the main problem with making it two layers is many protocols need coupling between them
20:41:10  <CTCP-User>function split(x) return x:find('\r\n', 1, true) end function decode(x) return x:gsub('\r\n', '') end
20:41:14  <creationix>you don't always know where to split before decoding partially
20:42:12  <creationix>git pack file streams being a nasty example
20:42:33  <creationix>the length header is the number of uncompressed bytes to expect, but what follows is a raw deflate stream of unknown length
20:42:35  <CTCP-User>creationix, local upvalue = -1 function split(x) if upvalue == -1 then upvalue = readint(x) if upvalue > #x-4 then upvalue = upvalue - #x-4 return nil end <other stuff here>
20:42:50  <CTCP-User>creationix, Lua has upvalues
20:42:51  <creationix>you don't know when to stop reading till your inflate state machine reaches end state
20:42:51  <CTCP-User>also, ouch
20:43:04  <CTCP-User>I mean
20:43:08  <CTCP-User>we could keep decoders as is
20:43:13  <CTCP-User>and add a splitter layer
20:43:20  <CTCP-User>that'd be backwards compatible and increase performance
20:43:49  <creationix>that might help
20:44:23  <creationix>adds a little complexity to the wrap api, but the new stuff can go at the end and be optional
20:44:31  <CTCP-User>for the git thing, use a plain decoder, for IRC, use a plain splitter (+ decoder if you wanna remove \r\n)
20:47:04  <CTCP-User>heh, funny how this went from documenting the API to improving the API
20:52:34  <creationix>yep
20:52:51  <creationix>so I think this could work well. I wonder if we need to update the splitter ever
20:53:01  <creationix>since it's coupled to the decoder, I would think so
20:57:46  <CTCP-User>or add a new arg to updateDecoder
20:58:02  <CTCP-User>right?
20:58:11  <CTCP-User>idk what updateDecoder actually does tho
20:58:17  <CTCP-User>so I might be spouting BS
20:58:19  <CTCP-User>:P
20:58:50  * ldubquit (Remote host closed the connection)
20:58:50  <creationix>hmm, looks like I was in the process of refactoring this before
20:59:03  <creationix>the coro-wrapper library looks interesting
20:59:36  <creationix>I think I was trying to decouple decoders from the conversion from libuv callbacks to coroutine blocking read/write functions
21:01:17  <creationix>so a custom splitter layer helps with the pathological case where a value is split across many chunks
21:01:20  * ldubjoined
21:01:35  <creationix>but we also need the offset input in decoder to solve the case where a chunk contains many events
21:01:49  * ldubquit (Read error: Connection reset by peer)
21:02:19  <creationix>one large chunk could contain hundreds or even thousands of lines. Without offset, we have to slice and allocate over and over for each line
21:02:54  <CTCP-User>oh
21:03:07  <CTCP-User>yes that's a good idea
21:03:14  <CTCP-User>but we don't want the buffer to grow indefinitely
21:03:27  <CTCP-User>creationix, how to clear the buffer?
21:03:44  <creationix>when the decoder returns nil it means it's done with the buffer and nothing is left
21:03:58  <creationix>it will be concatenated to the front of the next chunk
21:04:22  <creationix>(assuming there are extra bytes, this is often not the case in my testing)
21:04:51  <CTCP-User>o ok
21:04:54  <CTCP-User>alright
21:04:56  <creationix>I like thinking of this layer apart from the splitter helper
21:05:03  <creationix>they solve different problems
21:05:12  <CTCP-User>neat
21:05:43  <creationix>so the splitter's job is to efficiently merge many chunks
21:06:03  <creationix>since the decoder merges by concatting over and over, it doesn't do it well on it's own
21:06:50  <creationix>but a splitter (or merger or whatever) could quickly collect hundreds of chunks for a giant body and merge at once
21:07:05  <CTCP-User>yup
21:07:23  <creationix>changing the decoder to accept offset is a breaking change though
21:07:28  <creationix>might as well do both at once
21:07:37  <CTCP-User>ok
21:08:02  <creationix>and I'd really like to finish decoupling the decoder/splitter from the nasty libuv->coro translation code if it's possible to do without overhead
21:08:52  <creationix>this is nasty https://github.com/luvit/lit/blob/master/deps/coro-channel.lua
21:09:14  <creationix>but once you assume a base of coroutine-style streams, it's pretty simple https://github.com/luvit/lit/blob/master/deps/coro-wrapper.lua
21:09:47  <creationix>it does mean one extra closure since the wrapper takes read() and returns a new read()
21:09:56  <creationix>that's probably worth the costs
21:10:30  <creationix>and more importantly we can use the decoder/splitter logic on other streams, not just libuv streams
21:10:57  <creationix>makes unit tests for decoders easier
21:15:01  <creationix>rphillips if you publish a new version of rphillips/options to lit then the next agent version will pick it up I think
21:15:35  <creationix>I don't remember is the agent is published to lit
21:15:40  <creationix>*if
21:45:18  <creationix>CTCP-User ok, working on optimizing coro-channel
21:45:51  <creationix>another reason to decoulpe decoder from libuv shim is so we can easily add support for uv_udp_t
22:11:55  * DarkGodjoined
22:29:01  <creationix>CTCP-User Here is a simple merger function that helps for cases where there are too mane concatenations https://gist.github.com/creationix/579fa1244fe3b83fe8f1c0565c88b6f8
22:57:31  <rphillips>creationix: published that options package
22:57:38  <rphillips>0.0.6
22:57:38  <creationix>awesome thanks
22:57:47  <creationix>that will make errors in the agent CLI much easier to read
22:57:54  <rphillips>cool
22:57:57  <creationix>it was a tiny error message followed by 20 lines of stack trace
22:58:11  <creationix>took me 10 minutes to figure out the stack trace wasn't the root cause
23:03:46  <creationix>https://github.com/luvit/lit/pull/197
23:05:00  <rphillips>creationix: the string concat on line 103 is pretty slow
23:05:11  <rphillips>any way to tabelize it?
23:05:22  <creationix>that's what the merger helper up top is for
23:05:34  <creationix>you use merger if your protocol will have lots of concats
23:05:41  <rphillips>ah hah!
23:05:45  <creationix>this concat is for small events that get split across chunk boundaries
23:05:46  <rphillips>awesome
23:05:55  <rphillips>makes sense
23:06:25  <creationix>and the new index parameter to decoder will avoid lots of mem copies
23:06:57  <creationix>the concat in decode only happens if there was a partial event between chunks.
23:07:17  <creationix>(sub is also slow since it creates a new interned string in lua)
23:07:51  <creationix>I only use it on line 99 to avoid a case where a tiny tail is after a huge head of already used data
23:08:05  <creationix>again, this case only happens if there is leftover data between chunks
23:09:07  <creationix>or in other words, this only happens if decode returns nil asking for more data
23:09:27  <creationix>hence why merger is so useful, it helps ensure that for many cases, the decoder will always have enough data
23:13:06  * rendarquit (Ping timeout: 252 seconds)
23:25:52  <CTCP-User>creationix, don't use #parts
23:30:24  <SinisterRectus>?
23:42:12  * rendarjoined