///| Character constants and utility functions
/// Ported from js-yaml v3.13.1:
/// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
/// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
/// Copyright 2018-2025 the Deno authors. MIT license.
///|
/// Character code constants
pub const BOM = 0xfeff // BOM
///|
pub const TAB = 0x09 // Tab
///|
pub const LINE_FEED = 0x0a // LF
///|
pub const CARRIAGE_RETURN = 0x0d // CR
///|
pub const SPACE = 0x20 // Space
///|
pub const EXCLAMATION = 0x21 // !
///|
pub const DOUBLE_QUOTE = 0x22 // "
///|
pub const SHARP = 0x23 // #
///|
pub const PERCENT = 0x25 // %
///|
pub const AMPERSAND = 0x26 // &
///|
pub const SINGLE_QUOTE = 0x27 // '
///|
pub const ASTERISK = 0x2a // *
///|
pub const PLUS = 0x2b // +
///|
pub const COMMA = 0x2c // ,
///|
pub const MINUS = 0x2d // -
///|
pub const DOT = 0x2e // .
///|
pub const COLON = 0x3a // :
///|
pub const SMALLER_THAN = 0x3c // <
///|
pub const GREATER_THAN = 0x3e // >
///|
pub const QUESTION = 0x3f // ?
///|
pub const COMMERCIAL_AT = 0x40 // @
///|
pub const LEFT_SQUARE_BRACKET = 0x5b // [
///|
pub const BACKSLASH = 0x5c // \
///|
pub const RIGHT_SQUARE_BRACKET = 0x5d // ]
///|
pub const GRAVE_ACCENT = 0x60 // `
///|
pub const LEFT_CURLY_BRACKET = 0x7b // {
///|
pub const VERTICAL_LINE = 0x7c // |
///|
pub const RIGHT_CURLY_BRACKET = 0x7d // }
///|
/// Check if character is end-of-line (internal)
fn is_eol_internal(c : Int) -> Bool {
c == LINE_FEED || c == CARRIAGE_RETURN
}
///|
/// Check if character is end-of-line
pub fn is_eol(c : Int) -> Bool {
is_eol_internal(c)
}
///|
/// Check if character is whitespace (internal)
fn is_whitespace_internal(c : Int) -> Bool {
c == TAB || c == SPACE
}
///|
/// Check if character is whitespace or end-of-line
pub fn is_whitespace_or_eol(c : Int) -> Bool {
is_whitespace_internal(c) || is_eol_internal(c)
}
///|
/// Check if character is a flow indicator
pub fn is_flow_indicator(c : Int) -> Bool {
c == COMMA ||
c == LEFT_SQUARE_BRACKET ||
c == RIGHT_SQUARE_BRACKET ||
c == LEFT_CURLY_BRACKET ||
c == RIGHT_CURLY_BRACKET
}
///|
/// Check if character is printable
pub fn is_printable(c : Int) -> Bool {
(0x20 <= c && c <= 0x7E) ||
0x85 == // ASCII printable
c ||
(
0xA0 <= // NEL
c &&
c <= 0xD7FF
) || // Unicode printable range 1
(0xE000 <= c && c <= 0xFFFD) || // Unicode printable range 2
(0x10000 <= c && c <= 0x10FFFF) // Unicode printable range 3
}
///|
/// Check if character is a valid hexadecimal digit
pub fn is_hex_digit(c : Int) -> Bool {
(0x30 <= c && c <= 0x39) || // 0-9
(0x41 <= c && c <= 0x46) || // A-F
(0x61 <= c && c <= 0x66) // a-f
}
///|
/// Check if character is a valid decimal digit
pub fn is_decimal_digit(c : Int) -> Bool {
0x30 <= c && c <= 0x39 // 0-9
}
///|
/// Convert hex character to number
pub fn hex_char_to_number(c : Int) -> Int {
if 0x30 <= c && c <= 0x39 {
c - 0x30 // 0-9
} else if 0x41 <= c && c <= 0x46 {
c - 0x41 + 10 // A-F
} else if 0x61 <= c && c <= 0x66 {
c - 0x61 + 10 // a-f
} else {
-1 // Invalid hex digit
}
}
///|
/// Convert decimal character to number
pub fn decimal_char_to_number(c : Int) -> Int {
if 0x30 <= c && c <= 0x39 {
c - 0x30 // 0-9
} else {
-1 // Invalid decimal digit
}
}
///|
/// Convert Unicode code point to string
pub fn codepoint_to_string(codepoint : Int) -> String {
if codepoint <= 0xFFFF {
// Basic Multilingual Plane
codepoint.unsafe_to_char().to_string()
} else {
// Surrogate pairs for code points beyond BMP
let high = (codepoint - 0x010000) / 1024 + 0xD800
let low = (codepoint - 0x010000) % 1024 + 0xDC00
high.unsafe_to_char().to_string() + low.unsafe_to_char().to_string()
}
}