-
-
Notifications
You must be signed in to change notification settings - Fork 143
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
Map string <-> ettBinary, []byte -> ettBitBinary #68
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -403,15 +403,15 @@ func Encode(term Term, b *lib.Buffer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenString := len(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if lenString > 65535 { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if lenString > math.MaxUint32 { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ErrStringTooLong | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 1 (ettString) + 2 (len) + string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(1 + 2 + lenString) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettString | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
binary.BigEndian.PutUint16(buf[1:3], uint16(lenString)) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy(buf[3:], t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 1 (ettBinary) + 4 (len) + string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(1 + 4 + lenString) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettBinary | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
binary.BigEndian.PutUint32(buf[1:5], uint32(lenString)) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy(buf[5:], t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case Atom: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if cacheEnabled && cacheIndex < 256 { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -514,6 +514,38 @@ func Encode(term Term, b *lib.Buffer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stringAsCharlist: stringAsCharlist, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case String: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Spec: optimization for sending lists of bytes | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// See: https://erlang.org/doc/apps/erts/erl_ext_dist.html#string_ext | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenString := len(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
charlist := []rune(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenCharlist := len(charlist) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// each character takes up only one byte in extended ASCII charset (i.e. Latin1) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if lenString != lenCharlist { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Spec: when unicode detected, must send list of unicode/rune, as list of UTF8 bytes is a "StrangeList" in Erlang | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// See: https://erlang.org/doc/apps/stdlib/unicode_usage.html#lists-of-utf-8-bytes | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Usage: erl +pc unicode -name erl-demo@localhost -setcookie 123 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
term = charlist | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
goto recasting | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if lenString > 65535 { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Spec: implementations must ensure that lists longer than 65535 elements are encoded as LIST_EXT. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// See: https://erlang.org/doc/apps/erts/erl_ext_dist.html#string_ext | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
l := make(List, lenString) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for i := 0; i < lenString; i++ { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// each element = one char | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
l[i] = t[i] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
term = l | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
goto recasting | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 1 (ettString) + 2 (len) + string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(1 + 2 + lenString) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettString | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
binary.BigEndian.PutUint16(buf[1:3], uint16(lenString)) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy(buf[3:], t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case List: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenList := len(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(5) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -527,12 +559,30 @@ func Encode(term Term, b *lib.Buffer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stringAsCharlist: stringAsCharlist, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case []rune: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenList := len(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(5) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettList | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
binary.BigEndian.PutUint32(buf[1:], uint32(lenList)) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
l := make(List, lenList) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for i := 0; i < lenList; i++ { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
l[i] = t[i] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
child = &stackElement{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parent: stack, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
termType: ettList, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
term: l, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
children: lenList + 1, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stringAsCharlist: stringAsCharlist, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case []byte: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lenBinary := len(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(1 + 4 + lenBinary) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettBinary | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf := b.Extend(1 + 4 + 1 + lenBinary) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[0] = ettBitBinary | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see your idea to use ettBinary as a transport for the string and ettBitBinary for the real binary data but it makes Ergo-Ergo interaction a bit harder for the case of string usage or for the case if I sent real binary (not a string) from the Erlang side. That's why I prefer to see
and here are prioritized transitions for me so far as it doesn't require any extra conversions.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This commit was based on your previous input that this library's priority is Ergo <-> Ergo. If we start considering the case for Erlang, we should also consider the case for Elixir. Elixir strings are binaries. Do also note that the current ergo implementation can only send ASCII strings to Erlang and there are no safety checks to ensure that the user passes only ASCII goStrings. Rather than have golang side waste CPU cycles to check if a string contains utf8 or not, it's why
Note single quotes in Elixir produce charlists (and only support ascii characters), unlike double quotes .
List of positive integers (charlist) are also displayed as string with quotes in Erlang shell: https://erlang.org/doc/apps/stdlib/unicode_usage.html#heuristic-string-detection There is no impact on Ergo <-> Ergo integration.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure about Elixir <<...>>> -> ettBitBinary. May I ask you to show the same output
but in Elixir shell? (I'm not familiar with it) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just found
as you may notice it was encoded as ettBinary (109) which means there is no way to get []byte on the Ergo side using your approach. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elixir: Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> <<195,165,195,164,195,182>>
"åäö"
iex(2)> :erlang.term_to_binary("åäö")
<<131, 109, 0, 0, 0, 6, 195, 165, 195, 164, 195, 182>>
iex(3)> :erlang.term_to_binary("123")
<<131, 109, 0, 0, 0, 3, 49, 50, 51>>
iex(4)> :erlang.term_to_binary("日本")
<<131, 109, 0, 0, 0, 6, 230, 151, 165, 230, 156, 172>> Erlang: Eshell V10.7.2.12 (abort with ^G)
1> <<195,165,195,164,195,182>>.
<<"åäö"/utf8>>
2> term_to_binary(<<"åäö"/utf8>>).
<<131,109,0,0,0,6,195,165,195,164,195,182>>
3> term_to_binary("åäö").
<<131,107,0,3,229,228,246>>
4> term_to_binary("123").
<<131,107,0,3,49,50,51>>
5> term_to_binary("日本").
<<131,108,0,0,0,2,98,0,0,101,229,98,0,0,103,44,106>> I do understand your point, but it's not a coincidence that we can Use Strings as Byte Slices in golang: https://go101.org/article/string.html#use-string-as-byte-slice Since So i think the question would be, should decoded binary values be immutable or mutable? This topic is still a big contention even within the Golang Issue Tracker:
Which is why I would approach it from language design: what is a string in Elixir, what is a string in Erlang, and what is a String in Golang? And i find that the common denominator is that strings are just an immutable sequence of bytes in all three languages. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In other words, 107 is just an optimisation on 108 (or 109). Try searching for "StrangeList" in the Erlang docs. (Those are caused by 107). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another Interesting Side Note: All of Erlang standard lib and modern 3rd-party Erlang libraries, can always accept (and behave the same on) either 108 (CharList) or 109 (Binary), but not always 107 (StrangeList). We have tested this pretty extensively. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we just make this configurable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I appreciate your effort to make this project better, but seemingly this approach differs from the way this project goes. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
binary.BigEndian.PutUint32(buf[1:5], uint32(lenBinary)) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy(buf[5:], t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf[5] = 8 // 1 byte = 8 bits | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy(buf[6:], t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
default: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
v := reflect.ValueOf(t) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Benchmark data first before coming to a conclusion?