2

In Rebol 2, it is possible to use to char! to produce what is effectively a single byte, that you can use in operations on binaries such as append:

>> buffer: #{DECAFBAD}
>> data: #{FFAE}
>> append buffer (to char! (first data))
== #{DECAFBADFF}

Seems sensible. But in Rebol 3, you get something different:

>> append buffer (to char! (first data))
== #{DECAFBADC3BF}

That's because it doesn't model single characters as single bytes (due to Unicode). So the integer value of first data (255) is translated into a two-byte sequence:

>> to char! 255
== #"ÿ"
>> to binary! (to char! 255)
== #{C3BF}

Given that CHAR! is no longer equivalent to a byte in Rebol 3, and no BYTE! datatype was added (such that a BINARY! could be considered a series of these BYTE!s just as a STRING! is a series of CHAR!), what is one to do about this kind of situation?

3 Answers3

2

Use an integer!, the closest match we have for expressing a byte in R3, at the moment.

Note that integers are range-checked when used as bytes in context of a binary!:

>> append #{} 1024
** Script error: value out of range: 1024
** Where: append
** Near: append #{} 1024

For your first example, you actually append one element of one series to another series of the same type. In R3 you can express this in the obvious and most straight-forward way:

>> append #{DECAFBAD} first #{FFAE}
== #{DECAFBADFF}

So for that matter, a binary! is a series of range-constrained integer!s.

Unfortunately, that won't work in R2, because its binary! model was just broken in many tiny ways, including the above. While conceptually a binary! in R2 can be considered a series of char!s, that concept is not consistently implemented.

earl
  • 40,327
  • 6
  • 58
  • 59
  • Due to trying to do something that is likely to be very rare (making a codebase run on either R2 or R3) I don't always notice the "simple" answers. Seeing that this works, I guess the range-checking isn't so bad, I'll have to consider it further... – HostileFork says dont trust SE Jan 18 '13 at 19:19
1
>> buffer: #{DECAFBAD}
== #{DECAFBAD}

>> data: #{FFAE}
== #{FFAE}

>> append buffer data/1
== #{DECAFBADFF}
Graham Chiu
  • 4,856
  • 1
  • 23
  • 41
  • Yup, as @earl pointed out, this works in R3. But not R2, where you get the enigmatic `#{DECAFBAD323535}` :-) Sounds like consensus is that binary! was kind of borked in R2...and only worked with the not-very-forward-looking-idea of turning things into CHAR!, which should be not done henceforth. My answer has the *"if you need your code to run in R2 and R3, do this"* solution... – HostileFork says dont trust SE Jan 19 '13 at 02:07
0

The easiest workaround for the issue in both Rebol 2 and Rebol 3 is to use COPY/PART. This way, rather than trying to reduce your content to a byte value, you keep it as a binary series type. You're merely appending a binary sequence of length 1:

>> append buffer (copy/part data 1)
== #{DECAFBADFF}

It does seem that for completeness, Rebol 3 would have a BYTE! type, as calling it a "series of INTEGER!" clearly does not match the precedent set by STRING!

It's open source, so you (um, I?) might try adding it and seeing what the full ramifications are. :-)