Make tovector and toquaternion return nil on invalid inputs
complete
WolfGang Senizen
Right now
tovector("cake")
Returns a zero vector and it should probably return
nil
insteadThis is how
tonumber
works for instance.It would also allow for easy testing of if a string is a vector
Current behavior
tovector("cake") -- <0.0, 0.0, 0.0>
tovector("<0,0,as>") -- <0.0, 0.0, 0.0>
tovector("<0,0,0") -- <0.0, 0.0, 0.0>
tovector("<0,0,0>") -- <0.0, 0.0, 0.0>
tovector("<1,1,1>") -- <1.0, 1.0, 1.0>
tovector("<0xFF,0Xff,0xFF>") -- <255.0, 255.0, 255.0>
Expected behavior
tovector("cake") -- nil
tovector("<0,0,as>") -- nil
tovector("<0,0,0") -- nil
tovector("<0,0,0>") -- <0.0, 0.0, 0.0>
tovector("<1,1,1>") -- <1.0, 1.0, 1.0>
tovector("<0xFF,0Xff,0xFF>") -- <255.0, 255.0, 255.0>
Log In
H
Harold Linden
complete
H
Harold Linden
WolfGang Senizen This should be fixed in the latest rollout, are you able to confirm?
WolfGang Senizen
Harold Linden
Hmmm, maybe....
local vecs = {
tovector("cake"), -- nil
tovector("<0,0,as>"), -- nil
tovector("<0,0,0"), -- nil
tovector("<0,0,0>"), -- <0.0, 0.0, 0.0>
tovector("<1,1,1>"), -- <1.0, 1.0, 1.0>
tovector("<0xFF,0Xff,0xFF>"), -- <255, 255, 255>
}
ll.OwnerSay(lljson.encode(vecs))
Prints
[null,null,"<0,0,0>","<0,0,0>","<1,1,1>","<255,255,255>"]
I would have expected the third one to fail too, and it to print
[null,null,null,"<0,0,0>","<1,1,1>","<255,255,255>"]
It seems at the moment not to test for the 'closing'
>
.Same for quaternions, and
toquaternion
H
Harold Linden
WolfGang Senizen: That's an unfortunate legacy of SL using
sscanf()
to parse coordinates and just checking the number of elements that were successfully parsed. <1,2,3
is actually a valid vector and will convert successfully in Mono and LSO2.I believe some people actually abuse this behavior to make their string payloads smaller by intentionally omitting the closing
>
, so if we did it here we might break compatibility with things that parse successfully in LSL.For ex in Mono:
default {
state_entry() {
llOwnerSay(llList2CSV([(vector)"<1,2,3"]));
}
}
prints
<1.000000, 2.000000, 3.000000>
WolfGang Senizen
Harold Linden
I guess, as long as its documented it should be fine.
H
Harold Linden
Yep! Improving the scripting documentation (with all the weird caveats only a handful of people noticed before) is going to be part of the beta phase :)
WolfGang Senizen
Harold Linden
So to double check, any string that starts with
<
and is followed by, numeric
,
numeric
,
numeric
... then anything or nothing after that, parses as a vectorH
Harold Linden
WolfGang Senizen Yeah, I believe that was caused by a misunderstanding of how
sscanf()
works 20+ years ago.You can see the implementation way back in the first public release of lscript.
sscanf()
does all sorts of weird stuff that you probably don't want in practice, but we decided to stick with that approach in tovector()
and toquaternion()
for compatibility.WolfGang Senizen
Harold Linden
It might be nice to in the future offer more options, a bit like how
tonumber
lets you pass a base tonumber("AA",16) -- 170
tovector("0xFFFFFF","RGB_HEX") -- <1,1,1>
tovector("<122,79,45>","HSL_2_RGB") -- whatever that is in rgb
tovector("<0,0,0", "strict") --- nil
Obviously strings might not be the best option, but conceptually
H
Harold Linden
WolfGang Senizen We probably won't overload
tovector()
with too much functionality like that, though separate utility functions might make sense for some of them (HSL<->RGB, etc).After looking at some of the actual usages of
(vector)
in LSL, I think we'd be okay to make the SLua tovector()
pattern more like \s*<\s*(num)\s*,(num)\s*,(num)\s*>?\s*
so that we still accept vectors without a trailing >
but don't mistake treat quaternion
s as if they're valid vector
s. A quaternion string representation being accepted in tovector()
is a bit silly.LSL on the new VM will still behave the same as before because our conformance harnesses require bug-for-bug compatibility with the Mono implementation to tell if we messed something up. I also don't doubt that someone is accidentally relying on this behavior for their existing LSL scripts :(
WolfGang Senizen
Harold Linden
Yeh, while its not really my place to decide, I don't think implementing "compatability" with LSL bugs / hacks in "slua" is a good idea, at least not to start from, LSL on luau needs them, but porting them to SLua seems counter productive.
Nobody is going to write a script in lsl or slua to communicate between them, BEFORE now. So if SLua implements to vector "correctly" then they will know they have to write vectors with closing
>
If they are trying to interpret output from some old script, they can write their own compatibility layer in slua to handle the output of whatever script.
SLua's to vector, should be as correct as possible from the start imo, and not "handhold" old lsl bugs or hacks, let the scripter handle that themselves if they need to.
H
Harold Linden
WolfGang Senizen Yeah that makes sense to me. LSL on Luau can behave the same as it currently does and SLua's
tovector()
can have more sane casting, probably \s*<\s*(num)\s*,(num)\s*,(num)\s*>\s*
so you can have non-significant whitespace wherever within the string. The issue of allowing whitespace in particular was a recent ask related to LSL: https://feedback.secondlife.com/scripting-bugs/p/whitespace-unexpectedly-breaks-string-to-vector-string-to-rot-typecastsH
Harold Linden
WolfGang Senizen FYI, this behavior is included in the newest update.
tovector()
is now different from (vector)str
in LSL in that it only allows whitespace around terms.H
Harold Linden
in progress
H
Harold Linden
We have a fix for this that will be part of an upcoming roll
H
Harold Linden
planned
That seems reasonable to me, unless there are any objections!
We were just mimicking the behavior of LSL casts, though given the behavior of
tonumber()
it seems returning nil
would be more idiomatic.WolfGang Senizen
Harold Linden
Also the old behavior can always be achieved with
tovector("cake") or vector.zero