Can I get a
Slice pointing at a single
UInt8 without creating a new
Can I get a
Bytes is defined as just
alias Bytes = Slice(UInt8). With this in mind your question could be rephrased to “Can I get a
Slice … without creating a new
Slice …?” :)
So the answer is obviously no, just do
However maybe for your usecase you can avoid allocating the slice by not using a slice altogether? Always good to mention the underlying problem for which you seek a solution, rather than how to realize a solution you already came up with :)
This might be what you want:
x = 0u8 slice = pointerof(x).to_slice(1) slice = 1u8 p slice # => Bytes
It doesn’t allocate anything on the heap.
I really want to avoid heap allocation and
# The slice is allocated on the heap. macro slice(*nums, read_only = false)
Well you got your solution above :) Maybe there’s a safe and more idiomatic one though, one that doesn’t even need a slice…
How would you handle passing portions of c structs to
Digest#update and other stdlib methods that only take a
IO there’s the
write_bytes interface which is supported by all primitive types in stdlib, through the
to_io interface defined on them. One could expand on that by defining
to_io methods for compound types.
If something is type restricted to a
Slice argument with no alternative API, of course you need to get your hands onto a slice somehow :)
In general I still think providing the context on where you need something is still beneficial to the question quality and allows to offer solutions outside of the path you might have imagined so far. That’s all I was hinting at :)
@Didactic.Drunk can you provide some sample code of what you are trying to do?
slice = pointerof(struct.member).to_slice(1) digest.update slice
Memory allocations using
Bytes.new(1) were killing performance. I could keep a persistent
Bytes allocated but a
Slice directly to the
UInt8 seems like a better option.
Using pointerof is fine as long as you don’t give that pointer to something that keeps a reference to it.
def write_byte(byte : UInt8) x = byte write Slice.new(pointerof(x), 1) end
I’d also point out that
StaticArray doesn’t allocate on the heap, so it might actually be a viable, more high-level solution where you don’t need to work with pointers directly.
In the process of making a PR adding
write(byte : UInt8) to
Digest I wondered if it made more sense to add
Isn’t that what
DigestIO is for? So it gets methods like
IO#write_byte inherited for free?
I don’t think so. DigestIO calculates a
Digest of the unmodified stream as you read/write an
IO. I don’t have an
IO and if it was it’s not the entire stream or in order.
I wondered if it made more sense to add
The comment above is about adding easy
UInt8 compatibility for every function that accepts
Bytes which is more than
I think it’s fair if doing this is a bit hard,
IO#write_byte(s) is just so much more sane of an interface and we should push people towards it where possible. I don’t want people to end up with
write takes anything that responds to
#to_slice as does
Digest#update and many more.
What I propose:
io.write 1_u8 digest.update 2_u8 cipher.update 3_u8 any_duck_typed_to_slice_accepting_method 4_u8
If it’s not done at the
UInt8 level, code must be repeated for every function that wants to accept a
Slice | Byte
DigestIO is a misnomer and Should be
DigestIOWrapper or something less terrible, and then
Digest should just include
IO and disable
We have this wonderful
to_io interface, it would indeed be a shame to not use it.
Digest should even use a builder API akin to
String.build, yielding an
IO. Having to call
final on it always felt like an odd API to me.
write_byte for IO. I think having it for Digest is good too.
UInt8#to_slice will never happen because it’s unsafe. If you retain the slice and pass it around, it might crash your program or cause undefined behavior.