37 Replies
it expects your buffer to be null terminated so if you don't provide a length then it can just scan for the first null to figure out the length itself
I think you end up using this init from String:
because StringRef has this init which doesn't require the length:
I am not 100% sure I am correct on the UnsafePointer to StringRef auto conversion but I am sure you are not using a
String.__init__
signature requiring a length.
Is you code magically working with the correct String length? The StringRef init I pointed to walks the pointer to find the length.interesting... what control flow causes it to use another type's constructor?
I think you are correct and that's horrible, we should fix it
when I put in the len (buf len + 1 for the 0 terminator), i get this crash:
Could you include the whole program?
Nothing to do with the constructor per se. Mojo finds the overload where each argument undergoes at most one implicit conversion.
those are the relevant lines
buf
got freed too earilyWhen you initialize a String from an UnsafePointer the String takes ownership to avoid a copy. So both
buf
and s
own the same pointer here and both try to free it.I haven't formed an opinion yet, if it's a bug I don't want to rush to judgment
otherwise, I how are you supposed to know it would init the
StringRef
first?Implicit conversion itself is not a bug. Accidentally making
String
constructable from UnsafePointer[Byte]
is.is there a solution?
Yea,
UnsafePointer[Byte].alloc
, or String._buffer_type(capacity=...)
so copy
If you don't need the data to be in
buf
anymore then I think you should make buf
a List[Byte]
instead of InlineArray
and then use the String initialization from List (which avoids a copy).once inline array supports slicing this gets easier
though it didn't occur to me that creating a list would take ownership of the inline array, that is so much easier
I'm not sure since inline array is allocated on the stack
I mean you wouldn't return that
s = String(List[UInt8](buf))
zero copy string right?This is more the idiom
actually, creating the list allocates
but that's beside the point
StringSlice(buf[:read])
would be ideal in this scope
and raise if not utf8You can in fact avoid alloc, using
InlineArray
would be equivalent.
yep I use the unsafe StringSlice elsewhere, thanks. Would be nice to have a safe version
could the span created when slicing an InlineArray have a local lifetime?
sorry to bring up rust again, but arrays are sliced all the time
What do you mean by local lt?
how does rust prevent this:
Ah, Mojo does "prevent" you from returning the
Span
unless you manually rebind the lifetime parameterso there's no unique danger in supporting
__getitem__
then?Not at all, it's just people haven't implemented it yet. You could add that to the stdlib if you are interested.
it's getting there
let me check if I'm allowed to
megacorp rules
FYI, Mojo stdlib is apache 2 with LLVM exceptions, so if you are allowed to contribute to most libs for Rust, you should be fine.
oh I see, the origin would be the array, nice
ok this is cool
StringRef.__init__(inout self, ptr: UnsafePointer[C_char], len: Int):
Except
StringRef
is an unsafe type mainly meant for C++ interop which you probably should avoid using, people are trying to replace them with string slice in the stdlibyeah, this is the easy way, thx
do you want a gh issue?
I actually already made a PR for it: https://github.com/modularml/mojo/pull/3698
GitHub
[stdlib] Make
StringRef
ctor from UnsafePointer[Byte]
keyword o...This issues was reported by @aurelian on Discord.
This prevents accidental UnsafePointer[Byte] to String implicit conversion through String ctor from StringRef.
sweet
Could you share your GitHub handle so I can give you credit in the description?
diocletiann. thanks!