bitfocus / companion

Bitfocus Companion enables the reasonably priced Elgato Streamdeck and other controllers to be a professional shotbox surface for an increasing amount of different presentation switchers, video playback software and broadcast equipment.
http://bitfocus.io/companion
Other
1.46k stars 489 forks source link

feat: add `encode` and `decode` expression functions #2842

Closed istnv closed 2 months ago

istnv commented 2 months ago

Adds string encode/decode functions.

fromHex(val) Decodes a Hex encoded string. eg fromHex("436f6d70616e696f6e") gives "Companion"

toHex(val) Hex encodes a string. eg toHex("Companion") gives "436f6d70616e696f6e"

from64(val) Decodes a Base64 encoded string. eg from64("Q29tcGFuaW9uCg=="") gives "Companion"

to64(val) Encodes a string to Base64. eg to64("Companion") gives "Q29tcGFuaW9uCg=="

dnmeid commented 2 months ago

Any thoughts on the names of these functions? I think 'fromHex' and 'toHex' can easily be mixed up with a numerical conversion. For base64 there are the standard functions 'atob' (ascii to base64) and 'btoa' (base64 to ascii). Maybe we should use the same names for the same functionality and likewise 'htoa' and 'atoh', which are not part of ecma script but are used by several other libraries.

Julusian commented 2 months ago

@dnmeid you make good points there. I would prefer something more self descriptive than htoa and atoh. like hexToAscii, asciiToHex, base64Decode and base64Encode.

istnv commented 2 months ago

I think 'fromHex' and 'toHex' can easily be mixed up with a numerical conversion.

Number literals (0x10, 0b11) are already converted automatically. The documentation explicitly states 'string'.

I was looking for descriptive, yet brief, function names. The limited space in the GUI makes complex expressions extremely hard to work on.

This was a 'fun' to get working:

concat(`Soldering Iron`,$(internal:custom_si_off) < $(internal:time_unix)  ? '' :  concat(`\nAuto Off`,`
 @${secondsToTimestamp(max(0,$(internal:custom_si_off)-$(internal:time_unix)))}`) )

(A language I used in the '80s had built-in ATH and HTA functions for ascii-to-hex and hex-to-ascii.)

For base64 there are the standard functions 'atob' (ascii to base64) and 'btoa' (base64 to ascii).

These have been deprecated for a while.

dnmeid commented 2 months ago

@istnv don't get me wrong, I'm not talking about implementation, just about the names. I'd be fine too with hexToAscii, asciiToHex, base64Decode and base64Encode. I also would prefer if there was a good shorter variant, but a wise colleague of me once said: code is more often read than written, so readability is more important than writeability. The size of the text input originates from a time when we had no expressions and some crazy guys maybe used one variable. If it is not convenient anymore, that's a different issue.

istnv commented 2 months ago

I am also trying to keep the names similar since they are nearly identical functions. What about encodeHex, decodeHex, encodeBase64, decodeBase64? With appropriate documentation updates. Or to be more precise 'encodeBase16`? (joke) No one has asked for base64 (yet) but it was easy to add once I was working on the code.

There is definitely a need for a better input widget.

Since we now have a couple of reserved namespaces (internal, this) for variables, I'd like to see if $(internal:custom_var) could be reduced to $(custom:var)

istnv commented 2 months ago

Another idea. Basically expose Buffer.from(... and Buffer.to(...: decode(str,enc) and encode(str,enc) where enc is one of hex, base64, binary, or any other node character encoding.

decode(str, enc)

Decodes an string from the passed encoding ('hex','base64')

eg decode("436f6d70616e696f6e","hex") gives "Companion"

encode(str, enc)

Encodes a string to the passed encoding ('hex','base64')

eg encode("Companion","hex") gives "436f6d70616e696f6e"

istnv commented 2 months ago

Since 'hex' is used to pass binary data, I've set decode to return a latin1 formatted string. ascii strips any character above 0x7f and utf8 adds an escape sequence to them.

@Julusian If the enc parameter is missing, which is preferred:

dnmeid commented 2 months ago

If enc is missing or invalid, I suggest to go with the same default as js does: utf8 Returning an error message in the return value can lead to unwanted behavior, e.g. if the original text to be decoded is identical with the error message.

istnv commented 2 months ago

... the same default as js does: utf8

For binary messages, I have encountered 'utf8' and 'ascii' breaking values above 0x7f. This was problem for the generic-tcp-udp and generic-serial when node switched from a default of 'binary'/'latin1' to 'utf8'

A default of 'latin1' will cause less confusion since that will probably be the majority of uses.

If someone really wants 'utf8', they specify that as the encoding.

istnv commented 2 months ago

@Julusian This should be ready to merge.

istnv commented 2 months ago

@Julusian I don't have write access. I'm OK with that, but cannot merge the PR myself.