```"An 8-bit byte. A `Byte` value represents a congruence class
of [[integers|Integer]] modulo 256, and may be interpreted
as:

- an [[unsigned]] integer value in the range `0..255`, or
- a [[signed]] integer value in the range `-128..127`.

`Byte` is not considered a full numeric type, supporting
only:

- [[bitwise|Binary]] operations, and
- addition and subtraction modulo 256.

`Byte`s with modular addition form a [[mathematical
group|Invertible]]. Thus, every byte `b` has an additive
inverse `-b` where:

(-b).signed == -b.signed
(-b).unsigned == b.unsigned==0 then 0 else 256 - b.unsigned

`Byte` is a [[recursive enumerable type|Enumerable]]. For
example, the range:

254.byte .. 1.byte

contains the values `254.byte, 255.byte, 0.byte, 1.byte`.

`Byte` does not have a [[total order|Comparable]] because
any such order would:

- be inconsistent with the definition of [[successor]] and
- would depend on interpretation of the `Byte` value as
signed or unsigned.

Thus, to compare the magnitude of two bytes, it is
necessary to first convert them to either their `signed` or
`unsigned` integer values.

`Byte`s are useful mainly because they can be efficiently
stored in an [[Array]]."
tagged("Basic types")
since("1.1.0")
shared native final class Byte(congruent)
extends Object()
satisfies Binary<Byte> &
Invertible<Byte> &
Enumerable<Byte> {

"An integer member of the congruence class of the
resulting `Byte`.

For any integer `x>=0`:

x.byte.unsigned == x % 256
x.byte.signed == x % 256

And for an integer `x<0`:

x.byte.unsigned == 256 + x % 256
x.byte.signed == x % 256

And for any integers `x` and `y` which are congruent
modulo 256:

x.byte == y.byte"
Integer congruent;

"This byte interpreted as an unsigned integer in the
range `0..255` (that is, `0..#FF`)."
shared native Integer unsigned
= (congruent % #100).and(#FF);

"This byte interpreted as a signed integer in the range
`-128..127` (that is, `-#80..#7F`)."
shared native Integer signed
=> unsigned > #7F
then unsigned - #100
else unsigned;

//shared Boolean bits;

"Whether this byte is even."
shared native Boolean even => and(1.byte).zero;

"Whether this byte is zero."
shared native Boolean zero => unsigned == 0;

"Whether this byte is one."
shared native Boolean unit => unsigned == 1;

"The additive inverse of this byte. For any integer `x`:

(-x.byte).signed = -x.byte.signed"
shared actual native Byte negated => (-signed).byte;

"The modulo 256 sum of this byte and the given byte."
shared actual native Byte plus(Byte other)
=> (this.unsigned + other.unsigned).byte;

function indexInRange(Integer index)
=> 0 <= index < 8;

=> 1.byte.leftLogicalShift(index);

shared actual native Boolean get(Integer index)
=> indexInRange(index)
else false;

shared actual native Byte flip(Integer index)
=> indexInRange(index)
else this;

shared actual native Byte set(Integer index, Boolean bit)
=> indexInRange(index)
else this;

shared actual native Byte clear(Integer index)
=> indexInRange(index)
else this;

shared actual native Byte not => unsigned.not.byte;

shared actual native Byte and(Byte other)
=> unsigned.and(other.unsigned).byte;

shared actual native Byte or(Byte other)
=> unsigned.or(other.unsigned).byte;

shared actual native Byte xor(Byte other)
=> unsigned.xor(other.unsigned).byte;

"If [[shift]] is in the range `0..\$111`, shift the bits
to the left by `shift` positions, using zero extension
to fill in the least significant bits. Otherwise shift
the addressable bits to the left by `shift.and(\$111)`
positions, using zero extension."
aliased ("leftShift")
shared actual native Byte leftLogicalShift(Integer shift)
=> unsigned.leftLogicalShift(shift.and(\$111)).byte;

"If [[shift]] is in the range `0..\$111`, shift the bits
to the right by `shift` positions, using zero extension
to fill in the most significant bits. Otherwise shift
the addressable bits to the right by `shift.and(\$111)`
positions, using zero extension."
aliased ("rightShift")
shared actual native Byte rightLogicalShift(Integer shift)
=> unsigned.rightLogicalShift(shift.and(\$111)).byte;

"If [[shift]] is in the range `0..\$111`, shift the bits
to the right by `shift` positions, using sign extension
to fill in the most significant bits. Otherwise shift
the addressable bits to the right by `shift.and(\$111)`
positions, using sign extension."
shared actual native Byte rightArithmeticShift(Integer shift)
=> signed.rightArithmeticShift(shift.and(\$111)).byte;

shared actual native Byte predecessor => (unsigned-1).byte;
shared actual native Byte successor => (unsigned+1).byte;

shared actual native Byte neighbour(Integer offset)
=> (unsigned + offset).byte;

shared actual native Integer offset(Byte other)
=> minus(other).unsigned;

shared actual native Integer offsetSign(Byte other)
=> this==other then 0 else 1;

shared actual native Boolean equals(Object that)
=> if (is Byte that)
then this.unsigned == that.unsigned
else false;

shared actual native Integer hash => signed;

"The [[unsigned]] interpretation of this byte as a
string."
shared actual native String string => unsigned.string;

}
```