// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// The identity constructor for `Byte`, allowing values to be written using
/// constructor syntax, e.g. `Byte(3)`.
///
/// Example:
///
/// ```mbt check
/// test {
/// inspect(Byte(3), content="b'\\x03'")
/// }
/// ```
pub fn Byte::Byte(self : Byte) -> Byte = "%identity"
///|
/// Performs multiplication between two byte values. The result is truncated to
/// fit within the byte range.
///
/// Parameters:
///
/// * `self` : The first byte operand in the multiplication.
/// * `that` : The second byte operand in the multiplication.
///
/// Returns the product of the two bytes, truncated to fit within the byte range
/// (0-255).
///
/// Example:
///
/// ```mbt check
/// test {
/// let a = b'\x02'
/// let b = b'\x03'
/// inspect(a * b, content="b'\\x06'") // 2 * 3 = 6
/// let c = b'\xFF'
/// inspect(c * c, content="b'\\x01'") // 255 * 255 = 65025, truncated to 1
/// }
/// ```
pub impl Mul for Byte with fn mul(self : Byte, that : Byte) -> Byte {
(self.to_int() * that.to_int()).to_byte()
}
///|
/// Performs division operation between two bytes by converting them to integers,
/// performing the division, and converting the result back to a byte.
///
/// Parameters:
///
/// * `self` : The dividend byte value.
/// * `that` : The divisor byte value.
///
/// Returns the quotient of the division as a byte.
///
/// Example:
///
/// ```mbt check
/// test {
/// let a = b'\xFF' // 255
/// let b = b'\x03' // 3
/// inspect(a / b, content="b'\\x55'") // 255 / 3 = 85 (0x55)
/// }
/// ```
pub impl Div for Byte with fn div(self : Byte, that : Byte) -> Byte {
(self.to_int() / that.to_int()).to_byte()
}
///|
pub impl Mod for Byte with fn mod(self : Byte, that : Byte) -> Byte {
(self.to_int() % that.to_int()).to_byte()
}
///|
/// Compares two `Byte` values for equality.
///
/// Parameters:
///
/// - `self` : The first `Byte` value to compare.
/// - `that` : The second `Byte` value to compare.
///
/// Returns `true` if the two `Byte` values are equal, otherwise `false`.
pub impl Eq for Byte with fn equal(self : Byte, that : Byte) -> Bool {
self.to_int() == that.to_int()
}
///|
/// Compares two `Byte` values for inequality.
///
/// Parameters:
///
/// - `self` : The first `Byte` value to compare.
/// - `that` : The second `Byte` value to compare.
///
/// Returns `true` if the two `Byte` values are not equal, otherwise `false`.
pub impl Eq for Byte with fn not_equal(self : Byte, that : Byte) -> Bool {
self.to_int() != that.to_int()
}
///|
/// Adds two `Byte` values together and returns the result as a `Byte`.
///
/// Parameters:
///
/// - `byte1` : The first `Byte` value to be added.
/// - `byte2` : The second `Byte` value to be added.
///
/// Returns the sum of `byte1` and `byte2` as a `Byte`.
pub impl Add for Byte with fn add(self : Byte, that : Byte) -> Byte {
(self.to_int() + that.to_int()).to_byte()
}
///|
/// Subtracts the second byte from the first byte and returns the result as a
/// byte.
///
/// Parameters:
///
/// - `self` : The byte from which the second byte will be subtracted.
/// - `that` : The byte to subtract from the first byte.
///
/// Returns the result of the subtraction as a byte.
pub impl Sub for Byte with fn sub(self : Byte, that : Byte) -> Byte {
(self.to_int() - that.to_int()).to_byte()
}
///|
/// Compares two `Byte` values and returns an integer indicating their relative
/// order.
///
/// Parameters:
///
/// - `byte1` : The first `Byte` value to compare.
/// - `byte2` : The second `Byte` value to compare.
///
/// Returns an integer where:
/// - A value less than 0 indicates that `byte1` is less than `byte2`.
/// - A value of 0 indicates that `byte1` is equal to `byte2`.
/// - A value greater than 0 indicates that `byte1` is greater than `byte2`.
pub impl Compare for Byte with fn compare(self : Byte, that : Byte) -> Int {
self.to_int().compare(that.to_int())
}
///|
pub impl Compare for Byte with fn op_lt(x, y) {
x.to_int() < y.to_int()
}
///|
pub impl Compare for Byte with fn op_le(x, y) {
x.to_int() <= y.to_int()
}
///|
pub impl Compare for Byte with fn op_gt(x, y) {
x.to_int() > y.to_int()
}
///|
pub impl Compare for Byte with fn op_ge(x, y) {
x.to_int() >= y.to_int()
}
///|
fn alphabet(x : Int) -> String {
match x {
0 => "0"
1 => "1"
2 => "2"
3 => "3"
4 => "4"
5 => "5"
6 => "6"
7 => "7"
8 => "8"
9 => "9"
10 => "A"
11 => "B"
12 => "C"
13 => "D"
14 => "E"
15 => "F"
_ => abort("impossible")
}
}
///|
/// Converts a `Byte` to its string representation in hexadecimal format.
///
/// Parameters:
///
/// - `byte` : The `Byte` value to be converted.
///
/// Returns a `String` representing the `Byte` in the format `b'\xHH'`, where
/// `HH` is the hexadecimal representation of the byte.
pub fn Byte::to_string(self : Byte) -> String {
let i = self.to_int()
let hi = alphabet(i / 16)
let lo = alphabet(i % 16)
"b'\\x\{hi}\{lo}'"
}
///|
/// Implements the `Hash` trait for `Byte` type by providing a `hash_combine`
/// method that combines a byte value with a hasher.
///
/// Parameters:
///
/// * `self` : The byte value to be hashed.
/// * `hasher` : The hasher object that will be used to combine the byte value
/// into its internal state.
///
/// Example:
///
/// ```mbt check
/// test {
/// let hasher = Hasher(seed=0)
/// hasher.combine_byte(b'\xFF')
/// inspect(hasher.finalize(), content="1955036104")
/// }
/// ```
pub impl Hash for Byte with fn hash_combine(self, hasher) {
hasher.combine_byte(self)
}
///|
/// Returns the default value for a `Byte`, which is `b'\x00'`.
///
/// Parameters:
///
/// - None
///
/// Returns the default `Byte` value, which is `b'\x00'`.
pub impl Default for Byte with fn default() {
b'\x00'
}
///|
/// Performs a bitwise NOT operation on the given `Byte` value.
///
/// Parameters:
///
/// - `value` : The `Byte` value to apply the bitwise NOT operation on.
///
/// Returns the result of the bitwise NOT operation as a `Byte`.
pub fn Byte::lnot(self : Byte) -> Byte {
self.to_int().lnot().to_byte()
}
///|
/// Performs a bitwise AND operation between two `Byte` values.
///
/// Parameters:
///
/// - `byte1` : The first `Byte` value to perform the bitwise AND operation with.
/// - `byte2` : The second `Byte` value to perform the bitwise AND operation
/// with.
///
/// Returns the result of the bitwise AND operation as a `Byte`.
pub impl BitAnd for Byte with fn land(self : Byte, that : Byte) -> Byte {
(self.to_int() & that.to_int()).to_byte()
}
///|
/// Performs a bitwise OR operation between two `Byte` values.
///
/// Parameters:
///
/// - `self` : The first `Byte` value.
/// - `that` : The second `Byte` value.
///
/// Returns a new `Byte` value resulting from the bitwise OR operation.
pub impl BitOr for Byte with fn lor(self : Byte, that : Byte) -> Byte {
(self.to_int() | that.to_int()).to_byte()
}
///|
/// Performs a bitwise XOR operation between two `Byte` values.
///
/// Parameters:
///
/// - `self` : The first `Byte` value.
/// - `that` : The second `Byte` value.
///
/// Returns the result of the bitwise XOR operation as a `Byte`.
pub impl BitXOr for Byte with fn lxor(self : Byte, that : Byte) -> Byte {
(self.to_int() ^ that.to_int()).to_byte()
}
///|
/// Converts a `Byte` to a `UInt`.
///
/// Parameters:
///
/// - `byte` : The `Byte` value to be converted.
///
/// Returns the `UInt` representation of the `Byte`.
pub fn Byte::to_uint(self : Byte) -> UInt {
self.to_int().reinterpret_as_uint()
}
///|
/// Converts a byte value to an unsigned 64-bit integer.
///
/// Parameters:
///
/// * `byte` : The byte value to be converted.
///
/// Returns an unsigned 64-bit integer representation of the byte value.
///
/// Example:
///
/// ```mbt check
/// test {
/// let b = b'\xFF'
/// inspect(b.to_uint64(), content="255")
/// }
/// ```
pub fn Byte::to_uint64(self : Byte) -> UInt64 {
self.to_uint().to_uint64()
}
///|
/// Counts the number of 1-bits (population count) in the byte using bitwise operations.
///
/// Parameters:
///
/// * `self` : The byte value whose 1-bits are to be counted.
///
/// Returns the number of 1-bits in the byte.
///
/// Example:
///
/// ```mbt check
/// test {
/// let b = b'\x0F'
/// inspect(b.popcnt(), content="4")
/// }
/// ```
pub fn Byte::popcnt(self : Byte) -> Int {
let mut n = self
n = (n & 0x55) + ((n >> 1) & 0x55)
n = (n & 0x33) + ((n >> 2) & 0x33)
n = (n & 0x0F) + ((n >> 4) & 0x0F)
n.to_int()
}
///|
/// Shifts the bits of the `Byte` value to the left by the specified number of
/// positions.
///
/// Parameters:
///
/// - `byte_value` : The `Byte` value whose bits are to be shifted.
/// - `shift_count` : The number of bit positions to shift the `byte_value` to
/// the left.
///
/// Returns the resulting `Byte` value after the shift operation.
pub impl Shl for Byte with fn shl(self : Byte, count : Int) -> Byte {
(self.to_int() << count).to_byte()
}
///|
/// Shifts the bits of the `Byte` value to the right by the specified number of
/// positions.
///
/// Parameters:
///
/// - `byte` : The `Byte` value whose bits are to be shifted.
/// - `count` : The number of bit positions to shift the `byte` value to the
/// right.
///
/// Returns the resulting `Byte` value after the bitwise right shift operation.
pub impl Shr for Byte with fn shr(self : Byte, count : Int) -> Byte {
(self.to_uint() >> count).reinterpret_as_int().to_byte()
}