<hightower4>
Hm why does Char#bytes return Array(Uint8) rather than Bytes? And, any hints how do I covert the array to Bytes? I wasn't successful doing so
<FromGitter>
<tenebrousedge> maybe you want `String#to_slice` ?
<FromGitter>
<bryansray> If I had a class that looked something like this: ⏎ ⏎ ```class SuccessEnvelope ⏎ def initialize(data : Object) ⏎ end``` ⏎ ⏎ Apparently, I can’t accept any type of *Object* … can someone point me in the right direction here? Is this not possible? [https://gitter.im/crystal-lang/crystal?at=5dc4c3ad6ba2347d2d5458d3]
<FromGitter>
<tenebrousedge> you probably want a generic
<FromGitter>
<bew> hightower4: for input handling, does using a fiber which reads in a blocking way from STDIN and sending through a channel all the chars would work? then you just need to check if the channel has data, or select from multiple channels from your main event loop
<FromGitter>
<ImAHopelessDev_gitlab> Nice chicago event, thanks @wontruefree for hosting it
<FromGitter>
<ImAHopelessDev_gitlab> Crystal deserves far more recognition!!!
<FromGitter>
<ImAHopelessDev_gitlab> This will help me a lot
ht_ has joined #crystal-lang
_whitelogger has joined #crystal-lang
ht_ has quit [Remote host closed the connection]
_whitelogger has joined #crystal-lang
yukai has quit [Ping timeout: 265 seconds]
alexherbo2 has joined #crystal-lang
<hightower4>
Hey what's the right way to create strings based on reading from IO? Specifically, how is it handled when the last byte(s) available for read aren't a complete character?
DTZUZO has quit [Ping timeout: 240 seconds]
<FromGitter>
<straight-shoota> hightower4: When reading strings they are usually either of predetermined size or delimited by some character. That's what `IO#read_fully` and `IO#gets` do.
<FromGitter>
<straight-shoota> You can look at the implementation. They keep reading until they either reach the limit or delimiter.
<hightower4>
yes but let's say I want to read accumulated strings from STDIN. Are you saying that there will never be the case that at the end of available buffer, only one half of multi-byte character will be available for read?
<FromGitter>
<asterite> that might happen, but non-UTF8 strings are a valid thing in the language
<hightower4>
I mean, can it happen that read is done while something else is just in the middle of writing 2 bytes, so only 1 byte gets read?
<hightower4>
Is this possible, and if yes what happens... does that half-char remain in the buffer, or it's read and I need recognize it and buffer it for the next read?
<hightower4>
Also, unrelated, how do I most conveniently convert types between Slice(Uint8) (i.e. Bytes) and Array(UInt8)? Maybe it's simple but I had problems trying to do it
DTZUZO has joined #crystal-lang
<FromGitter>
<yxhuvud> hightower4: Writes are atomic if you write to and from a file descriptor, but what guarantees are left if you write from a buffered IO, I don't know.
<FromGitter>
<asterite> Slice to Array is just `to_a`. Array to Slice is `Slice.new(array.to_unsafe, array.size)`
<FromGitter>
<yxhuvud> yikes. You certainly like macros.
<hightower4>
Wonderful, thanks asterite, yxhuvud
<FromGitter>
<christopherzimmerman> Is it currently possible to change the templates for API documentation without editing crystal's source code?
DTZUZO has quit [Ping timeout: 265 seconds]
<hightower4>
uhmm.. how would I block until something is available for read on the IO, and then read as string whatever content is in there?
<hightower4>
I can't seem to find the right combination of functions to do this, and of course I want to avoid polling
<FromGitter>
<didactic-drunk> If you know how much you want to read `io.read_fully slice`.
<hightower4>
I don't...
<hightower4>
I do know that I want to read the whole buffer available, as soon as I someknow get notified that something is available
<hightower4>
somehow*
<FromGitter>
<Blacksmoke16> as a string?
<hightower4>
yes
<FromGitter>
<Blacksmoke16> `.gets_to_end`?
<hightower4>
yes I tried it and it blocked indefinitely
<hightower4>
I'll try again
<FromGitter>
<Blacksmoke16> i think you'd have to use fibers
<FromGitter>
<Blacksmoke16> so that the main fiber can continue while waiting for input?
<hightower4>
yes, yes, it's fine that I block. It's that gets_to_end didn't give me "a" when I pressed "a". I suppose it was waiting for end of IO
<FromGitter>
<didactic-drunk> Keyboard input vs general `IO` reading.
<hightower4>
And I am looking for something that would unblock as soon as at least 1 byte was available on the IO, and then return me as string of variable length as much as it can read in one go
<FromGitter>
<didactic-drunk> By default the `tty` is line oriented. It doesn't send data to your program until you press enter.
<hightower4>
well I'm simplifying, I am reading from STDIN.raw
<hightower4>
I didn't get stumped on a level that low :)
<FromGitter>
<didactic-drunk> Example code?
<hightower4>
let me try again just in case.. then will post code if I can't get it to work
<hightower4>
I mean code is simple: STDIN.raw do |io| io.gets_to_end end
<hightower4>
this won't return... whereas I would want any function that returns as soon as something comes in to the io
<FromGitter>
<didactic-drunk> Hit `ctrl+d`
<FromGitter>
<didactic-drunk> But then it's done.
<hightower4>
not even ctrl+d helps when its in raw mode
<hightower4>
but as you confirm, that per-se is not the issue, but blocking till end of IO is, rather than til buffer is non-empty
<FromGitter>
<didactic-drunk> You'd need a nonblocking read in to tell when there's no more data.
<FromGitter>
<didactic-drunk> Which means polling. I don't see any way to use `select`
<hightower4>
hmmm... let me look up a comment from Daniel from yesterday, he gave me some idea with `select` when we thought some call wasn't blocking on its own
return0e has quit [Read error: Connection reset by peer]
return0e has joined #crystal-lang
<hightower4>
I'm gonna try get it to work with `select` idea, that failing I'll check if I can make those `read(limit)` functions which read *at most* limit bytes to somehow read while blocking until there is something, and that failing switch to your solution.
<hightower4>
didactic-drunk: also one option instead of gets_to_end which you used would be to read first byte in blocking mode like you suggest, and then read the rest of string from io.peek which is nonblocking, and then manually io.skip(size)
<FromGitter>
<didactic-drunk> Didn't know those were available. Thanks.
<hightower4>
that would make the complete solution even nice looking... provided that I really don't manage to find anything to block til first byte and then just read non-blocking
<hightower4>
didactic-drunk eh I found it... plain io.read(limit) will wait til first byte and read what it can and return. Now I just need to see if there is a string version of this, and if there isn't then I just need to read using io.read and convert to string from that manually
<hightower4>
yeah, doesn't seem there exists anything string-specific and of variable length and no delimiter...
<hightower4>
So looks like the definitive solution is to define max buffer, like b=Bytes.new(1024), then do len = io.read(b), and then do s = String.new b[0,len]
<hightower4>
Now, possibly the only remaining thing... how to make the destination buffer of io.read() be the same buffer used by String, so that I don't instantiate a new string object on every read
<hightower4>
I am looking at String constructors, and it seems like all .new() calls create a new string, just from various sources. So probably what I need to do is create one string using constructor buf = String.new(max_capacity), and then as destination of io.read() I should pass buf.to_unsafe which will give pointer to the bytes
<FromGitter>
<didactic-drunk> You probably don't want to do that. `String` is immutablish. It's expected to be immutable. If this is keyboard input your probably over optimizing.
<hightower4>
well yes, keyboard, but I am not thinking about people typing letters but about copy-pasting input with mouse, which can be a lot of bytes at once
<FromGitter>
<didactic-drunk> So a few paragraphs every once in a while? Wouldn't worry about it.
<hightower4>
ok, yeah, agreed, just wanted to be slick :)
<hightower4>
ok great, thanks again for discussion, I got a lot out of it
<FromGitter>
<wontruefree> @ImAHopelessDev_gitlab you are welcome I have enjoyed putting these together
DTZUZO has joined #crystal-lang
<hightower4>
Should the value of String.build()'s argument 'capacity' include +1 for the \0 at the end or not?
<FromGitter>
<asterite> it's taken into account
HumanG33k has quit [Ping timeout: 240 seconds]
HumanG33k has joined #crystal-lang
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
dannyAAM has quit [Quit: znc.saru.moe : ZNC 1.6.2 - http://znc.in]
<FromGitter>
<didactic-drunk> `Pointer` doesn't have `#each`?
<FromGitter>
<christopherzimmerman> Pointers don't have an associated size, so no
<FromGitter>
<christopherzimmerman> `Slice` is as close as you are going to get
woodruffw has quit [Ping timeout: 240 seconds]
woodruffw has joined #crystal-lang
<FromGitter>
<straight-shoota> @repromancer_gitlab Thanks for pointing out the old URLs are still accessible. They should redirect to the new one.
woodruffw has quit [Ping timeout: 240 seconds]
woodruffw has joined #crystal-lang
rohitpaulk has joined #crystal-lang
<FromGitter>
<greenbigfrog> is there something like Enumerable#select that will return the first valid?
<hightower4>
hey greenbig, how about #find ?
<hightower4>
"Returns the first element in the collection for which the passed block is true."
<FromGitter>
<greenbigfrog> thanks ⏎ (btw call em frog or gbf)
woodruffw has quit [Ping timeout: 276 seconds]
woodruffw has joined #crystal-lang
woodruffw has quit [Ping timeout: 240 seconds]
DTZUZO has quit [Ping timeout: 240 seconds]
woodruffw has joined #crystal-lang
sorcus has quit [Remote host closed the connection]
DTZUZO has joined #crystal-lang
sorcus has joined #crystal-lang
woodruffw has quit [Ping timeout: 246 seconds]
woodruffw has joined #crystal-lang
rohitpaulk has quit [Remote host closed the connection]
<alexherbo2>
what is the easiest way to create static binaries?
<alexherbo2>
I’ve seen multiple impl using alpine from there and there, is there an official documentation detailing the full steps (the content of files, docker, etc.) ?
<alexherbo2>
the official page does not provide details
<alexherbo2>
nor the wiki
<alexherbo2>
having an implementation example could be helpful
<alexherbo2>
or even a shards command to generate a "minimal template"
woodruffw has joined #crystal-lang
<raz>
is it safe to access a Hash concurrently from multiple fibers? (e.g. one fiber iterating and reading, the other writing)
<raz>
i kinda assume the answer is no, but can't find anything definitive in the docs
<FromGitter>
<tenebrousedge> have you read the comments in hash.cr ?
<FromGitter>
<tenebrousedge> I think it might be relatively safe
<raz>
@tenebrousedge nope, thanks for the pointer, i indeed should
<raz>
i'll go read and see if i can make sense of it :)
<FromGitter>
<tenebrousedge> from what I remember, hash elements are not updated in-place
<raz>
yep, in my case i'm not concerned about consistency. just don't want to bomb out with a "ConcurrentAccessError" or such.
<raz>
(i.e. it's ok for my use-case if the iterating fiber isn't guaranteed to see items that were added after the iteration started)
<FromGitter>
<tenebrousedge> how big is the hash?
<FromGitter>
<straight-shoota> raz, `Hash` is currently not thread-safe. But multithreading is only a preview feature right now. So you're probably not talking about that, right?
<raz>
@straight-shoota no, i'm not using threading. only fibers.
<FromGitter>
<straight-shoota> Just plain single-threaded concurrency is no issue, though.
<raz>
sweet!
<raz>
thanks, that saves me some mutex juggling
<FromGitter>
<straight-shoota> You don't need mutexes unless your running multiple threads
<FromGitter>
<straight-shoota> Fibers can only switch context at specific locations (`sleep`, waiting for IO, channel recv/send etc), all of these are safe and can't occur randomly in some code
<raz>
@tenebrousedge the hash will be tiny, tens of elements (but rapidly changing). for context: this is for managing timeouts in a messaging system. pending msg's sit in that hash and i'll iterate over it in a fiber every now and then to drop timed out ones.
<raz>
@straight-shoota excellent! thanks for confirming. i assumed that is how it works, but wasn't 100% sure. :)
woodruffw has quit [Ping timeout: 240 seconds]
<FromGitter>
<straight-shoota> alexherbo2, it's really not much more to it (at least in general): Grab a machine with musl-libc (either an alpine docker or whatever), install crystal and run `crystal build --static`.
<FromGitter>
<straight-shoota> It can be tricky though when you need to link C libraries which might or might not be easily available/linkable with musl.
<alexherbo2>
what are the absolute "minimal dependency list" for alpine image
<alexherbo2>
there is a ton of packages I don’t even know what they are for
<FromGitter>
<straight-shoota> Yeah those seem to be binary dependencies for that particular shard
<FromGitter>
<straight-shoota> What you need depends on what your application needs for linking
<FromGitter>
<straight-shoota> the "minimal" list is just `apk add crystal`
<alexherbo2>
I'm the author of 'batch', I don't use any fancy library
<alexherbo2>
TeddyDD sended me a pr with this dockerfile
<FromGitter>
<straight-shoota> They're not fancy at all. Most libraries are probably used by stlib modules.
<alexherbo2>
how to know?
<alexherbo2>
(which packages are required for static builds)
HumanG33k has quit [Quit: Leaving]
<FromGitter>
<straight-shoota> Static linking needs the same libraries as dynamic linking, just the static library versions `.a` instead of `.so`.
<FromGitter>
<straight-shoota> If you have a dynamically linked executable, you can check with `ldd` which libraries it is linked against
<FromGitter>
<straight-shoota> You'll need them for static linking as well. But some might already be available by default on the build system
<alexherbo2>
oh nice tips thanks!
<FromGitter>
<straight-shoota> So the best way is to start with nothing and try it. The compiler will tell you which libraries are missing.
<alexherbo2>
thanks for pointing out ldd
<FromGitter>
<straight-shoota> Then you need to look them up. For alpine you can find them on https://pkgs.alpinelinux.org/ Static packages usually have a `-static` suffix. Sometimes it might be `-dev`.
<FromGitter>
<straight-shoota> I'm pretty sure most of the packages listed in TedyDD's Dockerfile won't be necessary. They're similar to those used for compiling the Crystal compiler and most of the standard library. It's unlikely your shard needs llvm.
<FromGitter>
<straight-shoota> Oh, I looked at your source code. It doesn't use anything from stdlib except `option_parser` which is entirely implemented in crystal. So you really shouldn't need to install any libraries.
<hightower4>
Hey what's the best way to split string into chars, but have the resulting chars still keep type String? (There is obviously String#chars but it changes type to Char)
<FromGitter>
<tenebrousedge> `split` I think
<hightower4>
tenebrousedge: ah indeed, split("") does work
<hightower4>
thanks
<FromGitter>
<tenebrousedge> :plus1:
HumanG33k has joined #crystal-lang
HumanG33k has quit [Read error: Connection reset by peer]
<alexherbo2>
straight-shoota: what would you put in RUN then?
<FromGitter>
<straight-shoota> Hm, nothing. You only need it as a build stage, right?
<FromGitter>
<straight-shoota> erh
<FromGitter>
<bajro17> @watzon how was last night at meeting?
<FromGitter>
<straight-shoota> sry, I thought you meant entrypoint
<FromGitter>
<watzon> What meeting?
<FromGitter>
<straight-shoota> `RUN apk add --no-cache --update-cache crystal` should do
<FromGitter>
<bajro17> Chicago?
<FromGitter>
<watzon> I wasn't at that one haha, mine was last month
<FromGitter>
<bajro17> oh I see you put you going on this site
<FromGitter>
<bajro17> Sorry :)
<FromGitter>
<watzon> Oh I must've marked the wrong one
<FromGitter>
<watzon> Yeah I missed it
<alexherbo2>
straight-shoota: yes
<alexherbo2>
nothing ? xD
<FromGitter>
<straight-shoota> see next
<alexherbo2>
`RUN apk add --no-cache --update-cache crystal` I don’t see --static
<FromGitter>
<straight-shoota> That only installs the package
<FromGitter>
<straight-shoota> compiling should be another one
<alexherbo2>
(how to access the buit binary, once built in the image)
<FromGitter>
<straight-shoota> Typically, you would mount the current working directory inside the container to access the code. The compiled binary should then also be available from outside the container. `bin/batch` (or whatever you decide to name it)
mps has joined #crystal-lang
woodruffw has quit [Ping timeout: 276 seconds]
woodruffw has joined #crystal-lang
ht_ has quit [Quit: ht_]
<alexherbo2>
straight-shoota: what would be a good name for a make command to build the static with docker?