SynchroLabs / SynchroServer

The Synchro Server platform
https://synchro.io
1 stars 2 forks source link

String.Format needs to support better type conversion #31

Open BobDickinson opened 9 years ago

BobDickinson commented 9 years ago

We currently format token strings using the .NET string formatting provided by String.Format(), see: http://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx

I ran into an issue today where I wanted to format the value of a slider for display. On some platforms the slider value is an integer, and on some it is floating point. When I attempted to use a "D" format specifier (for formatting an integer as an integer), and the value provided in the format string parameter (the resolved token) was a double, I got a System.FormatException " the specified format 'd' is invalid", which makes sense.

The problem is that when resolving tokens and putting them into the the parameter list, we don't really have any way of knowing what types they need to be (without parsing the format string). In Synchro, we need to be more forgiving of type conversion issues (at least in the specific case of formatting tokens, we should be as liberal as possible, even to the point of attempting to parse a string as a number if a number format is specified, or doing a potentially lossy conversion of a double to an integer if an integer is required). Essentially, if there is any way you could imagine the format operation succeeding, then it should succeed, and if it fails, it should fail "soft" (perhaps replacing the token with the ToString on the value as a worst-case fallback).

This is particularly relevant to the porting exercise, as we currently get the .NET String.Format via Xamarin/Mono. Given that we have to replace this with some other implementation on iOS and Android (presumably), it might make sense to adopt some different (but functionally comparable) string formatting approach and just implement it from scratch on all platforms so we can bend it to our will. In particular, if the string formatter understood the JToken/JValue interface, it could be a little smarter and remove one level of indirection/conversion. Maybe.

Right now I use percentage and fixed point formatting specifiers in a few places. I attempted, and gave up on, using an integer formatting specifier (though maybe fixed point with zero decimal places would work there). I could foresee date formatting being useful, maybe currency. Not sure what else.

BobDickinson commented 9 years ago

OK, this is fixed in the iOS Swift port.

There we parse out the format spec for each token, keep it with the token, and when resolving that token as a string, we apply it (this is all at the token level, not at the property value level as in .NET). Each format specifier can then validate and coerce the token as appropriate. In practice, we use TokenConverter.toDouble() to convert the token to double in all cases (this will parse strings, convert other types, etc), and then do any further conversion required per-formatter after that (such as converting to UInt for hex formatting). If the formatting fails in any way, we fall back to the string representation of the token value (using TokenConverter.toString(), which cannot fail).

This is generally a better approach I think and should probably be retrofitted to the . NET clients (and be the model for the Java client). This still allows us the use the numeric string formatter (so we're locale-specific), just at the token level and with better coercion to be more failsafe.

BobDickinson commented 9 years ago

I back-ported the iOS/Swift property value token formatter processing to .NET, which addresses the original issue of this bug (formatting failing hard when resolved token value was not of correct type for format spec). So this issue is resolved on .NET and iOS/Swift. Just leaving the issue open until Java implementation is implemented without issue.