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
Move to_<num_type> from String to Slice #6389
Comments
Crystal strings are always UTF-8 encoded, so when it comes to number conversion they work in ASCII so to say. You cannot assume that any We should rather try to find an allocation free way to turn a |
I agree that Unfortunately, it can't be implemented because strings are layed out differently from every other class. Strings don't have a pointer to their data, they have their data directly after their class in memory, so it's impossible to turn a Bytes into a String without allocating. I think that |
I wouldn't mind having |
Having |
Give an error. We already have methods on slice that only work for byte slices. And byte slices are the most common slice type (in fact, but I would happily change Slice(T) to a non generic Bytes type and remove the Slice type from the std, or maybe keep the two but return Bytes instead of Slice(UInt8) in all cases). |
Ok, that's what I thought too. And I was also thinking about a |
Can't inherit from struct. They would be two different types with a few similar methods. |
oh right, then maybe make it as a wrapper like: struct Bytes
def initialize(@raw : Slice(UInt8))
end
forward_missing_to @raw
def to_i(...)
# ...
end
end |
A little copying is better than a little dependency. I won't get tired of saying that. |
just put it on string |
@asterite by "a little copying" you mean the 550 lines of |
It's bit less than that, because there's hexdump and others in Slice that should only belong to Bytes. Maybe adding such methods to Slice but only having them compile for a slide of bytes isn't that bad, though. |
I guess this could be a nice use case for extension methods as described in #6438 |
it's easy enough to throw a |
@jhass what do you mean in this paragraph:
By Note that in this case |
I would very much like to make basic string processing methods available for plain byte slices. Maybe an option for this could be the introduction of a special type (perhaps Example: record StringBuffer, data : Bytes
class String
def ==(other : StringBuffer)
to_slice == other.data
end
end
hash = {"foo" => "bar"}
hash[StringBuffer.new("xfoox".to_slice[1..-2])] # => "bar" Footnotes
|
A relevant consideration when working with arbitrary byte slices interpreted as string content is that there's no guarantee for a trailing null byte. With arbitrary byte slices, we cannot be sure that there's a trailing null byte. And in most practical use cases, there won't be any. |
Any attempt to expose these operations at the instance level would lead to the same conclusions as https://forum.crystal-lang.org/t/more-slices-less-alloc/4332/6, even if the type is only used internally, so I think they should only be available as class methods. |
I don't follow what difference class methods would make in this context compared to a typed instance with instance methods? |
Having |
Isn't it the same with storing I wouldn't worry about this too much though either way. We're talking about a very low level instrument intended for optimizing heavily used algorithms. It should be fine to require some careful handling in this context. |
IMO it is the intent that matters. If only Of course, if the answer to that is "people are equally likely to move entire original |
While working on a terminfo parsing library, where I manipulate Slice of bytes (
Bytes
type), I needed to convert digits to an actual number.I realized that all the
to_<num_type>
conversion methods (liketo_i64
,to_u8
,to_f
, ..) are inString
, and I needed to allocate aString
just to convert the bytes to a number.I think thoses methods should be available in
Slice
too. The number conversion methods don't need anything fromString
as they directly work with a pointer and a size. They can almost directly be copy/pasted toSlice
!I have a working branch with this change, I can make a PR when it's accepted!
Note: the only problem I see here is that those methods will now exists for all kind of Slice, not only
Slice(UInt8)
.. But maybe it's ok? or maybe we can add a macro check inside theto_<num_type>
methods that raise whenT != UInt8
?Another possibility would be to make
Bytes
a new type (not just an alias) that inherits fromSlice(UInt8)
so it's easier to add methods that works specifically on bytes.WDYT?
The text was updated successfully, but these errors were encountered: