Repository: typst/typst
File: crates/typst/src/foundations/int.rs (Rust)

Code before:
            }
        } else {
            // Saturate at -1 (negative) or 0 (otherwise) on excessive arithmetic
            // right shift. Shifting those numbers any further does not change
            // them, so it is consistent.
            let shift = shift.min(i64::BITS - 1);
            self >> shift
        }
    }

    /// Converts bytes to an integer. The bytes will be treated as a 64-bit signed integer.
    /// The bytes should be at most 8 bytes (64 bits) in size to fit in a 64-bit integer, otherwise an error will occur.
    ///
    /// ```example
    /// #int.from-bytes(bytes((0, 0, 0, 0, 0, 0, 0, 1)), "little")
    /// ```
    #[func]
    pub fn from_bytes(
        /// The bytes that should be converted to an integer.
        bytes: Bytes,
        /// Endianness of the conversion.
        endianness: Endianness,
    ) -> StrResult<i64> {
        let len = bytes.len();
        if len > 8 {
            return Err("Bytes too large to convert to a 64 bit number".into());
        }

        let mut buf = [0u8; 8];

        match endianness {
            Endianness::Big => buf[8 - len..].copy_from_slice(bytes.as_ref()),
            Endianness::Little => buf[..len].copy_from_slice(bytes.as_ref()),
        }

        Ok(match endianness {
            Endianness::Big => i64::from_be_bytes(buf),
            Endianness::Little => i64::from_le_bytes(buf),
        })
    }

    /// Converts an integer to bytes.
    /// The integer is converted to a byte array of the specified size and endianness.
    ///
    /// ```example
    /// #array(10000.to-bytes("big"))
    /// #array(10000.to-bytes("little", 4))
    /// ```
    #[func]
    pub fn to_bytes(
        self,

Review comment (suggestion):
```suggestion
            bail!("too many bytes to convert to a 64 bit number");
```
(imported from `crate::diag`)

Code after:
                ((self as u64) >> shift) as i64
            }
        } else {
            // Saturate at -1 (negative) or 0 (otherwise) on excessive arithmetic
            // right shift. Shifting those numbers any further does not change
            // them, so it is consistent.
            let shift = shift.min(i64::BITS - 1);
            self >> shift
        }
    }

    /// Converts bytes to an integer.
    ///
    /// ```example
    /// #int.from-bytes(bytes((0, 0, 0, 0, 0, 0, 0, 1))) \
    /// #int.from-bytes(bytes((1, 0, 0, 0, 0, 0, 0, 0)), endian: "big")
    /// ```
    #[func]
    pub fn from_bytes(
        /// The bytes that should be converted to an integer.
        ///
        /// Must be of length at most 8 so that the result fits into a 64-bit
        /// signed integer.
        bytes: Bytes,
        /// The endianness of the conversion.
        #[named]
        #[default(Endianness::Little)]
        endian: Endianness,
        /// Whether the bytes should be treated as a signed integer. If this is
        /// `{true}` and the most significant bit is set, the resulting number
        /// will negative.
        #[named]
        #[default(true)]
        signed: bool,
    ) -> StrResult<i64> {
        let len = bytes.len();
        if len == 0 {
            return Ok(0);
        } else if len > 8 {
            bail!("too many bytes to convert to a 64 bit number");
        }

        // `decimal` will hold the part of the buffer that should be filled with
        // the input bytes, `rest` will remain as is or be filled with 0xFF for
        // negative numbers if signed is true.
        //
        // – big-endian: `decimal` will be the rightmost bytes of the buffer.
        // - little-endian: `decimal` will be the leftmost bytes of the buffer.
        let mut buf = [0u8; 8];
        let (rest, decimal) = match endian {
            Endianness::Big => buf.split_at_mut(8 - len),