@f12o/papyr-moonbit-bridge 2026.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/fu2hito/.moon/lib/core/double/limits.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_double.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_decimal.mbt","/Users/fu2hito/.moon/lib/core/json/lex_number.mbt","/Users/fu2hito/.moon/lib/core/builtin/hasher.mbt","/Users/fu2hito/.moon/lib/core/abort/abort.mbt","/Users/fu2hito/.moon/lib/core/builtin/json.mbt","/Users/fu2hito/.moon/lib/core/builtin/traits.mbt","/Users/fu2hito/.moon/lib/core/builtin/stringbuilder_concat.mbt","/Users/fu2hito/.moon/lib/core/builtin/uint16_char.mbt","/Users/fu2hito/.moon/lib/core/builtin/string.mbt","/Users/fu2hito/.moon/lib/core/builtin/deprecated.mbt","/Users/fu2hito/.moon/lib/core/builtin/byte.mbt","/Users/fu2hito/.moon/lib/core/builtin/show.mbt","/Users/fu2hito/.moon/lib/core/builtin/stringview.mbt","/Users/fu2hito/.moon/lib/core/builtin/intrinsics.mbt","/Users/fu2hito/.moon/lib/core/builtin/iterator.mbt","/Users/fu2hito/.moon/lib/core/builtin/to_string.mbt","/Users/fu2hito/.moon/lib/core/builtin/stringbuilder.mbt","/Users/fu2hito/.moon/lib/core/builtin/string_methods.mbt","/Users/fu2hito/.moon/lib/core/builtin/arraycore_js.mbt","/Users/fu2hito/.moon/lib/core/builtin/char.mbt","/Users/fu2hito/.moon/lib/core/builtin/readonlyarray.mbt","/Users/fu2hito/.moon/lib/core/builtin/option.mbt","/Users/fu2hito/.moon/lib/core/builtin/linked_hash_map.mbt","/Users/fu2hito/.moon/lib/core/builtin/int.mbt","/Users/fu2hito/.moon/lib/core/builtin/array.mbt","/Users/fu2hito/.moon/lib/core/builtin/double_to_int.mbt","/Users/fu2hito/.moon/lib/core/builtin/double.mbt","/Users/fu2hito/.moon/lib/core/error/error.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_errors.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_string_view.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_number.mbt","/Users/fu2hito/.moon/lib/core/internal/strconv/strconv_int.mbt","/Users/fu2hito/.moon/lib/core/json/utils.mbt","/Users/fu2hito/.moon/lib/core/json/types.mbt","/Users/fu2hito/.moon/lib/core/json/from_json.mbt","/Users/fu2hito/.moon/lib/core/json/json_path.mbt","/Users/fu2hito/.moon/lib/core/json/lex_misc.mbt","/Users/fu2hito/.moon/lib/core/json/internal_types.mbt","/Users/fu2hito/.moon/lib/core/json/lex_string.mbt","/Users/fu2hito/.moon/lib/core/json/lex_main.mbt","/Users/fu2hito/.moon/lib/core/json/parse.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/schema.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/pdf_layout.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/diagnostics.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/document_stack_tools.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/document_middleware.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/document_helpers.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/core/app_server_tools.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/markdown/serialize.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/markdown/document.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/formatter/formatter.mbt","/Users/fu2hito/src/moonrepo/target-repos/papyr.mbt.git/.wt/codex/document-framework-viewer/src/bridge/bridge.mbt"],"sourcesContent":["// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Numeric constant `not_a_number`.\npub let not_a_number : Double = 0x7FF8000000000001L.reinterpret_as_double()\n\n///|\n/// Numeric constant `infinity`.\npub let infinity : Double = 0x7FF0000000000000L.reinterpret_as_double()\n\n///|\n/// Numeric constant `neg_infinity`.\npub let neg_infinity : Double = 0xFFF0000000000000L.reinterpret_as_double()\n\n///|\n/// Max value constant for this type.\npub let max_value : Double = 0x7FEFFFFFFFFFFFFFL.reinterpret_as_double()\n\n///|\n/// Min value constant for this type.\npub let min_value : Double = 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double()\n\n///|\n/// Numeric constant `min_positive`.\npub let min_positive : Double = 0x0010000000000000L.reinterpret_as_double()\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\npriv struct FloatInfo {\n mantissa_bits : Int\n exponent_bits : Int\n bias : Int\n}\n\n///|\nlet double_info : FloatInfo = {\n mantissa_bits: 52,\n exponent_bits: 11,\n bias: -1023,\n}\n\n///|\n/// TODO: For `f32` it is 23, but we don't have `f32` yet.\nlet mantissa_explicit_bits = 52\n\n///|\n/// TODO: For `f32` it is -10, but we don't have `f32` yet.\nlet min_exponent_fast_path : Int64 = -22L\n\n///|\n/// TODO: For `f32` it is 10, but we don't have `f32` yet.\nlet max_exponent_fast_path : Int64 = 22L\n\n///|\n/// TODO: For `f32` it is 17, but we don't have `f32` yet.\nlet max_exponent_disguised_fast_path : Int64 = 37L\n\n///|\nlet max_mantissa_fast_path : UInt64 = 2UL << mantissa_explicit_bits\n\n///|\n/// Parse a string into a double precision floating point number. The string\n/// must contain at least one of:\n/// - An integer part (decimal digits)\n/// - A decimal point followed by a fractional part (decimal digits)\n/// - An exponent part ('e' or 'E' followed by an optional sign and decimal digits)\n///\n/// The string may optionally start with a sign ('+' or '-').\n/// For readability, underscores may appear between digits.\n///\n/// Examples:\n/// ```mbt check\n/// test {\n/// inspect(@strconv.parse_double(\"123\"), content=\"123\")\n/// inspect(@strconv.parse_double(\"12.34\"), content=\"12.34\")\n/// inspect(@strconv.parse_double(\".123\"), content=\"0.123\")\n/// inspect(@strconv.parse_double(\"1e5\"), content=\"100000\")\n/// inspect(@strconv.parse_double(\"1.2e-3\"), content=\"0.0012\")\n/// inspect(@strconv.parse_double(\"1_234.5\"), content=\"1234.5\")\n/// }\n/// ```\n///\n/// An exponent value exp scales the mantissa (significand) by 10^exp.\n/// For example, \"1.23e2\" represents 1.23 × 10² = 123.\npub fn parse_double(str : StringView) -> Double raise {\n guard str.length() > 0 else { syntax_err() }\n guard check_underscore(str) else { syntax_err() }\n // validate its a number\n match parse_number(str) {\n None => parse_inf_nan(str)\n Some(num) =>\n // Clinger's fast path (How to read floating point numbers accurately)[https://doi.org/10.1145/989393.989430]\n match num.try_fast_path() {\n Some(value) => value\n None => parse_decimal_priv(str).to_double_priv() // fallback to slow path\n }\n }\n}\n\n///|\nfn Number::is_fast_path(self : Number) -> Bool {\n min_exponent_fast_path <= self.exponent &&\n self.exponent <= max_exponent_disguised_fast_path &&\n self.mantissa <= max_mantissa_fast_path &&\n !self.many_digits\n}\n\n///|\nlet table : ReadOnlyArray[Double] = [\n 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0,\n 1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,\n 100000000000000.0, 1000000000000000.0, 10000000000000000.0, 100000000000000000.0,\n 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0, 1000000000000000000000.0,\n 10000000000000000000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n]\n\n///|\nfn pow10_fast_path(exponent : Int) -> Double {\n table[exponent & 31]\n}\n\n///|\nlet int_pow10 : ReadOnlyArray[UInt64] = [\n 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL,\n 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL,\n 100000000000000UL, 1000000000000000UL,\n]\n\n///|\nfn Number::try_fast_path(self : Number) -> Double? {\n if self.is_fast_path() {\n let mut value = if self.exponent <= max_exponent_fast_path {\n // normal fast path\n let value = Double::convert_uint64(self.mantissa)\n if self.exponent < 0L {\n value / pow10_fast_path(-self.exponent.to_int())\n } else {\n value * pow10_fast_path(self.exponent.to_int())\n }\n } else {\n // disguised fast path\n let shift = self.exponent - max_exponent_fast_path\n let mantissa = match\n checked_mul(self.mantissa, int_pow10[shift.to_int()]) {\n Some(m) => m\n None => return None\n }\n if mantissa > max_mantissa_fast_path {\n return None\n }\n Double::convert_uint64(mantissa) *\n pow10_fast_path(max_exponent_fast_path.to_int())\n }\n if self.negative {\n value = -value\n }\n Some(value)\n } else {\n None\n }\n}\n\n///|\ntest \"parse_double\" {\n let tests : Array[(String, Result[Double, String])] = [\n (\"\", Err(syntax_err_str)),\n (\"1x\", Err(syntax_err_str)),\n (\"1.1.\", Err(syntax_err_str)),\n (\"1e\", Err(syntax_err_str)),\n (\"1e-\", Err(syntax_err_str)),\n (\".e-1\", Err(syntax_err_str)),\n (\"1\", Ok(1.0)),\n (\"+1\", Ok(1.0)),\n (\"1e23\", Ok(1.0e23)),\n (\"1E23\", Ok(1.0e23)),\n (\"100000000000000000000000\", Ok(1.0e23)),\n (\"1e-100\", Ok(1.0e-100)),\n (\"123456700\", Ok(1.234567e+08)),\n (\"99999999999999974834176\", Ok(9.999999999999997e+22)),\n (\"100000000000000000000001\", Ok(1.0000000000000001e+23)),\n (\"100000000000000008388608\", Ok(1.0000000000000001e+23)),\n (\"100000000000000016777215\", Ok(1.0000000000000001e+23)),\n (\"100000000000000016777216\", Ok(1.0000000000000003e+23)),\n (\"-1\", Ok(-1.0)),\n (\"-0.1\", Ok(-0.1)),\n (\"-0\", Ok(-0.0)),\n (\"1e-20\", Ok(1.0e-20)),\n (\"625e-3\", Ok(0.625)),\n (\"6.62607015e-34\", Ok(6.62607015e-34)),\n (\"2.2250738585072012e-308\", Ok(2.2250738585072014e-308)),\n (\"2.2250738585072011e-308\", Ok(2.225073858507201e-308)),\n (\"0\", Ok(0.0)),\n (\"0e0\", Ok(0.0)),\n (\"-0e0\", Ok(-0.0)),\n (\"+0e0\", Ok(0.0)),\n (\"0e-0\", Ok(0.0)),\n (\"-0e-0\", Ok(-0.0)),\n (\"+0e-0\", Ok(0.0)),\n (\"0e+0\", Ok(0.0)),\n (\"-0e+0\", Ok(-0.0)),\n (\"+0e+0\", Ok(0.0)),\n (\"0e+01234567890123456789\", Ok(0.0)),\n (\"0.00e-01234567890123456789\", Ok(0.0)),\n (\"-0e+01234567890123456789\", Ok(-0.0)),\n (\"-0.00e-01234567890123456789\", Ok(-0.0)),\n (\"0e292\", Ok(0.0)),\n (\"0e347\", Ok(0.0)),\n (\"0e348\", Ok(0.0)),\n (\"-0e291\", Ok(-0.0)),\n (\"-0e292\", Ok(-0.0)),\n (\"-0e347\", Ok(-0.0)),\n (\"-0e348\", Ok(-0.0)),\n (\"1.7976931348623157e308\", Ok(1.7976931348623157e308)),\n (\"-1.7976931348623157e308\", Ok(-1.7976931348623157e308)),\n (\"1.7976931348623158e308\", Ok(1.7976931348623157e308)),\n (\"-1.7976931348623158e308\", Ok(-1.7976931348623157e308)),\n (\"1e308\", Ok(1.0e308)),\n (\n \"1.7976931348623159e308\",\n Err(\n // zeros\n // large double\n range_err_str,\n ),\n ),\n (\n \"-1.7976931348623159e308\",\n Err(\n // overflow\n range_err_str,\n ),\n ),\n (\"2e308\", Err(range_err_str)),\n (\"1e309\", Err(range_err_str)),\n (\"1e310\", Err(range_err_str)),\n (\"1e400\", Err(range_err_str)),\n (\"1e40000\", Err(range_err_str)),\n // denormalized\n (\"1e-305\", Ok(1.0e-305)),\n (\"1e-306\", Ok(1.0e-306)),\n (\"1e-307\", Ok(1.0e-307)),\n (\"1e-308\", Ok(1.0e-308)),\n (\"1e-309\", Ok(1.0e-309)),\n (\"1e-310\", Ok(1.0e-310)),\n (\"1e-322\", Ok(1.0e-322)),\n // smallest denormal\n (\"5e-324\", Ok(5.0e-324)),\n (\"4e-324\", Ok(5.0e-324)),\n (\"3e-324\", Ok(5.0e-324)),\n // underflow\n (\"2e-324\", Ok(0.0)),\n (\"1e-350\", Ok(0.0)),\n (\"1e-400000\", Ok(0.0)),\n // underscores\n (\"1_23.50_0_0e+1_2\", Ok(1.235e+14)),\n (\"-_123.5e+12\", Err(syntax_err_str)),\n (\"+_123.5e+12\", Err(syntax_err_str)),\n (\"_123.5e+12\", Err(syntax_err_str)),\n (\"1__23.5e+12\", Err(syntax_err_str)),\n (\"123_.5e+12\", Err(syntax_err_str)),\n (\"123._5e+12\", Err(syntax_err_str)),\n (\"123.5_e+12\", Err(syntax_err_str)),\n (\"123.5__0e+12\", Err(syntax_err_str)),\n (\"123.5e_+12\", Err(syntax_err_str)),\n (\"123.5e+_12\", Err(syntax_err_str)),\n (\"123.5e_-12\", Err(syntax_err_str)),\n (\"123.5e-_12\", Err(syntax_err_str)),\n (\"123.5e+1__2\", Err(syntax_err_str)),\n (\"123.5e+12_\", Err(syntax_err_str)),\n ]\n for t in tests {\n @test.assert_eq(\n Result::Ok(parse_double(t.0)) catch {\n Failure::Failure(err) => Err(err)\n err => Err(err.to_string())\n },\n t.1,\n )\n }\n}\n\n///|\ntest \"parse_double_inf\" {\n @test.assert_eq(parse_double(\"inf\"), @double.infinity)\n @test.assert_eq(parse_double(\"+Inf\"), @double.infinity)\n @test.assert_eq(parse_double(\"-Inf\"), @double.neg_infinity)\n @test.assert_eq(parse_double(\"+Infinity\"), @double.infinity)\n @test.assert_eq(parse_double(\"-Infinity\"), @double.neg_infinity)\n @test.assert_eq(parse_double(\"+INFINITY\"), @double.infinity)\n @test.assert_eq(parse_double(\"-INFINITY\"), @double.neg_infinity)\n}\n\n///|\ntest \"parse_double_nan\" {\n assert_true(parse_double(\"nan\").is_nan())\n assert_true(parse_double(\"NaN\").is_nan())\n assert_true(parse_double(\"NAN\").is_nan())\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Maximum shift that we can do in one pass without overflow.\n/// We have to be able to accommodate 9 << max_shift.\nlet max_shift = 59\n\n///|\npriv struct Decimal {\n digits : FixedArray[Byte]\n mut digits_num : Int\n mut decimal_point : Int\n mut negative : Bool\n mut truncated : Bool\n}\n\n///|\n/// Decimal power of ten to binary power of two.\n/// The Ith entry (starting at I = 0) is the largest power of 2 less than (10 ** I)\nlet powtab : ReadOnlyArray[Int] = [\n 1, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59,\n]\n\n///|\nfn Decimal::new_priv() -> Decimal {\n {\n digits: FixedArray::make(800, Byte::default()),\n digits_num: 0,\n decimal_point: 0,\n negative: false,\n truncated: false,\n }\n}\n\n///|\nfn Decimal::from_int64_priv(v : Int64) -> Decimal {\n let d = Decimal::new_priv()\n d.assign(v)\n d\n}\n\n///|\nfn parse_decimal_priv(str : StringView) -> Decimal raise {\n parse_decimal_from_view(str)\n}\n\n///|\nfn parse_decimal_from_view(str : StringView) -> Decimal raise {\n let d = Decimal::new_priv()\n let mut has_dp = false\n let mut has_digits = false\n // read sign\n let rest = match str {\n ['-', .. rest] => {\n d.negative = true\n rest\n }\n ['+', .. rest] => rest\n _ => str\n }\n // read digits\n let rest = for rest = rest {\n match rest {\n ['_', .. rest] => continue rest\n ['.', .. rest] => {\n guard !has_dp else { syntax_err() }\n has_dp = true\n d.decimal_point = d.digits_num\n continue rest\n }\n ['0'..='9' as digit, .. rest] => {\n has_digits = true\n if digit == '0' && d.digits_num == 0 {\n // ignore leading zeros\n d.decimal_point -= 1\n continue rest\n }\n if d.digits_num < d.digits.length() {\n d.digits[d.digits_num] = (digit.to_int() - '0').to_byte()\n d.digits_num += 1\n } else if digit != '0' {\n d.truncated = true\n }\n continue rest\n }\n rest => break rest\n }\n }\n guard has_digits else { syntax_err() }\n if !has_dp {\n d.decimal_point = d.digits_num\n }\n // read exponent part\n let rest = match rest {\n ['e' | 'E', .. rest] => {\n let mut exp_sign = 1\n let rest = match rest {\n ['+', .. rest] => rest\n ['-', .. rest] => {\n exp_sign = -1\n rest\n }\n rest => rest\n }\n guard rest is ['0'..='9', ..] else { syntax_err() }\n // Clamp the exponent accumulator so huge exponents cannot overflow `Int`.\n // The clamp lands `decimal_point` exactly at the boundary that\n // `to_double_priv` already treats as overflow / underflow:\n // - `decimal_point > 310` -> range_err (Double max ~1.8e+308, so\n // anything past 1e+310 is unreachable). Hence the `+311` ceiling.\n // - `decimal_point < -330` -> underflow to 0 (Double min subnormal\n // ~5e-324, so anything past 1e-331 underflows). Hence the `-331`\n // floor, expressed as `decimal_point + 331` for the negative-exp arm.\n // Once `exp` reaches `exp_limit`, additional digits cannot change the\n // result, so we stop accumulating before `Int` can wrap.\n let exp_limit = if exp_sign > 0 {\n if d.decimal_point < 311 {\n 311 - d.decimal_point\n } else {\n 0\n }\n } else if d.decimal_point > -331 {\n d.decimal_point + 331\n } else {\n 0\n }\n let mut exp = 0\n let rest = for rest = rest {\n match rest {\n ['_', .. rest] => continue rest\n ['0'..='9' as digit, .. rest] => {\n if exp < exp_limit {\n exp = exp * 10 + (digit.to_int() - '0')\n if exp > exp_limit {\n exp = exp_limit\n }\n }\n continue rest\n }\n rest => break rest\n }\n }\n d.decimal_point += exp_sign * exp\n rest\n }\n rest => rest\n }\n // finish\n guard rest is [] else { syntax_err() }\n d.trim()\n d\n}\n\n///|\nfn Decimal::to_double_priv(self : Decimal) -> Double raise {\n let mut exponent = 0\n let mut mantissa = 0L\n // check the underflow and overflow\n // Double: 1.79769e+308 (10^308) - 2.22507e-308 (10^-308)\n if self.digits_num == 0 || self.decimal_point < -330 {\n // zero\n mantissa = 0\n exponent = double_info.bias\n let bits = assemble_bits(mantissa, exponent, self.negative)\n return bits.reinterpret_as_double()\n }\n if self.decimal_point > 310 {\n // overflow\n range_err()\n }\n\n // scale by powers of 2 until in range [0.5 .. 1]\n // right shift\n while self.decimal_point > 0 {\n let mut n = 0\n if self.decimal_point >= powtab.length() {\n n = 60\n } else {\n n = powtab[self.decimal_point]\n }\n self.shift_priv(-n)\n exponent += n\n }\n // left shift\n while self.decimal_point < 0 ||\n (self.decimal_point == 0 && self.digits[0].to_int() < 5) {\n let mut n = 0\n if -self.decimal_point >= powtab.length() {\n n = 60\n } else {\n n = powtab[-self.decimal_point]\n }\n self.shift_priv(n)\n exponent -= n\n }\n\n // normalized floating point range is [1, 2), current [0.5, 1)\n // should decrease the exponent by 1\n exponent -= 1\n\n // minimum representable exponent is bias + 1\n // if the exponent is smaller, move it up and shift decimal accordingly\n if exponent < double_info.bias + 1 {\n let n = double_info.bias + 1 - exponent\n self.shift_priv(-n)\n exponent += n\n }\n if exponent - double_info.bias >= (1 << double_info.exponent_bits) - 1 {\n // overflow\n range_err()\n }\n\n // multiply by (2 ** precision) and round to get mantissa\n // extract mantissa_bits + 1 bits\n self.shift_priv(double_info.mantissa_bits + 1)\n mantissa = self.rounded_integer()\n\n // rounding might have added a bit, shift down.\n if mantissa == 2L << double_info.mantissa_bits {\n mantissa = mantissa >> 1\n exponent += 1\n if exponent - double_info.bias >= (1 << double_info.exponent_bits) - 1 {\n // overflow\n range_err()\n }\n }\n\n // denormalized\n if (mantissa & (1L << double_info.mantissa_bits)) == 0L {\n exponent = double_info.bias\n }\n\n // combining the 52 mantissa bits with the 11 exponent bits and 1 sign bit\n let bits = assemble_bits(mantissa, exponent, self.negative)\n bits.reinterpret_as_double()\n}\n\n///|\nfn Decimal::shift_priv(self : Decimal, s : Int) -> Unit {\n if self.digits_num == 0 {\n return\n }\n let mut s = s\n if s > 0 {\n while s > max_shift {\n self.left_shift(max_shift)\n s -= max_shift\n }\n self.left_shift(s)\n }\n if s < 0 {\n while s < -max_shift {\n self.right_shift(max_shift)\n s += max_shift\n }\n self.right_shift(-s)\n }\n}\n\n///|\nfn assemble_bits(mantissa : Int64, exponent : Int, negative : Bool) -> Int64 {\n let biased_exp = exponent - double_info.bias\n // set the mantissa bits\n let mut bits = mantissa & ((1L << double_info.mantissa_bits) - 1L)\n // set the exponent bits\n let exp_bits = (biased_exp & ((1 << double_info.exponent_bits) - 1)).to_int64()\n bits = bits | (exp_bits << double_info.mantissa_bits)\n // set the sign bit\n if negative {\n bits = bits | (1L << double_info.mantissa_bits << double_info.exponent_bits)\n }\n bits\n}\n\n///|\n/// Extract a rounded 64bit integer\nfn Decimal::rounded_integer(self : Decimal) -> Int64 {\n if self.decimal_point > 20 {\n return 0xFFFFFFFFFFFFFFFFL\n }\n let (n, i) = for n = 0L, i = 0; i < self.decimal_point && i < self.digits_num; {\n continue n * 10L + self.digits[i].to_int64(), i + 1\n } nobreak {\n (n, i)\n }\n let n = for n = n, i = i; i < self.decimal_point; {\n continue n * 10L, i + 1\n } nobreak {\n n\n }\n if self.should_round_up(self.decimal_point) {\n n + 1L\n } else {\n n\n }\n}\n\n///|\n/// Check if truncate at d digits should round up.\n/// Typically, when rounding a decimal fraction to an integer, 7.3 rounds down to 7 and 7.6 rounds up to 8.\n/// Rounding numbers like 7.5, half-way between two integers, will round to even.\nfn Decimal::should_round_up(self : Decimal, d : Int) -> Bool {\n if d < 0 || d >= self.digits_num {\n return false\n }\n if self.digits[d].to_int() == 5 && d + 1 == self.digits_num {\n // half-way between two integers\n // if truncated, the real value is higher than stored value, round up.\n if self.truncated {\n return true\n }\n // round to even\n return d > 0 && self.digits[d - 1].to_int() % 2 != 0\n }\n // normal case\n self.digits[d].to_int() >= 5\n}\n\n///|\n/// Assign a Int64 value to decimal.\nfn Decimal::assign(self : Decimal, v : Int64) -> Unit {\n let buf = FixedArray::make(24, Byte::default())\n\n // write value to buf\n let n = for n = 0, v = v; v > 0; {\n let v1 = v / 10\n buf[n] = (v - v1 * 10).to_byte()\n continue n + 1, v1\n } nobreak {\n n\n }\n\n // reverse the buf\n self.digits_num = 0\n for i in n>..0 {\n self.digits[self.digits_num] = buf[i]\n self.digits_num += 1\n }\n self.decimal_point = self.digits_num\n self.trim()\n}\n\n///|\n/// Binary shift right by s bits.\nfn Decimal::right_shift(self : Decimal, s : Int) -> Unit {\n let mut read_index = 0\n let mut write_index = 0\n\n // read enough leading digits to start a shift\n let mut acc = 0UL\n while acc >> s == 0 {\n if read_index >= self.digits_num {\n while acc >> s == 0 {\n acc *= 10\n read_index += 1\n }\n break\n }\n let d = self.digits[read_index]\n acc = acc * 10 + d.to_int64().reinterpret_as_uint64()\n read_index += 1\n }\n self.decimal_point -= read_index - 1\n\n // read a digit and output a shifted digit\n let mask = (1UL << s) - 1\n while read_index < self.digits_num {\n // output (acc >> s)\n let out = acc >> s\n self.digits[write_index] = out.to_byte()\n write_index += 1\n // contract\n acc = acc & mask\n // expand\n let d = self.digits[read_index]\n acc = acc * 10 + d.to_int64().reinterpret_as_uint64()\n read_index += 1\n }\n\n // output extra digits\n while acc > 0 {\n let out = acc >> s\n if write_index < self.digits.length() {\n self.digits[write_index] = out.to_byte()\n write_index += 1\n } else if out > 0 {\n self.truncated = true\n }\n acc = acc & mask\n acc = acc * 10\n }\n\n // update and trim\n self.digits_num = write_index\n self.trim()\n}\n\n///|\n/// Cheat sheet for left shift: table indexed by shift count giving\n/// number of new digits that will be introduced by that shift.\n/// left_shift_cheats[s] = (new digits num, (5 ** s))\nlet left_shift_cheats : ReadOnlyArray[(Int, String)] = [\n (0, \"\"),\n (1, \"5\"), // * 2\n (1, \"25\"), // * 4\n (1, \"125\"), // * 8\n (2, \"625\"), // * 16\n (2, \"3125\"), // * 32\n (2, \"15625\"), // * 64\n (3, \"78125\"), // * 128\n (3, \"390625\"), // * 256\n (3, \"1953125\"), // * 512\n (4, \"9765625\"), // * 1024\n (4, \"48828125\"), // * 2048\n (4, \"244140625\"), // * 4096\n (4, \"1220703125\"), // * 8192\n (5, \"6103515625\"), // * 16384\n (5, \"30517578125\"), // * 32768\n (5, \"152587890625\"), // * 65536\n (6, \"762939453125\"), // * 131072\n (6, \"3814697265625\"), // * 262144\n (6, \"19073486328125\"), // * 524288\n (7, \"95367431640625\"), // * 1048576\n (7, \"476837158203125\"), // * 2097152\n (7, \"2384185791015625\"), // * 4194304\n (7, \"11920928955078125\"), // * 8388608\n (8, \"59604644775390625\"), // * 16777216\n (8, \"298023223876953125\"), // * 33554432\n (8, \"1490116119384765625\"), // * 67108864\n (9, \"7450580596923828125\"), // * 134217728\n (9, \"37252902984619140625\"), // * 268435456\n (9, \"186264514923095703125\"), // * 536870912\n (10, \"931322574615478515625\"), // * 1073741824\n (10, \"4656612873077392578125\"), // * 2147483648\n (10, \"23283064365386962890625\"), // * 4294967296\n (10, \"116415321826934814453125\"), // * 8589934592\n (11, \"582076609134674072265625\"), // * 17179869184\n (11, \"2910383045673370361328125\"), // * 34359738368\n (11, \"14551915228366851806640625\"), // * 68719476736\n (12, \"72759576141834259033203125\"), // * 137438953472\n (12, \"363797880709171295166015625\"), // * 274877906944\n (12, \"1818989403545856475830078125\"), // * 549755813888\n (13, \"9094947017729282379150390625\"), // * 1099511627776\n (13, \"45474735088646411895751953125\"), // * 2199023255552\n (13, \"227373675443232059478759765625\"), // * 4398046511104\n (13, \"1136868377216160297393798828125\"), // * 8796093022208\n (14, \"5684341886080801486968994140625\"), // * 17592186044416\n (14, \"28421709430404007434844970703125\"), // * 35184372088832\n (14, \"142108547152020037174224853515625\"), // * 70368744177664\n (15, \"710542735760100185871124267578125\"), // * 140737488355328\n (15, \"3552713678800500929355621337890625\"), // * 281474976710656\n (15, \"17763568394002504646778106689453125\"), // * 562949953421312\n (16, \"88817841970012523233890533447265625\"), // * 1125899906842624\n (16, \"444089209850062616169452667236328125\"), // * 2251799813685248\n (16, \"2220446049250313080847263336181640625\"), // * 4503599627370496\n (16, \"11102230246251565404236316680908203125\"), // * 9007199254740992\n (17, \"55511151231257827021181583404541015625\"), // * 18014398509481984\n (17, \"277555756156289135105907917022705078125\"), // * 36028797018963968\n (17, \"1387778780781445675529539585113525390625\"), // * 72057594037927936\n (18, \"6938893903907228377647697925567626953125\"), // * 144115188075855872\n (18, \"34694469519536141888238489627838134765625\"), // * 288230376151711744\n (18, \"173472347597680709441192448139190673828125\"), // * 576460752303423488\n (19, \"867361737988403547205962240695953369140625\"), // * 1152921504606846976\n]\n\n///|\n/// Lookup the cheat sheet to find the new digits num.\nfn Decimal::new_digits(self : Decimal, s : Int) -> Int {\n let new_digits = left_shift_cheats[s].0\n let cheat_num = left_shift_cheats[s].1\n // check if the leading digits lexicographically less than cheats num.\n let less = for i in 0..<cheat_num.length() {\n if i >= self.digits_num {\n break true\n }\n let d = cheat_num.unsafe_get(i).to_int() - '0'.to_int()\n if self.digits[i].to_int() != d {\n break self.digits[i].to_int() < d\n }\n } nobreak {\n false\n }\n if less {\n new_digits - 1\n } else {\n new_digits\n }\n}\n\n///|\n/// Binary shift left by s bits.\nfn Decimal::left_shift(self : Decimal, s : Int) -> Unit {\n let new_digits = self.new_digits(s)\n // from right to left\n let mut read_index = self.digits_num\n let mut write_index = self.digits_num + new_digits\n\n // read a digit and output a shifted digit\n let mut acc = 0L\n read_index -= 1\n while read_index >= 0 {\n let d = self.digits[read_index].to_int64()\n acc += d << s\n let quo = acc / 10L\n let rem = (acc - quo * 10L).to_int()\n write_index -= 1\n if write_index < self.digits.length() {\n self.digits[write_index] = rem.to_byte()\n } else if rem != 0 {\n self.truncated = true\n }\n acc = quo\n read_index -= 1\n }\n\n // output extra digits\n while acc > 0L {\n let quo = acc / 10L\n let rem = (acc - 10L * quo).to_int()\n write_index -= 1\n if write_index < self.digits.length() {\n self.digits[write_index] = rem.to_byte()\n } else if rem != 0 {\n self.truncated = true\n }\n acc = quo\n }\n\n // update and trim\n self.digits_num += new_digits\n if self.digits_num > self.digits.length() {\n self.digits_num = self.digits.length()\n }\n self.decimal_point += new_digits\n self.trim()\n}\n\n///|\n/// Trim trailing zeros.\nfn Decimal::trim(self : Decimal) -> Unit {\n while self.digits_num > 0 && self.digits[self.digits_num - 1] == 0 {\n self.digits_num -= 1\n }\n if self.digits_num == 0 {\n self.decimal_point = 0\n }\n}\n\n///|\nimpl Show for Decimal with output(self, logger) {\n if self.digits_num == 0 {\n logger.write_char('0')\n return\n }\n if self.decimal_point <= 0 {\n // zeros filling between the decimal point and the digits\n logger.write_string(\"0.\")\n for _ in 0..<-self.decimal_point {\n logger.write_char('0')\n }\n for i in 0..<self.digits_num {\n logger.write_string(self.digits[i].to_int().to_string())\n }\n } else if self.decimal_point < self.digits_num {\n // decimal point in the middle of digits\n for i in 0..<self.digits_num {\n if i == self.decimal_point {\n logger.write_char('.')\n }\n logger.write_string(self.digits[i].to_int().to_string())\n }\n } else {\n // zeros filling between the digits and the decimal point\n for i in 0..<self.digits_num {\n logger.write_string(self.digits[i].to_int().to_string())\n }\n for _ in 0..<(self.decimal_point - self.digits_num) {\n logger.write_char('0')\n }\n }\n}\n\n///|\nfn Decimal::to_string(self : Decimal) -> String {\n Show::to_string(self)\n}\n\n///|\ntest \"new\" {\n let hpd = Decimal::from_int64_priv(1L)\n inspect(hpd.digits.length(), content=\"800\")\n inspect(hpd.digits_num, content=\"1\")\n inspect(hpd.decimal_point, content=\"1\")\n inspect(hpd.negative, content=\"false\")\n inspect(hpd.truncated, content=\"false\")\n}\n\n///|\ntest \"from_int64\" {\n let hpd = Decimal::from_int64_priv(123456789L)\n inspect(hpd.to_string(), content=\"123456789\")\n}\n\n///|\ntest \"parse_decimal\" {\n let s = \"0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625\"\n @test.assert_eq(parse_decimal_priv(s).to_string(), s)\n @test.assert_eq(parse_decimal_priv(\"1.0e-10\").to_string(), \"0.0000000001\")\n}\n\n///|\ntest \"to_string\" {\n let hpd = Decimal::from_int64_priv(123456789L)\n hpd.decimal_point = 1\n inspect(hpd.to_string(), content=\"1.23456789\")\n hpd.decimal_point = 0\n inspect(hpd.to_string(), content=\"0.123456789\")\n hpd.decimal_point = -1\n inspect(hpd.to_string(), content=\"0.0123456789\")\n hpd.decimal_point = 10\n inspect(hpd.to_string(), content=\"1234567890\")\n}\n\n///|\ntest \"shift\" {\n let tests : Array[_] = [\n (0L, 100, \"0\"),\n (0L, -100, \"0\"),\n (1L, 100, \"1267650600228229401496703205376\"),\n (\n 1L, -100, \"0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625\",\n ),\n (12345678L, 8, \"3160493568\"),\n (12345678L, -8, \"48225.3046875\"),\n (195312L, 9, \"99999744\"),\n (1953125L, 9, \"1000000000\"),\n ]\n for t in tests {\n let d = Decimal::from_int64_priv(t.0)\n d.shift_priv(t.1)\n @test.assert_eq(d.to_string(), t.2)\n }\n}\n\n///|\ntest \"parse decimal with underscore\" {\n inspect(parse_decimal_priv(\"1e1_2\"), content=\"1000000000000\")\n inspect(parse_decimal_priv(\"1e12\"), content=\"1000000000000\")\n inspect(parse_decimal_priv(\"1_2_3\"), content=\"123\")\n}\n\n///|\ntest \"parse decimal error\" {\n assert_true((try? parse_decimal_priv(\"1e\")) is Err(Failure(\"invalid syntax\")))\n assert_true(\n (try? parse_decimal_priv(\"1e+\")) is Err(Failure(\"invalid syntax\")),\n )\n assert_true(\n (try? parse_decimal_priv(\"1e_\")) is Err(Failure(\"invalid syntax\")),\n )\n assert_true(\n (try? parse_decimal_priv(\"1-23\")) is Err(Failure(\"invalid syntax\")),\n )\n assert_true(\n (try? parse_decimal_priv(\"1.2.3\")) is Err(Failure(\"invalid syntax\")),\n )\n}\n\n///|\ntest \"parse decimal with large numbers\" {\n let s = String::make(100, '9')\n inspect(parse_decimal_priv(s), content=s)\n}\n\n///|\ntest \"should_round_up when truncated and half-way\" {\n // Create a decimal from \"12.50\"\n let decimal = parse_decimal_priv(\"12.50\")\n // Convert to double\n inspect(decimal.to_double_priv(), content=\"12.5\")\n}\n\n///|\ntest \"parse_decimal with large numbers and truncation\" {\n // Construct a very large number to trigger truncation\n let s = String::make(1000, '9')\n inspect(parse_decimal_priv(s), content=String::make(800, '9'))\n}\n\n///|\ntest \"rounded_integer overflow when decimal_point > 20\" {\n // This test should trigger the uncovered line 252 in rounded_integer\n // We need to create a decimal that will have decimal_point > 20 after shifting\n // but not trigger the early overflow check in to_double_priv\n\n // Create a decimal manually to bypass the early overflow checks\n let decimal = Decimal::new_priv()\n decimal.negative = false\n decimal.decimal_point = 25 // This is > 20 but < 310\n decimal.digits_num = 1\n decimal.digits[0] = (1 : Int).to_byte()\n decimal.truncated = false\n\n // Call rounded_integer directly to trigger the uncovered line\n let result = decimal.rounded_integer()\n inspect(result, content=\"-1\") // Should be Int64::max_value\n}\n\n///|\ntest \"corner cases\" {\n assert_true((try? parse_decimal_priv(\".123\")) is Ok(_))\n assert_true((try? parse_decimal_priv(\".\")) is Err(Failure(\"invalid syntax\")))\n assert_true((try? parse_decimal_priv(\"-\")) is Err(Failure(\"invalid syntax\")))\n}\n\n///|\ntest \"parse_double mantissa normalization boundary\" {\n inspect(parse_double(\"1.9999999999999999\"), content=\"2\")\n inspect(parse_double(\"9007199254740991.5\"), content=\"9007199254740992\")\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nconst SAFE_INTEGER_LIMIT : Int64 = 9007199254740991L\n\n///|\nconst MAX_MANTISSA_FAST_PATH : UInt64 = 9007199254740992UL\n\n///|\nconst MIN_EXPONENT_FAST_PATH : Int64 = -22L\n\n///|\nconst MAX_EXPONENT_FAST_PATH : Int64 = 22L\n\n///|\nconst MAX_EXPONENT_DISGUISED_FAST_PATH : Int64 = 37L\n\n///|\nconst EXPONENT_CAP : Int64 = 100000L\n\n///|\nconst MAX_UINT64 : UInt64 = 0xffffffffffffffffUL\n\n///|\nlet pow10_table : ReadOnlyArray[Double] = [\n 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0,\n 1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,\n 100000000000000.0, 1000000000000000.0, 10000000000000000.0, 100000000000000000.0,\n 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0, 1000000000000000000000.0,\n 10000000000000000000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n]\n\n///|\nlet int_pow10_table : ReadOnlyArray[UInt64] = [\n 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL,\n 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL,\n 100000000000000UL, 1000000000000000UL,\n]\n\n///|\npriv struct JsonNumberScan {\n negative : Bool\n is_integer : Bool\n mantissa : UInt64\n exponent : Int64\n many_digits : Bool\n}\n\n///|\nfn json_pow10_fast_path(exponent : Int) -> Double {\n pow10_table[exponent & 31]\n}\n\n///|\nfn checked_mul(a : UInt64, b : UInt64) -> UInt64? {\n if a == 0UL || b == 0UL {\n return Some(0UL)\n }\n if a == 1UL {\n return Some(b)\n }\n if b == 1UL {\n return Some(a)\n }\n if b.clz() == 0 || a.clz() == 0 {\n return None\n }\n let quotient = MAX_UINT64 / b\n if a > quotient {\n None\n } else {\n Some(a * b)\n }\n}\n\n///|\nfn JsonNumberScan::try_fast_double(self : JsonNumberScan) -> Double? {\n if self.mantissa == 0UL {\n let value = 0.0\n return Some(if self.negative { -value } else { value })\n }\n if self.many_digits ||\n self.exponent < MIN_EXPONENT_FAST_PATH ||\n self.exponent > MAX_EXPONENT_DISGUISED_FAST_PATH ||\n self.mantissa > MAX_MANTISSA_FAST_PATH {\n return None\n }\n let value = if self.exponent <= MAX_EXPONENT_FAST_PATH {\n let value = self.mantissa.to_double()\n if self.exponent < 0L {\n value / json_pow10_fast_path(-self.exponent.to_int())\n } else {\n value * json_pow10_fast_path(self.exponent.to_int())\n }\n } else {\n let shift = self.exponent - MAX_EXPONENT_FAST_PATH\n let mantissa = match\n checked_mul(self.mantissa, int_pow10_table[shift.to_int()]) {\n Some(m) => m\n None => return None\n }\n if mantissa > MAX_MANTISSA_FAST_PATH {\n return None\n }\n mantissa.to_double() * json_pow10_fast_path(MAX_EXPONENT_FAST_PATH.to_int())\n }\n Some(if self.negative { -value } else { value })\n}\n\n///|\nfn ParseContext::scan_json_number(\n ctx : ParseContext,\n start : Int,\n end : Int,\n) -> JsonNumberScan {\n let negative = ctx.input.unsafe_get(start) == '-'\n let mut has_decimal = false\n let mut has_exponent = false\n let mut exponent_negative = false\n let mut exponent_part = 0L\n let mut fractional_digits = 0\n let mut mantissa = 0UL\n let mut significant_digits = 0\n let mut seen_nonzero = false\n for i = (if negative { start + 1 } else { start }); i < end; i = i + 1 {\n let c = ctx.input.unsafe_get(i)\n if c is ('0'..='9') {\n let digit = c.to_int() - '0'\n if has_exponent {\n if exponent_part < EXPONENT_CAP {\n let next_exponent = exponent_part * 10L + digit.to_int64()\n exponent_part = if next_exponent > EXPONENT_CAP {\n EXPONENT_CAP\n } else {\n next_exponent\n }\n }\n } else {\n if has_decimal {\n fractional_digits += 1\n }\n if digit != 0 || seen_nonzero {\n seen_nonzero = true\n significant_digits += 1\n if significant_digits <= 19 {\n mantissa = mantissa * 10UL +\n UInt64::extend_uint(digit.reinterpret_as_uint())\n }\n }\n }\n } else if c == '.' {\n has_decimal = true\n } else if c == 'e' || c == 'E' {\n has_exponent = true\n if i + 1 < end {\n let next = ctx.input.unsafe_get(i + 1)\n if next == '-' {\n exponent_negative = true\n }\n }\n }\n }\n let exponent_part = if exponent_negative {\n -exponent_part\n } else {\n exponent_part\n }\n {\n negative,\n is_integer: !has_decimal && !has_exponent,\n mantissa,\n exponent: exponent_part - fractional_digits.to_int64(),\n many_digits: significant_digits > 19,\n }\n}\n\n///|\nfn ParseContext::lex_integer_end(\n ctx : ParseContext,\n start : Int,\n end : Int,\n) -> (Double, StringView?) {\n let negative = ctx.input.unsafe_get(start) == '-'\n let number_start = if negative { start + 1 } else { start }\n for i = number_start, acc = 0L {\n if i >= end {\n let value = if negative { -acc } else { acc }\n break (value.to_double(), None)\n }\n let digit = (ctx.input.unsafe_get(i).to_int() - '0').to_int64()\n if acc > (SAFE_INTEGER_LIMIT - digit) / 10L {\n let s = ctx.input.view(start_offset=start, end_offset=end)\n return if negative {\n (@double.neg_infinity, Some(s))\n } else {\n (@double.infinity, Some(s))\n }\n }\n continue i + 1, acc * 10L + digit\n }\n}\n\n///|\nfn ParseContext::lex_decimal_integer(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n for ;; {\n match ctx.read_char() {\n Some('.') => return ctx.lex_decimal_point(start~)\n Some('e' | 'E') => return ctx.lex_decimal_exponent(start~)\n Some(c) => {\n if c is ('0'..='9') {\n continue\n }\n ctx.offset -= 1\n return ctx.lex_number_end(start, ctx.offset)\n }\n None => return ctx.lex_number_end(start, ctx.offset)\n }\n }\n}\n\n///|\nfn ParseContext::lex_decimal_point(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n match ctx.read_char() {\n Some(c) =>\n if c is ('0'..='9') {\n ctx.lex_decimal_fraction(start~)\n } else {\n ctx.invalid_char(shift=-1)\n }\n None => raise InvalidEof\n }\n}\n\n///|\nfn ParseContext::lex_decimal_fraction(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n for ;; {\n match ctx.read_char() {\n Some('e' | 'E') => return ctx.lex_decimal_exponent(start~)\n Some(c) => {\n if c is ('0'..='9') {\n continue\n }\n ctx.offset -= 1\n return ctx.lex_number_end(start, ctx.offset)\n }\n None => return ctx.lex_number_end(start, ctx.offset)\n }\n }\n}\n\n///|\nfn ParseContext::lex_decimal_exponent(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n match ctx.read_char() {\n Some('+') | Some('-') => return ctx.lex_decimal_exponent_sign(start~)\n Some(c) => {\n if c is ('0'..='9') {\n return ctx.lex_decimal_exponent_integer(start~)\n }\n ctx.offset -= 1\n ctx.invalid_char()\n }\n None => raise InvalidEof\n }\n}\n\n///|\nfn ParseContext::lex_decimal_exponent_sign(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n match ctx.read_char() {\n Some(c) => {\n if c is ('0'..='9') {\n return ctx.lex_decimal_exponent_integer(start~)\n }\n ctx.offset -= 1\n ctx.invalid_char()\n }\n None => raise InvalidEof\n }\n}\n\n///|\nfn ParseContext::lex_decimal_exponent_integer(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) {\n for ;; {\n match ctx.read_char() {\n Some(c) => {\n if c is ('0'..='9') {\n continue\n }\n ctx.offset -= 1\n return ctx.lex_number_end(start, ctx.offset)\n }\n None => return ctx.lex_number_end(start, ctx.offset)\n }\n }\n}\n\n///|\nfn ParseContext::lex_zero(\n ctx : ParseContext,\n start~ : Int,\n) -> (Double, StringView?) raise ParseError {\n match ctx.read_char() {\n Some('.') => ctx.lex_decimal_point(start~)\n Some('e' | 'E') => ctx.lex_decimal_exponent(start~)\n Some(c) => {\n if c is ('0'..='9') {\n ctx.offset -= 1\n ctx.invalid_char()\n }\n ctx.offset -= 1\n return ctx.lex_number_end(start, ctx.offset)\n }\n None => return ctx.lex_number_end(start, ctx.offset)\n }\n}\n\n///|\nfn ParseContext::lex_number_end(\n ctx : ParseContext,\n start : Int,\n end : Int,\n) -> (Double, StringView?) {\n // Fast path for JSON numbers: the lexer has already validated the grammar,\n // so scan raw UTF-16 digits once and bypass the general strconv parser for\n // safe integers and Clinger-style fast-path doubles. Fall back to strconv for\n // large or precision-sensitive numbers so existing rounding behavior is kept.\n let scan = ctx.scan_json_number(start, end)\n if scan.is_integer {\n return ctx.lex_integer_end(start, end)\n }\n match scan.try_fast_double() {\n Some(d) => (d, None)\n None => {\n let s = ctx.input.view(start_offset=start, end_offset=end)\n let parsed_double = try? @internal/strconv.parse_double(s)\n match parsed_double {\n // For normal values, return without string representation\n Ok(d) => (d, None)\n // If parsing fails as a double, treat it as infinity and preserve the string\n Err(_) =>\n if scan.negative {\n (@double.neg_infinity, Some(s))\n } else {\n (@double.infinity, Some(s))\n }\n }\n }\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nconst GPRIME1 : UInt = 0x9E3779B1\n\n///|\nconst GPRIMES2 : UInt = 0x85EBCA77\n\n///|\nconst GPRIME3 : UInt = 0xC2B2AE3D\n\n///|\nconst GPRIME4 : UInt = 0x27D4EB2F\n\n///|\nconst GPRIME5 : UInt = 0x165667B1\n\n///|\n/// Represents a hasher that implements the xxHash32 algorithm. The hasher\n/// maintains a mutable accumulator that is updated with each value added to the\n/// hash computation.\n///\n/// This struct provides methods for combining different types of values into a\n/// single hash value, making it suitable for implementing hash functions for\n/// custom types.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_int(42)\n/// hasher.combine_string(\"hello\")\n/// inspect(hasher.finalize(), content=\"860601284\")\n/// }\n/// ```\nstruct Hasher {\n mut acc : UInt\n}\n\n///|\n/// Creates a new hasher with an optional seed value.\n///\n/// Parameters:\n///\n/// * `seed` : An integer value used to initialize the hasher's internal state.\n/// Defaults to 0.\n///\n/// Returns a new `Hasher` instance initialized with the given seed value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let h1 = Hasher::new(seed=0) // Create a hasher with default seed\n/// let h2 = Hasher::new(seed=42) // Create a hasher with custom seed\n/// let x = 123\n/// h1.combine(x)\n/// h2.combine(x)\n/// inspect(h1.finalize() != h2.finalize(), content=\"true\") // Different seeds produce different hashes\n/// }\n/// ```\npub fn Hasher::new(seed? : Int = seed) -> Hasher {\n { acc: seed.reinterpret_as_uint() + GPRIME5 }\n}\n\n///|\n#cfg(not(target=\"js\"))\nlet seed : Int = 0\n\n///|\n#cfg(target=\"js\")\nlet seed : Int = random_seed()\n\n///|\n#cfg(target=\"js\")\nextern \"js\" fn random_seed() -> Int =\n #|() => {\n #| if (globalThis.crypto?.getRandomValues) {\n #| const array = new Uint32Array(1);\n #| globalThis.crypto.getRandomValues(array);\n #| return array[0] | 0; // Convert to signed 32\n #| } else {\n #| return Math.floor(Math.random() * 0x100000000) | 0; // Fallback to Math.random\n #| }\n #|}\n\n///|\n/// Combines a hashable value with the current state of the hasher. This is\n/// typically used to incrementally build a hash value from multiple components.\n///\n/// Parameters:\n///\n/// * `self` : The hasher instance to update.\n/// * `value` : The value to be combined with the current hash state. Must\n/// implement the `Hash` trait.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine(42)\n/// hasher.combine(\"hello\")\n/// inspect(hasher.finalize(), content=\"860601284\")\n/// }\n/// ```\npub fn[T : Hash] Hasher::combine(self : Hasher, value : T) -> Unit {\n value.hash_combine(self)\n}\n\n///|\n/// Combines the unit value (i.e., `()`) into the hasher's internal state by\n/// hashing it as an integer value of 0.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object to combine the unit value into.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_unit()\n/// inspect(hasher.finalize(), content=\"148298089\")\n/// }\n/// ```\npub fn Hasher::combine_unit(self : Hasher) -> Unit {\n self.combine_uint(0)\n}\n\n///|\n/// Combines a boolean value into the current hash state. The boolean value is\n/// converted to an integer (1 for true, 0 for false) before being combined with\n/// the hash.\n///\n/// Parameters:\n///\n/// * `self` : The hasher instance to update.\n/// * `value` : The boolean value to be combined into the hash state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_bool(true)\n/// inspect(hasher.finalize(), content=\"-205818221\")\n/// }\n/// ```\npub fn Hasher::combine_bool(self : Hasher, value : Bool) -> Unit {\n self.combine_uint(if value { 1 } else { 0 })\n}\n\n///|\n/// Combines a 32-bit integer value into the hasher's internal state. The value\n/// is processed\n/// as a 4-byte sequence, and the internal accumulator is updated accordingly.\n///\n/// Parameters:\n///\n/// * `self` : The hasher instance to update.\n/// * `value` : A 32-bit integer value to be incorporated into the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_int(42)\n/// inspect(hasher.finalize(), content=\"1161967057\")\n/// }\n/// ```\npub fn Hasher::combine_int(self : Hasher, value : Int) -> Unit {\n self.combine_uint(value.reinterpret_as_uint())\n}\n\n///|\n/// Combines a 64-bit integer value into the hash state by splitting it into two\n/// 32-bit parts and processing them separately. This method is used internally\n/// by the hash implementation to incorporate 64-bit integers into the hash\n/// computation.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object whose internal state will be updated.\n/// * `value` : The 64-bit integer value to be incorporated into the hash state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_int64(42L)\n/// inspect(hasher.finalize(), content=\"-1962516083\")\n/// }\n/// ```\npub fn Hasher::combine_int64(self : Hasher, value : Int64) -> Unit {\n self.acc += 8\n self.consume4(value.reinterpret_as_uint64().to_uint())\n self.consume4((value.reinterpret_as_uint64() >> 32).to_uint())\n}\n\n///|\n/// Combines an unsigned 32-bit integer into the hasher's internal state by\n/// reinterpreting it as a signed integer and incorporating it into the hash\n/// computation.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object to update.\n/// * `value` : The unsigned 32-bit integer value to be combined into the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_uint(42U)\n/// inspect(hasher.finalize(), content=\"1161967057\")\n/// }\n/// ```\npub fn Hasher::combine_uint(self : Hasher, value : UInt) -> Unit {\n self.acc += 4\n self.consume4(value)\n}\n\n///|\n/// Combines a 64-bit unsigned integer into the hasher's internal state. Useful\n/// for hashing `UInt64` values as part of a larger composite structure.\n///\n/// Parameters:\n///\n/// * `self` : The hasher instance to update.\n/// * `value` : The 64-bit unsigned integer value to be incorporated into the\n/// hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_uint64(42UL)\n/// inspect(hasher.finalize(), content=\"-1962516083\")\n/// }\n/// ```\npub fn Hasher::combine_uint64(self : Hasher, value : UInt64) -> Unit {\n self.combine_int64(value.reinterpret_as_int64())\n}\n\n///|\n/// Combines a double-precision floating-point number into the hasher's internal\n/// state by reinterpreting its bits as a 64-bit integer. Maintains consistent\n/// hashing behavior regardless of the floating-point value's representation.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher to combine the value into.\n/// * `value` : The double-precision floating-point number to be combined into\n/// the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_double(3.14)\n/// inspect(hasher.finalize(), content=\"-428265677\")\n/// }\n/// ```\npub fn Hasher::combine_double(self : Hasher, value : Double) -> Unit {\n self.combine_int64(value.reinterpret_as_int64())\n}\n\n///|\n/// Combines a 32-bit floating-point value into the hasher by reinterpreting its\n/// bit pattern as a 32-bit integer. The operation maintains the same hash result\n/// regardless of the floating-point value's representation.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object that maintains the internal state of the\n/// hashing operation.\n/// * `value` : The 32-bit floating-point value to be combined into the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine(3.14F)\n/// inspect(hasher.finalize(), content=\"635116317\") // Hash of the bits of 3.14\n/// }\n/// ```\n#deprecated\npub fn Hasher::combine_float(self : Hasher, value : Float) -> Unit {\n self.combine_uint(value.reinterpret_as_uint())\n}\n\n///|\nfn Float::reinterpret_as_uint(self : Float) -> UInt = \"%f32.to_i32_reinterpret\"\n\n///|\n/// Combines a byte value into the hash state.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object to update with the byte value.\n/// * `byte` : The byte value to be combined into the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_byte(b'\\xFF')\n/// inspect(hasher.finalize(), content=\"1955036104\")\n/// }\n/// ```\npub fn Hasher::combine_byte(self : Hasher, value : Byte) -> Unit {\n self.consume1(value)\n}\n\n///|\n/// Combines a byte sequence into the hasher's internal state using xxHash32\n/// algorithm. Processes the input bytes in chunks of 4 bytes for efficiency,\n/// with remaining bytes processed individually.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object to update with the byte sequence.\n/// * `bytes` : The byte sequence to be combined into the hash.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_bytes(b\"\\xFF\\x00\\xFF\\x00\")\n/// inspect(hasher.finalize(), content=\"-686861102\")\n/// }\n/// ```\npub fn Hasher::combine_bytes(self : Hasher, value : Bytes) -> Unit {\n let (cur, remain) = for cur = 0, remain = value.length(); remain >= 4; {\n self.consume4(endian32(value, cur))\n continue cur + 4, remain - 4\n } nobreak {\n (cur, remain)\n }\n for cur = cur, remain = remain; remain >= 1; {\n self.consume1(value[cur])\n continue cur + 1, remain - 1\n }\n}\n\n///|\n/// Combines a string value into the current hash state by processing each\n/// character in the string sequentially.\n///\n/// Parameters:\n///\n/// * `self` : The hasher object whose state will be updated.\n/// * `value` : The string value to be combined into the hash state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_string(\"hello\")\n/// inspect(hasher.finalize(), content=\"-655549713\")\n/// }\n/// ```\npub fn Hasher::combine_string(self : Hasher, value : String) -> Unit {\n for i in 0..<value.length() {\n self.combine_uint(value.unsafe_get(i).to_int().reinterpret_as_uint())\n }\n}\n\n///|\n/// Combines a character value into the hasher's internal state. The character is\n/// first converted to its Unicode code point (as an integer) before being\n/// combined.\n///\n/// Parameters:\n///\n/// * `self` : The hasher instance to update.\n/// * `value` : The character value to be combined into the hash state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_char('A')\n/// inspect(hasher.finalize(), content=\"-1625495534\")\n/// }\n/// ```\npub fn Hasher::combine_char(self : Hasher, value : Char) -> Unit {\n self.combine_uint(value.to_uint())\n}\n\n///|\n/// Finalizes the hashing process and returns the computed hash value. Applies an\n/// avalanche function to improve the distribution of the hash value.\n///\n/// Parameters:\n///\n/// * `hasher` : The hasher object containing the accumulated hash state.\n///\n/// Returns a 32-bit integer representing the final hash value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_byte(b'\\xFF')\n/// inspect(hasher.finalize(), content=\"1955036104\")\n/// }\n/// ```\npub fn Hasher::finalize(self : Hasher) -> Int {\n self.avalanche().reinterpret_as_int()\n}\n\n///|\nfn Hasher::avalanche(self : Hasher) -> UInt {\n let mut acc = self.acc\n acc = acc ^ (acc >> 15)\n acc *= GPRIMES2\n acc = acc ^ (acc >> 13)\n acc *= GPRIME3\n acc = acc ^ (acc >> 16)\n acc\n}\n\n///|\nfn Hasher::consume4(self : Hasher, input : UInt) -> Unit {\n self.acc = rotl(self.acc + input * GPRIME3, 17) * GPRIME4\n}\n\n///|\nfn Hasher::consume1(self : Hasher, input : Byte) -> Unit {\n self.acc = rotl(self.acc + input.to_uint() * GPRIME5, 11) * GPRIME1\n}\n\n///|\nfn rotl(x : UInt, r : Int) -> UInt {\n (x << r) | (x >> (32 - r))\n}\n\n///|\nfn endian32(input : Bytes, cur : Int) -> UInt {\n input[cur + 0].to_uint() |\n (\n (input[cur + 1].to_uint() << 8) |\n (input[cur + 2].to_uint() << 16) |\n (input[cur + 3].to_uint() << 24)\n )\n}\n\n///|\n/// Implements the `Hash` trait for `String` type, providing a method to combine\n/// a string's hash value with a hasher's state.\n///\n/// Parameters:\n///\n/// * `self` : The string value to be hashed.\n/// * `hasher` : The hasher object that will be updated with the string's hash\n/// value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let s1 = \"hello\"\n/// let s2 = \"hello\"\n/// let s3 = \"world\"\n/// inspect(Hash::hash(s1) == Hash::hash(s2), content=\"true\")\n/// inspect(Hash::hash(s1) == Hash::hash(s3), content=\"false\")\n/// }\n/// ```\npub impl Hash for String with hash_combine(self, hasher) {\n hasher.combine_string(self)\n}\n\n///|\npub impl Hash for StringView with hash_combine(\n self : StringView,\n hasher : Hasher,\n) -> Unit {\n let str = self.str()\n for i in self.start()..<self.end() {\n hasher.combine_uint(str.unsafe_get(i).to_int().reinterpret_as_uint())\n }\n}\n\n///|\n/// Implements hash combination for integers by combining the integer value with\n/// a hasher. This implementation ensures that integers can be used as keys in\n/// hash-based collections like hash maps and hash sets.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be hashed.\n/// * `hasher` : A `Hasher` object that accumulates the hash value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_int(42)\n/// inspect(hasher.finalize(), content=\"1161967057\")\n/// }\n/// ```\npub impl Hash for Int with hash_combine(self, hasher) {\n hasher.combine_int(self)\n}\n\n///|\n/// Combines the hash value of an unsigned integer with a hasher object. This is\n/// useful when you need to hash a data structure that contains unsigned\n/// integers.\n///\n/// Parameters:\n///\n/// * `value` : The unsigned integer to be combined with the hasher.\n/// * `hasher` : The hasher object that will incorporate the hash value of the\n/// unsigned integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_uint(42U)\n/// inspect(hasher.finalize(), content=\"1161967057\")\n/// }\n/// ```\npub impl Hash for UInt with hash_combine(self, hasher) {\n hasher.combine_uint(self)\n}\n\n///|\n/// Implements the `Hash` trait for `UInt64` by combining the hash value of an\n/// unsigned 64-bit integer into a hasher.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 64-bit integer value to be hashed.\n/// * `hasher` : The hasher object used to compute the combined hash value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_uint64(42UL)\n/// inspect(hasher.finalize(), content=\"-1962516083\")\n/// }\n/// ```\npub impl Hash for UInt64 with hash_combine(self, hasher) {\n hasher.combine_uint64(self)\n}\n\n///|\n/// Implements the `Hash` trait for `Option` types, allowing them to be used as\n/// keys in hash-based collections.\n///\n/// Parameters:\n///\n/// * `self` : The `Option` value to be hashed.\n/// * `hasher` : The hasher object that accumulates the hash state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// let some_value : Int? = Some(42)\n/// let none_value : Int? = None\n/// hasher.combine(some_value)\n/// inspect(hasher.finalize(), content=\"2103260413\")\n/// let hasher2 = Hasher::new(seed=0)\n/// hasher2.combine(none_value)\n/// inspect(hasher2.finalize(), content=\"148298089\")\n/// }\n/// ```\npub impl[X : Hash] Hash for X? with hash_combine(self, hasher) {\n match self {\n None => hasher.combine_int(0)\n Some(x) => {\n hasher.combine_int(1)\n hasher.combine(x)\n }\n }\n}\n\n///|\n/// Implements the `Hash` trait for `Result` type, allowing `Result` values to be\n/// used in hash-based collections.\n///\n/// Parameters:\n///\n/// * `self` : The `Result` value to be hashed.\n/// * `hasher` : The hasher object to which the hash value will be combined.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// let ok_result : Result[Int, String] = Ok(42)\n/// let err_result : Result[Int, String] = Err(\"error\")\n/// hasher.combine(ok_result)\n/// inspect(hasher.finalize(), content=\"-1948635851\")\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine(err_result)\n/// inspect(hasher.finalize(), content=\"1953766574\")\n/// }\n/// ```\npub impl[T : Hash, E : Hash] Hash for Result[T, E] with hash_combine(\n self,\n hasher,\n) {\n match self {\n Ok(x) => {\n hasher.combine_int(0)\n hasher.combine(x)\n }\n Err(x) => {\n hasher.combine_int(1)\n hasher.combine(x)\n }\n }\n}\n\n///|\npub impl Hash for BytesView with hash_combine(self : BytesView, hasher : Hasher) {\n let data = self.bytes()\n let (start, rest) = for start = self.start(), rest = self.len(); rest >= 4; {\n let result = for i in 0..<=3; result = (0 : UInt) {\n continue result | (data.unsafe_get(i + start).to_uint() << (8 * i))\n } nobreak {\n result\n }\n hasher.combine_uint(result)\n continue start + 4, rest - 4\n } nobreak {\n (start, rest)\n }\n for start = start, rest = rest; rest >= 1; {\n hasher.combine_byte(data.unsafe_get(start))\n continue start + 1, rest - 1\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Aborts the program with an error message. Always causes a panic, regardless\n/// of the message provided.\n///\n/// Parameters:\n///\n/// * `message` : A string containing the error message to be displayed when\n/// aborting.\n///\n/// Returns a value of type `T`. However, this function never actually returns a\n/// value as it always causes a panic.\n#cfg(not(target=\"native\"))\npub fn[T] abort(msg : String) -> T {\n let _ = msg\n panic_impl()\n}\n\n///|\n#cfg(target=\"native\")\nfn println(s : String) -> Unit = \"%println\"\n\n///|\n/// Aborts the program with an error message. Always causes a panic, regardless\n/// of the message provided.\n///\n/// Parameters:\n///\n/// * `message` : A string containing the error message to be displayed when\n/// aborting.\n///\n/// Returns a value of type `T`. However, this function never actually returns a\n/// value as it always causes a panic.\n#cfg(target=\"native\")\npub fn[T] abort(msg : String) -> T {\n println(msg)\n panic_impl()\n}\n\n///|\nfn[T] panic_impl() -> T = \"%panic\"\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// JSON value type used by core serialization APIs.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let value : Json = Json::array([Json::number(1.0), Json::null()])\n/// inspect(value.stringify(), content=\"[1,null]\")\n/// }\n/// ```\npub enum Json {\n Null\n True\n False\n Number(Double, repr~ : String?) // 1.0000000000000000000e100 \n String(String)\n Array(Array[Json])\n Object(Map[String, Json])\n}\n\n///|\npub impl Eq for Json with equal(a, b) {\n match (a, b) {\n (Null, Null) => true\n (True, True) => true\n (False, False) => true\n (Number(a_num, ..), Number(b_num, ..)) => a_num == b_num\n (String(a_str), String(b_str)) => a_str == b_str\n (Array(a_arr), Array(b_arr)) => a_arr == b_arr\n (Object(a_obj), Object(b_obj)) => a_obj == b_obj\n _ => false\n }\n}\n\n///|\n/// Creates a JSON null value.\n///\n/// Returns a JSON value representing `null`.\npub fn Json::null() -> Json {\n return Null\n}\n\n///|\n/// JSON `null` constant.\n///\n/// Equivalent to `Json::null()`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(null.stringify(), content=\"null\")\n/// }\n/// ```\npub let null : Json = Null\n\n///|\n/// Creates a JSON number value from a double-precision floating-point number.\n///\n/// Parameters:\n///\n/// * `value` : A double-precision floating-point number to be converted to a\n/// JSON number.\n///\n/// Returns a JSON value representing the given number.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// @debug.debug_inspect(Json::number(3.14), content=\"Number(3.14)\")\n/// inspect(\n/// Json::number(@double.infinity, repr=\"1e9999999999999999999999999999999\").stringify(),\n/// content=\"1e9999999999999999999999999999999\",\n/// )\n/// }\n/// ```\npub fn Json::number(number : Double, repr? : String) -> Json {\n return Number(number, repr~)\n}\n\n///|\n/// Creates a JSON string value from a MoonBit string.\n///\n/// Parameters:\n///\n/// * `string` : A MoonBit string to be converted to a JSON string value.\n///\n/// Returns a JSON value representing the given string.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// @debug.debug_inspect(Json::string(\"hello\"), content=\"String(\\\"hello\\\")\")\n/// }\n/// ```\npub fn Json::string(string : String) -> Json {\n return String(string)\n}\n\n///|\n/// Creates a JSON boolean value from a MoonBit boolean.\n///\n/// Parameters:\n///\n/// * `boolean` : A MoonBit boolean to be converted to a JSON boolean value.\n///\n/// Returns a JSON value representing the given boolean.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// @debug.debug_inspect(Json::boolean(true), content=\"True\")\n/// @debug.debug_inspect(Json::boolean(false), content=\"False\")\n/// }\n/// ```\npub fn Json::boolean(boolean : Bool) -> Json {\n if boolean {\n True\n } else {\n False\n }\n}\n\n///|\n/// Creates a JSON array value from a MoonBit array.\n///\n/// Parameters:\n///\n/// * `values` : An array of JSON values to be converted to a JSON array value.\n///\n/// Returns a JSON value representing the given array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let values : Array[Json] = [1.0, \"hello\"]\n/// @debug.debug_inspect(\n/// Json::array(values),\n/// content=\"Array([Number(1), String(\\\"hello\\\")])\",\n/// )\n/// }\n/// ```\npub fn Json::array(array : Array[Json]) -> Json {\n return Array(array)\n}\n\n///|\n/// Creates a JSON object value from a MoonBit map.\n///\n/// Parameters:\n///\n/// * `map` : A map from strings to JSON values to be converted to a JSON object\n/// value.\n///\n/// Returns a JSON value representing the given map.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map : Map[String, Json] = { \"name\": \"John\", \"age\": 42.0 }\n/// @debug.debug_inspect(\n/// Json::object(map),\n/// content=\"Object({ \\\"name\\\": String(\\\"John\\\"), \\\"age\\\": Number(42) })\",\n/// )\n/// }\n/// ```\npub fn Json::object(object : Map[String, Json]) -> Json {\n return Object(object)\n}\n\n///|\n/// Trait for types that can be converted to `Json`\npub(open) trait ToJson {\n to_json(Self) -> Json\n}\n\n///|\npub impl ToJson for Bool with to_json(self : Bool) -> Json {\n if self {\n true\n } else {\n false\n }\n}\n\n///|\npub impl ToJson for Byte with to_json(self : Byte) -> Json {\n Json::number(self.to_double())\n}\n\n///|\npub impl ToJson for Int with to_json(self : Int) -> Json {\n Json::number(self.to_double())\n}\n\n///|\npub impl ToJson for Int64 with to_json(self : Int64) -> Json {\n String::to_json(self.to_string())\n}\n\n///|\npub impl ToJson for UInt with to_json(self : UInt) -> Json {\n Json::number(self.to_uint64().to_double())\n}\n\n///|\npub impl ToJson for UInt64 with to_json(self : UInt64) -> Json {\n String::to_json(self.to_string())\n}\n\n///|\npub impl ToJson for Double with to_json(self : Double) -> Json {\n if self != self {\n Json::string(\"NaN\")\n } else if self > 0x7FEFFFFFFFFFFFFFL.reinterpret_as_double() {\n Json::string(\"Infinity\")\n } else if self < 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double() {\n Json::string(\"-Infinity\")\n } else {\n Json::number(self)\n }\n}\n\n///|\npub impl ToJson for String with to_json(self : String) -> Json {\n String(self)\n}\n\n///|\npub impl[X : ToJson] ToJson for Array[X] with to_json(self) {\n Array(self.map(x => x.to_json()))\n}\n\n///|\npub impl[X : ToJson] ToJson for FixedArray[X] with to_json(self) {\n let len = self.length()\n if len == 0 {\n return []\n }\n let res = Array::make_uninit(self.length())\n for i, x in self {\n res.unsafe_set(i, ToJson::to_json(x))\n }\n Array(res)\n}\n\n///|\npub impl[X : ToJson] ToJson for ArrayView[X] with to_json(self) {\n let len = self.length()\n if len == 0 {\n return []\n }\n let res = Array::make_uninit(self.length())\n for i, x in self {\n res.unsafe_set(i, ToJson::to_json(x))\n }\n Array(res)\n}\n\n///|\npub impl[K : Show, V : ToJson] ToJson for Map[K, V] with to_json(self) {\n let object = Map([], capacity=self.capacity)\n for k, v in self {\n object[k.to_string()] = v.to_json()\n }\n Object(object)\n}\n\n///|\npub impl[T : ToJson] ToJson for T? with to_json(self) {\n match self {\n None => Null\n Some(value) => [value]\n }\n}\n\n///|\npub impl[Ok : ToJson, Err : ToJson] ToJson for Result[Ok, Err] with to_json(\n self : Result[Ok, Err],\n) -> Json {\n match self {\n Ok(ok) => { \"Ok\": ok }\n Err(err) => { \"Err\": err }\n }\n}\n\n//| unit\n\n///|\npub impl ToJson for Unit with to_json(_self) {\n Null\n}\n\n///|\npub impl Default for Json with default() {\n false\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Trait for types whose elements can test for equality\npub(open) trait Eq {\n equal(Self, Self) -> Bool\n not_equal(Self, Self) -> Bool = _\n}\n\n///|\nimpl Eq with not_equal(x, y) {\n !(x == y)\n}\n\n///|\n/// Trait for types whose elements are ordered\n///\n/// The return value of [compare] is:\n/// - zero, if the two arguments are equal\n/// - negative, if the first argument is smaller\n/// - positive, if the first argument is greater\npub(open) trait Compare: Eq {\n compare(Self, Self) -> Int\n op_lt(Self, Self) -> Bool = _\n op_gt(Self, Self) -> Bool = _\n op_le(Self, Self) -> Bool = _\n op_ge(Self, Self) -> Bool = _\n}\n\n///|\nimpl Compare with op_lt(x, y) {\n x.compare(y).is_neg()\n}\n\n///|\nimpl Compare with op_gt(x, y) {\n x.compare(y).is_pos()\n}\n\n///|\nimpl Compare with op_le(x, y) {\n x.compare(y).is_non_pos()\n}\n\n///|\nimpl Compare with op_ge(x, y) {\n x.compare(y).is_non_neg()\n}\n\n///|\n/// Trait for types that can be hashed\n/// \n/// The `hash` method should return a hash value for the type, which is used in hash tables and other data structures.\n/// The `hash_combine` method is used to combine the hash of the current value with another hash value,\n/// typically used to hash composite types.\n/// \n/// When two values are equal according to the `Eq` trait, they should produce the same hash value.\n/// \n/// The `hash` method does not need to be implemented if `hash_combine` is implemented,\n/// When implemented separately, `hash` **does not need** to produce a hash value that is consistent with `hash_combine`.\npub(open) trait Hash {\n hash_combine(Self, Hasher) -> Unit\n hash(Self) -> Int = _\n}\n\n///|\nimpl Hash with hash(self) {\n let h = Hasher::new()\n h.combine(self)\n h.finalize()\n}\n\n///|\n/// Trait for types with a default value\npub(open) trait Default {\n default() -> Self\n}\n\n///|\n/// Trait for append-only text sinks used by `Show` implementations.\n///\n/// A logger receives formatted output without requiring callers to allocate a\n/// complete `String` first.\npub(open) trait Logger {\n /// Writes a string to the logger.\n write_string(Self, String) -> Unit = _\n /// Writes a substring of the given string to the logger.\n #deprecated(\"use `write_view` instead\", skip_current_package=true)\n write_substring(Self, String, Int, Int) -> Unit = _\n /// Writes a string view to the logger.\n write_view(Self, StringView) -> Unit = _\n /// Writes a character to the logger.\n write_char(Self, Char) -> Unit = _\n write(Self, &Show) -> Unit = _\n}\n\n///|\nimpl Logger with write(self, show) {\n show.output(self)\n}\n\n///|\n/// Writes a substring of the given string to the logger.\nimpl Logger with write_substring(self, value, start, len) {\n self.write_view(value[start:start + len])\n}\n\n///|\n/// Writes a string to the logger.\nimpl Logger with write_string(self, value) {\n self.write_view(value)\n}\n\n///|\n/// Writes a string view to the logger.\n#deprecated(\"replace `impl write_substring` with `impl write_view`\")\nimpl Logger with write_view(self, value) {\n self.write_substring(value.data(), value.start_offset(), value.length())\n}\n\n///|\n/// Writes a character to the logger.\nimpl Logger with write_char(self, value) {\n self.write_string([value])\n}\n\n///|\n/// Trait for types that can be converted to `String`\n#must_implement_one(output, to_string)\npub(open) trait Show {\n // `output` writes a string representation of `self` to a logger.\n // The behaviors of output and to_string should be the same.\n output(Self, &Logger) -> Unit = _\n // `to_string` should be used by end users of `Show`,\n // for printing, interpolation, etc. only, and should not be used for composition.\n to_string(Self) -> String = _\n}\n\n///|\n/// Default implementation for `Show::output`, uses `Show::to_string`.\nimpl Show with output(self, logger) {\n logger.write_string(self.to_string())\n}\n\n///|\n/// Default implementation for `Show::to_string`, uses a `StringBuilder`\nimpl Show with to_string(self) {\n let logger = StringBuilder()\n self.output(logger)\n logger.to_string()\n}\n\n///|\n/// Writes the `Show` representation of an object to the logger.\npub fn[Obj : Show] &Logger::write_object(self : &Logger, obj : Obj) -> Unit {\n obj.output(self)\n}\n\n///|\n/// Writes an iterator of `Show` values to the logger.\n///\n/// By default, values are written in list form, such as `[1, 2]`. The\n/// `prefix`, `suffix`, and `sep` arguments customize the surrounding text and\n/// separator. If `trailing` is true, `sep` is also written after the last value.\npub fn[T : Show] &Logger::write_iter(\n self : &Logger,\n iter : Iter[T],\n prefix? : String = \"[\",\n suffix? : String = \"]\",\n sep? : String = \", \",\n trailing? : Bool = false,\n) -> Unit {\n self.write_string(prefix)\n if trailing {\n for x in iter {\n self.write_object(x)\n self.write_string(sep)\n }\n } else if iter.next() is Some(x) {\n self.write_object(x)\n for x in iter {\n self.write_string(sep)\n self.write_object(x)\n }\n }\n self.write_string(suffix)\n}\n// TODO: Logger::write_double(self:Logger, val:Double) -> Unit\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nstruct StringBuilder {\n mut val : String\n}\n\n///|\n/// Creates a new string builder with an optional initial capacity hint.\n///\n/// Parameters:\n///\n/// * `size_hint` : An optional initial capacity hint for the internal buffer. If\n/// less than 1, a minimum capacity of 1 is used. Defaults to 0. It is the size of bytes, \n/// not the size of characters. `size_hint` may be ignored on some platforms, JS for example.\n///\n/// Returns a new `StringBuilder` instance with the specified initial capacity.\n///\n#alias(new)\npub fn StringBuilder::StringBuilder(size_hint? : Int = 0) -> StringBuilder {\n ignore(size_hint)\n { val: \"\" }\n}\n\n///|\n/// Return whether the given buffer is empty.\npub fn StringBuilder::is_empty(self : StringBuilder) -> Bool {\n self.val == \"\"\n}\n\n///|\n/// Writes a string to the StringBuilder.\npub impl Logger for StringBuilder with write_string(self, str) {\n self.val += str\n}\n\n///|\n/// Writes a character to the StringBuilder.\npub impl Logger for StringBuilder with write_char(self, ch) {\n self.val += char_to_string(ch)\n}\n\n///|\n/// Writes a part of the given string to the StringBuilder.\n/// \n/// Parameters:\n///\n/// * `self` : The StringBuilder to write to.\n/// * `str` : The given string.\n/// * `start` : The start index of the substring to write.\n/// * `len` : The length of the substring to write.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sb = StringBuilder()\n/// sb.write_view(\"Hello, world!\"[:5])\n/// assert_eq(sb.to_string(), \"Hello\")\n/// }\n/// ```\npub impl Logger for StringBuilder with write_view(\n self : StringBuilder,\n str : StringView,\n) -> Unit {\n self.val += str.to_owned()\n}\n\n///|\npub impl Show for StringBuilder with output(self, logger) {\n logger.write_string(self.val)\n}\n\n///|\n/// Returns the current content of the StringBuilder as a string.\npub fn StringBuilder::to_string(self : StringBuilder) -> String {\n self.val\n}\n\n///|\n/// Resets the string builder to an empty state.\npub fn StringBuilder::reset(self : StringBuilder) -> Unit {\n self.val = \"\"\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Checks if the integer value represents a UTF-16 leading surrogate.\n/// Leading surrogates are in the range 0xD800 to 0xDBFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xD800 : UInt16).is_leading_surrogate(), content=\"true\")\n/// inspect((0xDBFF : UInt16).is_leading_surrogate(), content=\"true\")\n/// inspect((0xDC00 : UInt16).is_leading_surrogate(), content=\"false\")\n/// inspect((0x41 : UInt16).is_leading_surrogate(), content=\"false\") // 'A'\n/// }\n/// ```\npub fn UInt16::is_leading_surrogate(self : Self) -> Bool {\n self >= 0xD800 && self <= 0xDBFF\n}\n\n///|\n/// Checks if the integer value represents a UTF-16 trailing surrogate.\n/// Trailing surrogates are in the range 0xDC00 to 0xDFFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xDC00 : UInt16).is_trailing_surrogate(), content=\"true\")\n/// inspect((0xDFFF : UInt16).is_trailing_surrogate(), content=\"true\")\n/// inspect((0xD800 : UInt16).is_trailing_surrogate(), content=\"false\")\n/// inspect((0x41 : UInt16).is_trailing_surrogate(), content=\"false\") // 'A'\n/// }\n/// ```\npub fn UInt16::is_trailing_surrogate(self : Self) -> Bool {\n self >= 0xDC00 && self <= 0xDFFF\n}\n\n///|\n/// Checks if the integer value represents any UTF-16 surrogate (leading or trailing).\n/// Surrogates are in the range 0xD800 to 0xDFFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xD800 : UInt16).is_surrogate(), content=\"true\") // leading surrogate\n/// inspect((0xDC00 : UInt16).is_surrogate(), content=\"true\") // trailing surrogate\n/// inspect((0xDFFF : UInt16).is_surrogate(), content=\"true\") // trailing surrogate\n/// inspect((0x41 : UInt16).is_surrogate(), content=\"false\") // 'A'\n/// }\n/// ```\npub fn UInt16::is_surrogate(self : Self) -> Bool {\n self >= 0xD800 && self <= 0xDFFF\n}\n\n///|\n/// Unsafe variant of `to_char`.\npub fn UInt16::unsafe_to_char(self : UInt16) -> Char {\n self.to_int().unsafe_to_char()\n}\n\n///|\n/// Convert to `char`.\npub fn UInt16::to_char(self : UInt16) -> Char? {\n if self is (0..=0xD7FF) || self is (0xE000..<_) {\n Some(self.unsafe_to_char())\n } else {\n None\n }\n}\n\n///|\npub impl Add for UInt16 with add(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() + that.to_int()).to_uint16()\n}\n\n///|\npub impl Sub for UInt16 with sub(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() - that.to_int()).to_uint16()\n}\n\n///|\npub impl Mul for UInt16 with mul(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() * that.to_int()).to_uint16()\n}\n\n///|\npub impl Div for UInt16 with div(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() / that.to_int()).to_uint16()\n}\n\n///|\npub impl Mod for UInt16 with mod(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() % that.to_int()).to_uint16()\n}\n\n///|\npub impl Eq for UInt16 with equal(self, that) {\n self.to_int() == that.to_int()\n}\n\n///|\npub impl Eq for UInt16 with not_equal(self, that) {\n self.to_int() != that.to_int()\n}\n\n///|\npub impl Compare for UInt16 with compare(self, that) {\n self.to_int().compare(that.to_int())\n}\n\n///|\npub impl Hash for UInt16 with hash_combine(self, hasher) {\n hasher.combine_int(self.to_int())\n}\n\n///|\npub impl Shl for UInt16 with shl(self : UInt16, that : Int) -> UInt16 {\n (self.to_int() << that).to_uint16()\n}\n\n///|\npub impl Shr for UInt16 with shr(self : UInt16, that : Int) -> UInt16 {\n (self.to_int() >> that).to_uint16()\n}\n\n///|\npub impl BitOr for UInt16 with lor(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() | that.to_int()).to_uint16()\n}\n\n///|\npub impl BitAnd for UInt16 with land(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() & that.to_int()).to_uint16()\n}\n\n///|\npub impl BitXOr for UInt16 with lxor(self : UInt16, that : UInt16) -> UInt16 {\n (self.to_int() ^ that.to_int()).to_uint16()\n}\n\n///|\npub impl Default for UInt16 with default() {\n 0\n}\n\n///|\npub impl ToJson for UInt16 with to_json(self : UInt16) -> Json {\n Json::number(self.to_int().to_double())\n}\n\n///|\n/// Convert to `uint`.\npub fn UInt16::to_uint(self : UInt16) -> UInt {\n self.to_int().reinterpret_as_uint()\n}\n\n///|\n/// Convert to `uint64`.\npub fn UInt16::to_uint64(self : UInt16) -> UInt64 {\n self.to_int().to_uint64()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn unsafe_make_string(length : Int, value : Char) -> String = \"$moonbit.unsafe_make_string\"\n\n///|\n/// Create new string of `length`, where each character is `value`\n///\n/// ```mbt check\n/// test {\n/// assert_eq(String::make(5, 'S'), \"SSSSS\")\n/// }\n/// ```\npub fn String::make(length : Int, value : Char) -> String {\n guard length >= 0 else { abort(\"invalid length\") }\n if value.to_int() <= 0xFFFF {\n unsafe_make_string(length, value)\n } else {\n let buf = StringBuilder(size_hint=2 * length)\n for _ in 0..<length {\n buf.write_char(value)\n }\n buf.to_string()\n }\n}\n\n///|\nfn code_point_of_surrogate_pair(leading : Int, trailing : Int) -> Char {\n ((leading - 0xD800) * 0x400 + trailing - 0xDC00 + 0x10000).unsafe_to_char()\n}\n\n///|\n/// Returns the number of Unicode code points (characters) in the string.\n///\n/// This method counts actual Unicode characters, properly handling surrogate pairs\n/// that represent single characters like emojis. For the raw UTF-16 code unit count,\n/// use `length()` instead.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let s = \"Hello🤣\"\n/// inspect(s.char_length(), content=\"6\") // 6 actual characters\n/// inspect(s.length(), content=\"7\")\n/// } // 5 ASCII chars + 2 surrogate pairs\n/// ```\n#alias(codepoint_length, deprecated)\npub fn String::char_length(\n self : String,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> Int {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n guard start_offset >= 0 &&\n start_offset <= end_offset &&\n end_offset <= self.length() else {\n abort(\"invalid start or end index for String::codepoint_length\")\n }\n for utf16_index = start_offset, char_count = 0\n utf16_index < end_offset\n utf16_index = utf16_index + 1, char_count = char_count + 1 {\n let c1 = self.unsafe_get(utf16_index)\n if c1.is_leading_surrogate() && utf16_index + 1 < end_offset {\n let c2 = self.unsafe_get(utf16_index + 1)\n if c2.is_trailing_surrogate() {\n continue utf16_index + 2, char_count + 1\n } else {\n abort(\"invalid surrogate pair\")\n }\n }\n } nobreak {\n char_count\n }\n}\n\n///|\n/// Unsafe variant of `substring`.\n#intrinsic(\"%string.substring\")\npub fn String::unsafe_substring(\n str : String,\n start~ : Int,\n end~ : Int,\n) -> String {\n if start == 0 && end == str.length() {\n return str\n }\n let len = end - start\n let bytes = FixedArray::make(len * 2, Byte::default())\n bytes.blit_from_string(0, str, start, len)\n bytes.unsafe_reinterpret_as_bytes().to_unchecked_string()\n}\n\n///|\n/// Returns a new string containing characters from the original string starting\n/// at `start` index up to (but not including) `end` index.\n///\n/// Parameters:\n///\n/// * `string` : The source string from which to extract the substring.\n/// * `start` : The starting index of the substring (inclusive). Defaults to 0.\n/// * `end` : The ending index of the substring (exclusive). Defaults to the\n/// length of the string.\n///\n/// Returns a new string containing the specified substring.\n///\n#deprecated(\"Use `str[:]` or `str[:].to_string()` instead\", skip_current_package=true)\npub fn String::substring(self : String, start? : Int = 0, end? : Int) -> String {\n let len = self.length()\n let end = match end {\n Some(end) => end\n None => len\n }\n guard start >= 0 && start <= end && end <= len\n self.unsafe_substring(start~, end~)\n}\n\n///|\n/// Iterates over all suffixes of the string as views that reuse the\n/// original storage. Surrogate pairs stay intact while advancing.\npub fn String::suffixes(\n self : String,\n include_empty? : Bool = false,\n) -> Iter[StringView] {\n self[:].suffixes(include_empty~)\n}\n\n///|\ntest \"substring/empty\" {\n let s = \"test\"\n inspect(s.substring(start=2, end=2), content=\"\")\n inspect(s.substring(start=4, end=4), content=\"\")\n inspect(\"\".substring(), content=\"\")\n}\n\n///|\ntest \"panic substring/invalid_range\" {\n let s = \"test\"\n ignore(s.substring(start=-1))\n ignore(s.substring(end=5))\n ignore(s.substring(start=3, end=2))\n}\n\n///|\ntest \"substring/basic\" {\n inspect(\"Hello world\".substring(start=0, end=5), content=\"Hello\")\n inspect(\"Hello world\".substring(start=6, end=11), content=\"world\")\n inspect(\"Hello world\".substring(start=0), content=\"Hello world\")\n inspect(\"Hello world\".substring(start=6), content=\"world\")\n}\n\n///|\ntest \"substring/boundary\" {\n inspect(\"\".substring(start=0, end=0), content=\"\")\n inspect(\"a\".substring(start=0, end=1), content=\"a\")\n inspect(\"abc\".substring(start=0), content=\"abc\")\n inspect(\"abc\".substring(start=1), content=\"bc\")\n inspect(\"abc\".substring(start=0, end=3), content=\"abc\")\n}\n\n///|\ntest \"panic substring/out_of_bounds\" {\n ignore(\"hello\".substring(start=-1, end=4))\n ignore(\"hello\".substring(start=6, end=4))\n ignore(\"hello\".substring(start=0, end=6))\n}\n\n///|\n/// Strings are ordered based on shortlex order by their charcodes (code units). This \n/// orders Unicode characters based on their positions in the code charts. This is\n/// not necessarily the same as \"alphabetical\" order, which varies by language\n/// and locale.\npub impl Compare for String with compare(self, other) {\n let len = self.length()\n match len.compare(other.length()) {\n 0 => {\n for i in 0..<len {\n let order = self.unsafe_get(i).compare(other.unsafe_get(i))\n if order != 0 {\n return order\n }\n }\n 0\n }\n order => order\n }\n}\n\n///|\n/// The empty string\npub impl Default for String with default() {\n \"\"\n}\n\n///|\n/// `String` holds a sequence of UTF-16 code units encoded in little endian format\n#deprecated(\"Check `@encoding/utf8.encode`\")\npub fn String::to_bytes(self : String) -> Bytes {\n let array = FixedArray::make(self.length() * 2, Byte::default())\n array.blit_from_string(0, self, 0, self.length())\n array |> unsafe_to_bytes\n}\n\n///|\nfn unsafe_to_bytes(array : FixedArray[Byte]) -> Bytes = \"%identity\"\n\n///|\n/// Converts the String into an array of Chars.\npub fn String::to_array(self : String) -> Array[Char] {\n self\n .iter()\n .fold(init=Array::new(capacity=self.length()), (rv, c) => {\n rv.push(c)\n rv\n })\n}\n\n///|\n/// Returns an iterator over the Unicode characters in the string.\n///\n/// Note: This iterator yields Unicode characters, not Utf16 code units.\n/// As a result, the count of characters returned by `iterator().count()` may not be equal to the length of the string returned by `length()`.\n///\n/// ```mbt check\n/// test {\n/// let s = \"Hello, World!🤣\"\n/// assert_eq(s.iter().count(), 14) // Unicode characters\n/// assert_eq(s.length(), 15)\n/// } // Utf16 code units\n/// ```\n#alias(iterator, deprecated)\npub fn String::iter(self : String) -> Iter[Char] {\n let len = self.length()\n let mut index = 0\n Iter::new(fn() {\n guard index < len else { None }\n let c1 = self.unsafe_get(index)\n if c1.is_leading_surrogate() && index + 1 < len {\n let c2 = self.unsafe_get(index + 1)\n if c2.is_trailing_surrogate() {\n let c = code_point_of_surrogate_pair(c1.to_int(), c2.to_int())\n index += 2\n return Some(c)\n }\n }\n index += 1\n //TODO: handle garbage input\n Some(c1.unsafe_to_char())\n })\n}\n\n///|\n/// Return an iterator via `iter2`.\n#alias(iterator2, deprecated)\npub fn String::iter2(self : String) -> Iter2[Int, Char] {\n self.iter().iter2()\n}\n\n///|\n/// Returns an iterator that yields characters from the end to the start of the string. This function handles\n/// Unicode surrogate pairs correctly, ensuring that characters are not split across surrogate pairs.\n///\n/// # Parameters\n///\n/// - `self` : The input `String` to be iterated in reverse.\n///\n/// # Returns\n///\n/// - An `Iter[Char]` that yields characters from the end to the start of the string.\n///\n/// # Behavior\n///\n/// - The function iterates over the string in reverse order.\n/// - If a trailing surrogate is encountered, it checks for a preceding leading surrogate to form a complete Unicode code point.\n/// - Yields each character or combined code point to the iterator.\n/// - Stops iteration if the `yield_` function returns `IterEnd`.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let input = \"Hello, World!\"\n/// let reversed = input.rev_iter().collect()\n/// assert_eq(reversed, [\n/// '!', 'd', 'l', 'r', 'o', 'W', ' ', ',', 'o', 'l', 'l', 'e', 'H',\n/// ])\n/// }\n/// ```\n#alias(rev_iterator, deprecated)\npub fn String::rev_iter(self : String) -> Iter[Char] {\n let len = self.length()\n let mut index = len\n Iter::new(fn() {\n guard index > 0 else { None }\n index -= 1\n let c1 = self.unsafe_get(index)\n if c1.is_trailing_surrogate() && index - 1 >= 0 {\n let c2 = self.unsafe_get(index - 1)\n if c2.is_leading_surrogate() {\n index -= 1\n return Some(code_point_of_surrogate_pair(c2.to_int(), c1.to_int()))\n }\n }\n Some(c1.unsafe_to_char())\n })\n}\n\n///|\n/// Returns the index of the n-th (zero-indexed) character within the range [start, end).\nfn String::offset_of_nth_char_forward(\n self : String,\n n : Int,\n start_offset~ : Int,\n end_offset~ : Int,\n) -> Int? {\n guard start_offset >= 0 && start_offset <= end_offset else {\n abort(\"Invalid start index\")\n }\n let (utf16_offset, char_count) = for utf16_offset = start_offset, char_count = 0; utf16_offset <\n end_offset &&\n char_count < n; {\n let c = self.unsafe_get(utf16_offset)\n // check if this is a surrogate pair\n if c.is_leading_surrogate() {\n continue utf16_offset + 2, char_count + 1\n } else {\n continue utf16_offset + 1, char_count + 1\n }\n } nobreak {\n (utf16_offset, char_count)\n }\n // Return None if either:\n // 1. We couldn't reach the requested character offset\n // 2. The resulting offset is beyond the end of the string\n // This handles the empty string case correctly.\n if char_count < n || utf16_offset >= end_offset {\n None\n } else {\n Some(utf16_offset)\n }\n}\n\n///|\n/// Returns the index of the n-th (zero-indexed) character within the range [start, end).\n/// self[end] is counted as the 0-th character (though it might not exist if end = self.length()).\nfn String::offset_of_nth_char_backward(\n self : String,\n n : Int,\n start_offset~ : Int,\n end_offset~ : Int,\n) -> Int? {\n // Iterating backwards from the end of the string.\n // Invariant: utf16_offset always points to the previous character\n let (utf16_offset, char_count) = for utf16_offset = end_offset, char_count = 0; utf16_offset -\n 1 >=\n start_offset &&\n char_count < n; {\n let c = self.unsafe_get(utf16_offset - 1)\n if c.is_trailing_surrogate() {\n continue utf16_offset - 2, char_count + 1\n } else {\n continue utf16_offset - 1, char_count + 1\n }\n } nobreak {\n (utf16_offset, char_count)\n }\n if char_count < n || utf16_offset < start_offset {\n None\n } else {\n Some(utf16_offset)\n }\n}\n\n///|\n/// Returns the UTF-16 index of the i-th (zero-indexed) Unicode character \n/// within the range [start, end). If i is negative, it returns the index of \n/// the (n + i)-th character where n is the number of Unicode characters \n/// in the range [start, end).\n/// \n/// This functions assumes that the string is valid UTF-16.\npub fn String::offset_of_nth_char(\n self : String,\n i : Int,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> Int? {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n if i >= 0 {\n // forward case\n self.offset_of_nth_char_forward(i, start_offset~, end_offset~)\n } else {\n // backward case\n self.offset_of_nth_char_backward(-i, start_offset~, end_offset~)\n }\n}\n\n///|\n/// Test if the length of the string is equal to the given length.\n///\n/// This has O(n) complexity where n is the length in the parameter.\npub fn String::char_length_eq(\n self : String,\n len : Int,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> Bool {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n for index = start_offset, count = 0\n index < end_offset && count < len\n index = index + 1, count = count + 1 {\n let c1 = self.unsafe_get(index)\n if c1.is_leading_surrogate() && index + 1 < end_offset {\n let c2 = self.unsafe_get(index + 1)\n if c2.is_trailing_surrogate() {\n continue index + 2, count + 1\n } else {\n abort(\"invalid surrogate pair\")\n }\n }\n } nobreak {\n count == len && index == end_offset\n }\n}\n\n///|\n/// Test if the length of the string is greater than or equal to the given length.\n///\n/// This has O(n) complexity where n is the length in the parameter.\npub fn String::char_length_ge(\n self : String,\n len : Int,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> Bool {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n for index = start_offset, count = 0\n index < end_offset && count < len\n index = index + 1, count = count + 1 {\n let c1 = self.unsafe_get(index)\n if c1.is_leading_surrogate() && index + 1 < end_offset {\n let c2 = self.unsafe_get(index + 1)\n if c2.is_trailing_surrogate() {\n continue index + 2, count + 1\n } else {\n abort(\"invalid surrogate pair\")\n }\n }\n } nobreak {\n count >= len\n }\n}\n\n///|\n/// Performs a lexicographical comparison of two strings.\n///\n/// This method compares the strings character by character (UTF-16 code unit by code unit),\n/// similar to Java's `String.compareTo()`. Unlike the `Compare` trait implementation which\n/// uses shortlex order (shorter strings come first), this method compares based purely on\n/// character values until a difference is found or one string is exhausted.\n///\n/// # Returns\n///\n/// - A negative integer if `self` is lexicographically less than `other`\n/// - Zero if `self` is lexicographically equal to `other`\n/// - A positive integer if `self` is lexicographically greater than `other`\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect(\"ab\".lexical_compare(\"abc\"), content=\"-1\")\n/// inspect(\"abc\".lexical_compare(\"ab\"), content=\"1\")\n/// inspect(\"abc\".lexical_compare(\"abc\"), content=\"0\")\n/// inspect(\"abc\".lexical_compare(\"abd\"), content=\"-1\")\n/// }\n/// ```\n///\n/// # Note\n///\n/// Since MoonBit strings are UTF-16 encoded (like Java), this comparison operates on\n/// UTF-16 code units, not Unicode code points. Surrogate pairs (used for characters\n/// outside the Basic Multilingual Plane) are compared as individual code units.\npub fn String::lexical_compare(self : String, other : String) -> Int {\n self[:].lexical_compare(other)\n}\n\n///|\n/// Performs a lexicographical comparison of two strings, treating ASCII\n/// letters as case-insensitive.\n///\n/// Each pair of UTF-16 code units is compared after folding ASCII `'A'..'Z'`\n/// onto `'a'..'z'`. Non-ASCII code units are compared by their raw value, so\n/// this function does **not** perform Unicode case folding (e.g. `'Ä'` and\n/// `'ä'` are still considered different). Use this when you only need to\n/// match ASCII identifiers, headers, file extensions, or similar protocol\n/// text — not for human-language text where locale-dependent folding matters.\n///\n/// Aside from case folding, the semantics match `lexical_compare`: characters\n/// are compared one by one and, when one string is a prefix of the other, the\n/// shorter string is considered less. The result is independent of which\n/// string is `self`.\n///\n/// # Returns\n///\n/// - A negative integer if `self` is less than `other`\n/// - Zero if `self` is equal to `other` under ASCII case folding\n/// - A positive integer if `self` is greater than `other`\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect(\"Hello\".compare_ignore_ascii_case(\"hello\"), content=\"0\")\n/// inspect(\"ABC\".compare_ignore_ascii_case(\"abd\"), content=\"-1\")\n/// inspect(\"abc\".compare_ignore_ascii_case(\"AB\"), content=\"1\")\n/// // Non-ASCII letters are NOT folded\n/// inspect(\"Ä\".compare_ignore_ascii_case(\"ä\") != 0, content=\"true\")\n/// }\n/// ```\npub fn String::compare_ignore_ascii_case(self : String, other : String) -> Int {\n self[:].compare_ignore_ascii_case(other)\n}\n\n///|\n/// Tests two strings for equality, treating ASCII letters as case-insensitive.\n///\n/// ASCII `'A'..'Z'` are folded onto `'a'..'z'` before comparison; all other\n/// code units (including non-ASCII letters like `'Ä'`) are compared by their\n/// raw UTF-16 value. Use this for ASCII-only protocol text — HTTP headers,\n/// file extensions, identifiers — not for human-language text where Unicode\n/// case folding matters.\n///\n/// Equivalent to `self.compare_ignore_ascii_case(other) == 0` but short-\n/// circuits on length mismatch and on the first differing code unit, so it\n/// is preferred when only equality is needed.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect(\"Hello\".equal_ignore_ascii_case(\"hello\"), content=\"true\")\n/// inspect(\"Hello\".equal_ignore_ascii_case(\"world\"), content=\"false\")\n/// inspect(\"abc\".equal_ignore_ascii_case(\"ab\"), content=\"false\")\n/// // Non-ASCII letters are NOT folded\n/// inspect(\"Ä\".equal_ignore_ascii_case(\"ä\"), content=\"false\")\n/// }\n/// ```\npub fn String::equal_ignore_ascii_case(self : String, other : String) -> Bool {\n self[:].equal_ignore_ascii_case(other)\n}\n\n///|\n/// Convert char array to string.\n///\n/// ```mbt check\n/// test {\n/// let s = String::from_array(['H', 'e', 'l', 'l', 'o'])\n/// assert_eq(s, \"Hello\")\n/// }\n/// ```\n///\n/// Do not convert large data to `Array[Char]` and build a string with `String::from_array`.\n///\n/// For efficiency considerations, it's recommended to use `Buffer` instead.\npub fn String::from_array(chars : ArrayView[Char]) -> String {\n let buf = StringBuilder(size_hint=chars.length() * 4)\n for c in chars {\n buf.write_char(c)\n }\n buf.to_string()\n}\n\n///|\n/// Convert char iterator to string,\n#alias(from_iterator, deprecated)\npub fn String::from_iter(iter : Iter[Char]) -> String {\n let buf = StringBuilder()\n for c in iter {\n buf.write_char(c)\n }\n buf.to_string()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Encode a UTF-16 string into raw bytes.\n///\n/// Deprecated: use `@encoding/utf8.encode` for text encoding.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = Bytes::from_array([b'A'])\n/// inspect(bytes.length(), content=\"1\")\n/// }\n/// ```\n#deprecated(\"check `@encoding/utf8.encode`\")\n#coverage.skip\npub fn Bytes::of_string(str : String) -> Bytes {\n let arr = FixedArray::make(str.length() * 2, Byte::default())\n arr.blit_from_string(0, str, 0, str.length())\n arr.unsafe_reinterpret_as_bytes()\n}\n\n///|\n/// Return a copied `Bytes` value.\n///\n/// Deprecated because `Bytes` is immutable and copying is usually unnecessary.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = b\"abc\"\n/// let b = Bytes::makei(a.length(), i => a[i])\n/// inspect(a == b, content=\"true\")\n/// }\n/// ```\n#deprecated(\"Bytes are immutable. Use `FixedArray::blit_from_bytes` if it's really necessary.\")\n#alias(clone, deprecated)\npub fn Bytes::copy(self : Bytes) -> Bytes {\n Bytes::makei(self.length(), i => self[i])\n}\n\n///|\n/// Create a hash map.\n/// The capacity of the map will be the smallest power of 2 that is\n/// greater than or equal to the provided [capacity].\n///\n/// Deprecated: use `Map([], capacity=...)` instead.\n#deprecated(\"Use `Map([], capacity=...)` instead\")\npub fn[K, V] Map::new(capacity? : Int = default_init_capacity) -> Map[K, V] {\n new_map(capacity)\n}\n\n///|\n/// positions.\n///\n/// Parameters:\n///\n/// - `byte_value` : The `Byte` value whose bits are to be shifted.\n/// - `shift_count` : The number of bit positions to shift the `byte_value` to\n/// the left.\n///\n/// Returns the resulting `Byte` value after the bitwise left shift operation.\n///\n#deprecated(\"Use infix operator `<<` instead\")\n#coverage.skip\npub fn Byte::lsl(self : Byte, count : Int) -> Byte {\n (self.to_int() << count).to_byte()\n}\n\n///|\n/// bits.\n///\n/// Parameters:\n///\n/// - `value` : The `Byte` value to be shifted.\n/// - `count` : The number of bits to shift the `value` to the right.\n///\n/// Returns the result of the logical shift right operation as a `Byte`.\n///\n#deprecated(\"Use infix operator `>>` instead\")\n#coverage.skip\npub fn Byte::lsr(self : Byte, count : Int) -> Byte {\n (self.to_uint() >> count).reinterpret_as_int().to_byte()\n}\n\n///|\n/// Returns the Unicode code point at the given index without bounds checking.\n#deprecated(\"Use `s.get_char(i).unwrap()` instead\", skip_current_package=true)\npub fn String::unsafe_char_at(self : String, index : Int) -> Char {\n let c1 = self.unsafe_get(index)\n if c1.is_leading_surrogate() {\n let c2 = self.unsafe_get(index + 1)\n code_point_of_surrogate_pair(c1.to_int(), c2.to_int())\n } else {\n c1.unsafe_to_char()\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Performs multiplication between two byte values. The result is truncated to\n/// fit within the byte range.\n///\n/// Parameters:\n///\n/// * `self` : The first byte operand in the multiplication.\n/// * `that` : The second byte operand in the multiplication.\n///\n/// Returns the product of the two bytes, truncated to fit within the byte range\n/// (0-255).\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = b'\\x02'\n/// let b = b'\\x03'\n/// inspect(a * b, content=\"b'\\\\x06'\") // 2 * 3 = 6\n/// let c = b'\\xFF'\n/// inspect(c * c, content=\"b'\\\\x01'\") // 255 * 255 = 65025, truncated to 1\n/// }\n/// ```\npub impl Mul for Byte with mul(self : Byte, that : Byte) -> Byte {\n (self.to_int() * that.to_int()).to_byte()\n}\n\n///|\n/// Performs division operation between two bytes by converting them to integers,\n/// performing the division, and converting the result back to a byte.\n///\n/// Parameters:\n///\n/// * `self` : The dividend byte value.\n/// * `that` : The divisor byte value.\n///\n/// Returns the quotient of the division as a byte.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = b'\\xFF' // 255\n/// let b = b'\\x03' // 3\n/// inspect(a / b, content=\"b'\\\\x55'\") // 255 / 3 = 85 (0x55)\n/// }\n/// ```\npub impl Div for Byte with div(self : Byte, that : Byte) -> Byte {\n (self.to_int() / that.to_int()).to_byte()\n}\n\n///|\npub impl Mod for Byte with mod(self : Byte, that : Byte) -> Byte {\n (self.to_int() % that.to_int()).to_byte()\n}\n\n///|\n/// Compares two `Byte` values for equality.\n///\n/// Parameters:\n///\n/// - `self` : The first `Byte` value to compare.\n/// - `that` : The second `Byte` value to compare.\n///\n/// Returns `true` if the two `Byte` values are equal, otherwise `false`.\npub impl Eq for Byte with equal(self : Byte, that : Byte) -> Bool {\n self.to_int() == that.to_int()\n}\n\n///|\n/// Compares two `Byte` values for inequality.\n///\n/// Parameters:\n///\n/// - `self` : The first `Byte` value to compare.\n/// - `that` : The second `Byte` value to compare.\n///\n/// Returns `true` if the two `Byte` values are not equal, otherwise `false`.\npub impl Eq for Byte with not_equal(self : Byte, that : Byte) -> Bool {\n self.to_int() != that.to_int()\n}\n\n///|\n/// Adds two `Byte` values together and returns the result as a `Byte`.\n///\n/// Parameters:\n///\n/// - `byte1` : The first `Byte` value to be added.\n/// - `byte2` : The second `Byte` value to be added.\n///\n/// Returns the sum of `byte1` and `byte2` as a `Byte`.\npub impl Add for Byte with add(self : Byte, that : Byte) -> Byte {\n (self.to_int() + that.to_int()).to_byte()\n}\n\n///|\n/// Subtracts the second byte from the first byte and returns the result as a\n/// byte.\n///\n/// Parameters:\n///\n/// - `self` : The byte from which the second byte will be subtracted.\n/// - `that` : The byte to subtract from the first byte.\n///\n/// Returns the result of the subtraction as a byte.\npub impl Sub for Byte with sub(self : Byte, that : Byte) -> Byte {\n (self.to_int() - that.to_int()).to_byte()\n}\n\n///|\n/// Compares two `Byte` values and returns an integer indicating their relative\n/// order.\n///\n/// Parameters:\n///\n/// - `byte1` : The first `Byte` value to compare.\n/// - `byte2` : The second `Byte` value to compare.\n///\n/// Returns an integer where:\n/// - A value less than 0 indicates that `byte1` is less than `byte2`.\n/// - A value of 0 indicates that `byte1` is equal to `byte2`.\n/// - A value greater than 0 indicates that `byte1` is greater than `byte2`.\npub impl Compare for Byte with compare(self : Byte, that : Byte) -> Int {\n self.to_int().compare(that.to_int())\n}\n\n///|\npub impl Compare for Byte with op_lt(x, y) {\n x.to_int() < y.to_int()\n}\n\n///|\npub impl Compare for Byte with op_le(x, y) {\n x.to_int() <= y.to_int()\n}\n\n///|\npub impl Compare for Byte with op_gt(x, y) {\n x.to_int() > y.to_int()\n}\n\n///|\npub impl Compare for Byte with op_ge(x, y) {\n x.to_int() >= y.to_int()\n}\n\n///|\nfn alphabet(x : Int) -> String {\n match x {\n 0 => \"0\"\n 1 => \"1\"\n 2 => \"2\"\n 3 => \"3\"\n 4 => \"4\"\n 5 => \"5\"\n 6 => \"6\"\n 7 => \"7\"\n 8 => \"8\"\n 9 => \"9\"\n 10 => \"A\"\n 11 => \"B\"\n 12 => \"C\"\n 13 => \"D\"\n 14 => \"E\"\n 15 => \"F\"\n _ => abort(\"impossible\")\n }\n}\n\n///|\n/// Converts a `Byte` to its string representation in hexadecimal format.\n///\n/// Parameters:\n///\n/// - `byte` : The `Byte` value to be converted.\n///\n/// Returns a `String` representing the `Byte` in the format `b'\\xHH'`, where\n/// `HH` is the hexadecimal representation of the byte.\npub fn Byte::to_string(self : Byte) -> String {\n let i = self.to_int()\n let hi = alphabet(i / 16)\n let lo = alphabet(i % 16)\n \"b'\\\\x\\{hi}\\{lo}'\"\n}\n\n///|\n/// Implements the `Hash` trait for `Byte` type by providing a `hash_combine`\n/// method that combines a byte value with a hasher.\n///\n/// Parameters:\n///\n/// * `self` : The byte value to be hashed.\n/// * `hasher` : The hasher object that will be used to combine the byte value\n/// into its internal state.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hasher = Hasher::new(seed=0)\n/// hasher.combine_byte(b'\\xFF')\n/// inspect(hasher.finalize(), content=\"1955036104\")\n/// }\n/// ```\npub impl Hash for Byte with hash_combine(self, hasher) {\n hasher.combine_byte(self)\n}\n\n///|\n/// Returns the default value for a `Byte`, which is `b'\\x00'`.\n///\n/// Parameters:\n///\n/// - None\n///\n/// Returns the default `Byte` value, which is `b'\\x00'`.\npub impl Default for Byte with default() {\n b'\\x00'\n}\n\n///|\n/// Performs a bitwise NOT operation on the given `Byte` value.\n///\n/// Parameters:\n///\n/// - `value` : The `Byte` value to apply the bitwise NOT operation on.\n///\n/// Returns the result of the bitwise NOT operation as a `Byte`.\npub fn Byte::lnot(self : Byte) -> Byte {\n self.to_int().lnot().to_byte()\n}\n\n///|\n/// Performs a bitwise AND operation between two `Byte` values.\n///\n/// Parameters:\n///\n/// - `byte1` : The first `Byte` value to perform the bitwise AND operation with.\n/// - `byte2` : The second `Byte` value to perform the bitwise AND operation\n/// with.\n///\n/// Returns the result of the bitwise AND operation as a `Byte`.\npub impl BitAnd for Byte with land(self : Byte, that : Byte) -> Byte {\n (self.to_int() & that.to_int()).to_byte()\n}\n\n///|\n/// Performs a bitwise OR operation between two `Byte` values.\n///\n/// Parameters:\n///\n/// - `self` : The first `Byte` value.\n/// - `that` : The second `Byte` value.\n///\n/// Returns a new `Byte` value resulting from the bitwise OR operation.\npub impl BitOr for Byte with lor(self : Byte, that : Byte) -> Byte {\n (self.to_int() | that.to_int()).to_byte()\n}\n\n///|\n/// Performs a bitwise XOR operation between two `Byte` values.\n///\n/// Parameters:\n///\n/// - `self` : The first `Byte` value.\n/// - `that` : The second `Byte` value.\n///\n/// Returns the result of the bitwise XOR operation as a `Byte`.\npub impl BitXOr for Byte with lxor(self : Byte, that : Byte) -> Byte {\n (self.to_int() ^ that.to_int()).to_byte()\n}\n\n///|\n/// Converts a `Byte` to a `UInt`.\n///\n/// Parameters:\n///\n/// - `byte` : The `Byte` value to be converted.\n///\n/// Returns the `UInt` representation of the `Byte`.\npub fn Byte::to_uint(self : Byte) -> UInt {\n self.to_int().reinterpret_as_uint()\n}\n\n///|\n/// Converts a byte value to an unsigned 64-bit integer.\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted.\n///\n/// Returns an unsigned 64-bit integer representation of the byte value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b = b'\\xFF'\n/// inspect(b.to_uint64(), content=\"255\")\n/// }\n/// ```\npub fn Byte::to_uint64(self : Byte) -> UInt64 {\n self.to_uint().to_uint64()\n}\n\n///|\n/// Counts the number of 1-bits (population count) in the byte using bitwise operations.\n///\n/// Parameters:\n///\n/// * `self` : The byte value whose 1-bits are to be counted.\n///\n/// Returns the number of 1-bits in the byte.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b = b'\\x0F'\n/// inspect(b.popcnt(), content=\"4\")\n/// }\n/// ```\npub fn Byte::popcnt(self : Byte) -> Int {\n let mut n = self\n n = (n & 0x55) + ((n >> 1) & 0x55)\n n = (n & 0x33) + ((n >> 2) & 0x33)\n n = (n & 0x0F) + ((n >> 4) & 0x0F)\n n.to_int()\n}\n\n///|\n/// Shifts the bits of the `Byte` value to the left by the specified number of\n/// positions.\n///\n/// Parameters:\n///\n/// - `byte_value` : The `Byte` value whose bits are to be shifted.\n/// - `shift_count` : The number of bit positions to shift the `byte_value` to\n/// the left.\n///\n/// Returns the resulting `Byte` value after the shift operation.\npub impl Shl for Byte with shl(self : Byte, count : Int) -> Byte {\n (self.to_int() << count).to_byte()\n}\n\n///|\n/// Shifts the bits of the `Byte` value to the right by the specified number of\n/// positions.\n///\n/// Parameters:\n///\n/// - `byte` : The `Byte` value whose bits are to be shifted.\n/// - `count` : The number of bit positions to shift the `byte` value to the\n/// right.\n///\n/// Returns the resulting `Byte` value after the bitwise right shift operation.\npub impl Shr for Byte with shr(self : Byte, count : Int) -> Byte {\n (self.to_uint() >> count).reinterpret_as_int().to_byte()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\npub impl Show for Unit with output(_self, logger) {\n logger.write_string(\"()\")\n}\n\n///|\npub impl Show for Unit with to_string(_self) {\n \"()\"\n}\n\n///|\npub impl Show for Bool with to_string(self) {\n if self {\n \"true\"\n } else {\n \"false\"\n }\n}\n\n///|\npub impl Show for Int with to_string(self) {\n Int::to_string(self)\n}\n\n///|\npub impl Show for Int64 with to_string(self) {\n Int64::to_string(self)\n}\n\n///|\npub impl Show for UInt with to_string(self) {\n UInt::to_string(self)\n}\n\n///|\npub impl Show for UInt64 with to_string(self) {\n UInt64::to_string(self)\n}\n\n///|\npub impl Show for Byte with to_string(self) {\n Byte::to_string(self)\n}\n\n///|\npub impl Show for UInt16 with to_string(self) {\n UInt16::to_string(self)\n}\n\n///|\n/// Convert a byte to a two-digit lowercase hexadecimal string.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(Byte::to_hex(b'\\x0f'), content=\"0f\")\n/// }\n/// ```\npub fn Byte::to_hex(b : Byte) -> String {\n fn to_hex_digit(i : Byte) -> Char {\n if i < 10 {\n (i + b'0').to_char()\n } else {\n (i + b'a' - 10).to_char()\n }\n }\n\n [to_hex_digit(b / 16), to_hex_digit(b % 16)]\n}\n\n///|\ntest \"to_hex_digit\" {\n inspect(Byte::to_hex(b'\\xee'), content=\"ee\")\n inspect(Byte::to_hex(b'\\xf3'), content=\"f3\")\n}\n\n///|\n/// Returns the escaped representation of a string.\n///\n/// When `quote` is true (default), the result is wrapped in double quotes\n/// like a MoonBit string literal.\n///\n/// Escape rules:\n/// - Double quote and backslash are backslash-escaped: `\\\"`, `\\\\`\n/// - Common control characters use named escapes: `\\n`, `\\r`, `\\b`, `\\t`\n/// - Other control characters (< U+0020) use `\\u{hex}` format\n/// - All other characters are displayed as-is\n///\n/// ```mbt check\n/// test {\n/// inspect(\"Hello \\n\".escape(), content=\"\\\"Hello \\\\n\\\"\")\n/// inspect(\"Hello \\n\".escape(quote=false), content=\"Hello \\\\n\")\n/// }\n/// ```\npub fn String::escape(self : String, quote? : Bool = true) -> String {\n let buf = StringBuilder()\n self[:].escape_to(buf, quote~)\n buf.to_string()\n}\n\n///|\n/// Returns the escaped representation of a string view.\n///\n/// When `quote` is true (default), the result is wrapped in double quotes\n/// like a MoonBit string literal.\n///\n/// Escape rules:\n/// - Double quote and backslash are backslash-escaped: `\\\"`, `\\\\`\n/// - Common control characters use named escapes: `\\n`, `\\r`, `\\b`, `\\t`\n/// - Other control characters (< U+0020) use `\\u{hex}` format\n/// - All other characters are displayed as-is\n///\n/// ```mbt check\n/// test {\n/// inspect(\"Hello\\nWorld\"[:6].escape(), content=\"\\\"Hello\\\\n\\\"\")\n/// inspect(\"Hello\\nWorld\"[:6].escape(quote=false), content=\"Hello\\\\n\")\n/// }\n/// ```\npub fn StringView::escape(\n self : StringView,\n quote? : Bool = true,\n) -> StringView {\n let buf = StringBuilder()\n self.escape_to(buf, quote~)\n buf.to_string()\n}\n\n///|\nfn StringView::escape_to(\n self : StringView,\n logger : &Logger,\n quote? : Bool = true,\n) -> Unit {\n if quote {\n logger.write_char('\"')\n }\n let len = self.length()\n fn flush_segment(seg : Int, i : Int) {\n if i > seg {\n logger.write_view(self[seg:i])\n }\n }\n for i = 0, seg = 0 {\n if i >= len {\n flush_segment(seg, i)\n break\n }\n let code = self.unsafe_get(i)\n match code {\n '\"' | '\\\\' as c => {\n flush_segment(seg, i)\n logger.write_char('\\\\')\n logger.write_char(c.unsafe_to_char())\n continue i + 1, i + 1\n }\n '\\n' => {\n flush_segment(seg, i)\n logger.write_string(\"\\\\n\")\n continue i + 1, i + 1\n }\n '\\r' => {\n flush_segment(seg, i)\n logger.write_string(\"\\\\r\")\n continue i + 1, i + 1\n }\n '\\b' => {\n flush_segment(seg, i)\n logger.write_string(\"\\\\b\")\n continue i + 1, i + 1\n }\n '\\t' => {\n flush_segment(seg, i)\n logger.write_string(\"\\\\t\")\n continue i + 1, i + 1\n }\n code =>\n if code < ' ' {\n flush_segment(seg, i)\n logger.write_string(\"\\\\u{\")\n logger.write_string(code.to_byte().to_hex())\n logger.write_char('}')\n continue i + 1, i + 1\n } else {\n continue i + 1, seg\n }\n }\n }\n if quote {\n logger.write_char('\"')\n }\n}\n\n///|\n/// Returns the original string without escaping.\n/// `Show::output` for `String` also writes the raw string through this\n/// `Show::to_string` implementation.\n/// Use `String::escape` when a quoted and escaped representation is needed.\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let str = \"Hello \\n\"\n/// inspect(str.to_string(), content=\"Hello \\n\")\n/// inspect(str.escape(quote=true), content=\"\\\"Hello \\\\n\\\"\")\n/// }\n/// ```\npub impl Show for String with to_string(self) {\n self\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[X : Show] Show for X?\n\n///|\npub impl[X : Show] Show for X? with output(self, logger) {\n match self {\n None => logger.write_string(\"None\")\n Some(arg) => {\n logger.write_string(\"Some(\")\n logger.write_object(arg)\n logger.write_string(\")\")\n }\n }\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[T : Show, E : Show] Show for Result[T, E]\n\n///|\npub impl[T : Show, E : Show] Show for Result[T, E] with output(self, logger) {\n match self {\n Ok(x) => {\n logger.write_string(\"Ok(\")\n logger.write_object(x)\n logger.write_string(\")\")\n }\n Err(e) => {\n logger.write_string(\"Err(\")\n logger.write_object(e)\n logger.write_string(\")\")\n }\n }\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[X : Show] Show for FixedArray[X]\n\n///|\npub impl[X : Show] Show for FixedArray[X] with output(self, logger) {\n logger.write_iter(self.iter())\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[X : Show] Show for Array[X]\n\n///|\npub impl[X : Show] Show for Array[X] with output(self, logger) {\n logger.write_iter(self.iter())\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Returns the source string being viewed.\nfn StringView::str(self : StringView) -> String = \"%stringview.str\"\n\n///|\n/// Returns the starting UTF-16 code unit index into the string.\nfn StringView::start(self : StringView) -> Int = \"%stringview.start\"\n\n///|\n/// Returns the ending UTF-16 code unit index into the string (not included).\nfn StringView::end(self : StringView) -> Int = \"%stringview.end\"\n\n///|\nfn StringView::make_view(str : String, start : Int, end : Int) -> StringView = \"%stringview.make\"\n\n///|\n/// Returns the UTF-16 code unit at the given index.\n/// \n/// This method has O(1) complexity.\n/// Panics if the index is out of bounds.\n/// TODO: make it intrinsic\n#alias(\"_[_]\")\n#alias(code_unit_at)\npub fn StringView::at(self : StringView, index : Int) -> UInt16 {\n guard index >= 0 && index < self.length() else {\n abort(\"Index out of bounds\")\n }\n self.unsafe_get(index)\n}\n\n///|\n/// Returns the length of the view.\n/// \n/// This method counts the charcodes(code unit) in the view and has O(1) complexity.\npub fn StringView::length(self : StringView) -> Int {\n self.end() - self.start()\n}\n\n///|\n/// Iterates over all suffixes of the view, advancing by a Unicode character at\n/// a time. Each yielded suffix is itself a view into the original string.\npub fn StringView::suffixes(\n self : StringView,\n include_empty? : Bool = false,\n) -> Iter[StringView] {\n let str = self.str()\n let end = self.end()\n let mut next_start = self.start()\n let mut finished = false\n Iter::new(fn() -> StringView? {\n if finished {\n None\n } else if next_start == end {\n finished = true\n if include_empty {\n Some(StringView::make_view(str, next_start, end))\n } else {\n None\n }\n } else {\n let suffix = StringView::make_view(str, next_start, end)\n let code = str.unsafe_get(next_start)\n if code.is_leading_surrogate() &&\n next_start + 1 < end &&\n str.unsafe_get(next_start + 1).is_trailing_surrogate() {\n next_start += 2\n } else {\n next_start += 1\n }\n Some(suffix)\n }\n })\n}\n\n///|\n/// Returns the original string that is being viewed.\npub fn StringView::data(self : StringView) -> String {\n self.str()\n}\n\n///|\n/// Returns the starting offset (in UTF-16 code units) of this view into its\n/// underlying string.\npub fn StringView::start_offset(self : StringView) -> Int {\n self.start()\n}\n\n///|\n/// Returns a new view of the view with the given start and end offsets.\npub fn StringView::view(\n self : StringView,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> StringView {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n guard start_offset >= 0 &&\n start_offset <= end_offset &&\n end_offset <= self.length() else {\n abort(\"Invalid index for View\")\n }\n StringView::make_view(\n self.str(),\n self.start() + start_offset,\n self.start() + end_offset,\n )\n}\n\n///|\n/// Returns the UTF-16 code unit at the given index without checking if the\n/// index is within bounds.\n///\n/// This method has O(1) complexity.\n#internal(unsafe, \"Undefined behavior if index is out of bounds.\")\npub fn StringView::unsafe_get(self : StringView, index : Int) -> UInt16 {\n self.str().unsafe_get(self.start() + index)\n}\n\n///|\n/// Returns the charcode(code unit) at the given index without checking if the\n/// index is within bounds.\n/// \n/// This method has O(1) complexity.\n/// #Example\n/// \n/// ```mbt check\n/// test {\n/// let str = \"B🤣🤣C\"\n/// let view = str[:]\n/// inspect(view.unsafe_get(0), content=\"66\")\n/// inspect(view.unsafe_get(1), content=\"55358\")\n/// inspect(view.unsafe_get(2), content=\"56611\")\n/// inspect(view.unsafe_get(3), content=\"55358\")\n/// inspect(view.unsafe_get(4), content=\"56611\")\n/// inspect(view.unsafe_get(5), content=\"67\")\n/// }\n/// ```\n#deprecated(\"Use `StringView::unsafe_get` instead\")\npub fn StringView::unsafe_charcode_at(self : StringView, index : Int) -> Int {\n self.str().unsafe_get(self.start() + index).to_int()\n}\n\n///|\n/// Returns the number of Unicode characters in this view.\n/// \n/// Note this has O(n) complexity where n is the length of the code points in \n/// the view.\npub fn StringView::char_length(self : StringView) -> Int {\n self.str().char_length(start_offset=self.start(), end_offset=self.end())\n}\n\n///|\n/// Materialize this view into an owned `String`.\n///\n/// This crosses an ownership boundary and generally allocates. Use format\n/// strings (`\"\\{view}\"`) or `Show::to_string(view)` when you only need a\n/// display representation — those paths go through the `Show` trait and are\n/// not flagged.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let str = \"Hello World\"\n/// let view = str.view(\n/// start_offset=str.offset_of_nth_char(0).unwrap(),\n/// end_offset=str.offset_of_nth_char(5).unwrap(),\n/// ) // \"Hello\"\n/// inspect(view.to_owned(), content=\"Hello\")\n/// }\n/// ```\n#alias(to_string, deprecated=\"Use `to_owned` to allocate an owned String from a StringView; use `Show::to_string` or format strings for display\")\npub fn StringView::to_owned(self : StringView) -> String {\n // when `self == self.str()`, `String::unsafe_substring` would return original string, which doesn't create a new copy.\n self.str().unsafe_substring(start=self.start(), end=self.end())\n}\n\n///|\npub impl Show for StringView with output(self, logger) {\n logger.write_view(self)\n}\n\n///|\npub impl Show for StringView with to_string(self) {\n self.to_owned()\n}\n\n///|\n/// Returns an iterator over the Unicode characters in the string view.\n#alias(iterator, deprecated)\npub fn StringView::iter(self : StringView) -> Iter[Char] {\n let start = self.start()\n let end = self.end()\n let mut index = start\n Iter::new(fn() {\n guard index < end else { None }\n let c1 = self.str().unsafe_get(index)\n if c1.is_leading_surrogate() && index + 1 < self.end() {\n let c2 = self.str().unsafe_get(index + 1)\n if c2.is_trailing_surrogate() {\n index += 2\n return Some(code_point_of_surrogate_pair(c1.to_int(), c2.to_int()))\n }\n }\n index += 1\n Some(c1.unsafe_to_char())\n })\n}\n\n///|\n/// Returns an iterator over the Unicode characters in the string view,\n/// yielding pairs of (character index, character).\n#alias(iterator2, deprecated)\npub fn StringView::iter2(self : StringView) -> Iter2[Int, Char] {\n let start = self.start()\n let end = self.end()\n let mut index = start\n let mut char_index = 0\n Iter2::new(fn() {\n guard index < end else { None }\n let c1 = self.str().unsafe_get(index)\n if c1.is_leading_surrogate() && index + 1 < self.end() {\n let c2 = self.str().unsafe_get(index + 1)\n if c2.is_trailing_surrogate() {\n let result = (\n char_index,\n code_point_of_surrogate_pair(c1.to_int(), c2.to_int()),\n )\n index += 2\n char_index += 1\n return Some(result)\n }\n }\n let result = (char_index, c1.unsafe_to_char())\n index += 1\n char_index += 1\n Some(result)\n })\n}\n\n///|\n/// Returns an iterator over the Unicode characters in the string view in reverse order.\n#alias(rev_iterator, deprecated)\npub fn StringView::rev_iter(self : StringView) -> Iter[Char] {\n let start = self.start()\n let end = self.end()\n let mut index = end\n Iter::new(fn() {\n guard index > start else { None }\n index -= 1\n let c1 = self.str().unsafe_get(index)\n if c1.is_trailing_surrogate() && index - 1 >= 0 {\n let c2 = self.str().unsafe_get(index - 1)\n if c2.is_leading_surrogate() {\n index -= 1\n return Some(code_point_of_surrogate_pair(c2.to_int(), c1.to_int()))\n }\n }\n Some(c1.unsafe_to_char())\n })\n}\n\n///|\n/// Compares two views for equality. Returns true only if both views\n/// have the same length and contain identical characters in the same order.\npub impl Eq for StringView with equal(self, other) {\n let len = self.length()\n guard len == other.length() else { return false }\n if physical_equal(self.str(), other.str()) && self.start() == other.start() {\n return true\n }\n for i in 0..<len {\n guard self.str().unsafe_get(self.start() + i) ==\n other.str().unsafe_get(other.start() + i) else {\n return false\n }\n }\n true\n}\n\n///|\n/// Compares a `StringView` to a `String` code-unit-for-code-unit.\n///\n/// This is the cross-type equivalent of `==` and avoids materializing a fresh\n/// `String` (or a wrapping `StringView`) when probing an owned-`String`-keyed\n/// container with a view-shaped key. When the view spans an entire backing\n/// string that is physically the same as `other`, this short-circuits.\n///\n/// Returns `true` if the lengths match and every UTF-16 code unit in `self`\n/// equals the code unit at the same index in `other`.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// let s = \"say hello to everyone\"\n/// inspect(\n/// s.view(start_offset=4, end_offset=9).equal_to_string(\"hello\"),\n/// content=\"true\",\n/// )\n/// inspect(\n/// s.view(start_offset=4, end_offset=9).equal_to_string(\"world\"),\n/// content=\"false\",\n/// )\n/// }\n/// ```\npub fn StringView::equal_to_string(self : StringView, other : String) -> Bool {\n let len = self.length()\n guard len == other.length() else { return false }\n if physical_equal(self.str(), other) && self.start() == 0 {\n return true\n }\n for i in 0..<len {\n guard self.str().unsafe_get(self.start() + i) == other.unsafe_get(i) else {\n return false\n }\n }\n true\n}\n\n///|\n/// Views are ordered based on shortlex order by their charcodes (code units). This \n/// orders Unicode characters based on their positions in the code charts. This is\n/// not necessarily the same as \"alphabetical\" order, which varies by language\n/// and locale.\npub impl Compare for StringView with compare(self, other) {\n let self_len = self.length()\n let other_len = other.length()\n let cmp = self_len.compare(other_len)\n guard cmp == 0 else { return cmp }\n if physical_equal(self.str(), other.str()) && self.start() == other.start() {\n return 0\n }\n for i in 0..<self_len {\n let cmp = self\n .str()\n .unsafe_get(self.start() + i)\n .compare(other.str().unsafe_get(other.start() + i))\n guard cmp == 0 else { return cmp }\n }\n 0\n}\n\n///|\n/// Performs a lexicographical comparison of two string views.\n///\n/// This method compares the views character by character (UTF-16 code unit by code unit),\n/// similar to Java's `String.compareTo()`. Unlike the `Compare` trait implementation which\n/// uses shortlex order (shorter strings come first), this method compares based purely on\n/// character values until a difference is found or one view is exhausted.\n///\n/// # Returns\n///\n/// - A negative integer if `self` is lexicographically less than `other`\n/// - Zero if `self` is lexicographically equal to `other`\n/// - A positive integer if `self` is lexicographically greater than `other`\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let str = \"abc\"\n/// inspect(\n/// str\n/// .view(start_offset=0, end_offset=2)\n/// .lexical_compare(str.view(start_offset=0, end_offset=3)),\n/// content=\"-1\",\n/// )\n/// inspect(\n/// str\n/// .view(start_offset=0, end_offset=3)\n/// .lexical_compare(str.view(start_offset=0, end_offset=2)),\n/// content=\"1\",\n/// )\n/// inspect(\n/// str\n/// .view(start_offset=0, end_offset=2)\n/// .lexical_compare(str.view(start_offset=1, end_offset=3)),\n/// content=\"-1\",\n/// )\n/// }\n/// ```\n///\n/// # Note\n///\n/// Since MoonBit strings are UTF-16 encoded (like Java), this comparison operates on\n/// UTF-16 code units, not Unicode code points. Surrogate pairs (used for characters\n/// outside the Basic Multilingual Plane) are compared as individual code units.\npub fn StringView::lexical_compare(\n self : StringView,\n other : StringView,\n) -> Int {\n let self_len = self.length()\n let other_len = other.length()\n let min_len = if self_len < other_len { self_len } else { other_len }\n\n // Compare character by character up to the minimum length\n for i in 0..<min_len {\n let self_char = self.str().unsafe_get(self.start() + i)\n let other_char = other.str().unsafe_get(other.start() + i)\n let cmp = self_char.compare(other_char)\n if cmp != 0 {\n return cmp\n }\n }\n\n // If all characters match up to min_len, the shorter one is lexicographically smaller\n self_len.compare(other_len)\n}\n\n///|\n/// Folds an ASCII uppercase code unit (`'A'..'Z'`) to its lowercase form. Code\n/// units outside that range — including all non-ASCII code units — are returned\n/// unchanged.\nfn ascii_fold_lower_u16(c : UInt16) -> UInt16 {\n if c >= ('A' : UInt16) && c <= ('Z' : UInt16) {\n c + (32 : UInt16)\n } else {\n c\n }\n}\n\n///|\n/// Performs a lexicographical comparison of two string views, treating ASCII\n/// letters as case-insensitive.\n///\n/// Each pair of UTF-16 code units is compared after folding ASCII `'A'..'Z'`\n/// onto `'a'..'z'`. Non-ASCII code units are compared by their raw value, so\n/// this function does **not** perform Unicode case folding (e.g. `'Ä'` and\n/// `'ä'` are still considered different). Use this when you only need to\n/// match ASCII identifiers, headers, file extensions, or similar protocol\n/// text — not for human-language text where locale-dependent folding matters.\n///\n/// Aside from case folding, the semantics match `lexical_compare`: characters\n/// are compared one by one (UTF-16 code unit by code unit) and, when one view\n/// is a prefix of the other, the shorter view is considered less. The result\n/// is independent of which view is `self`.\n///\n/// # Returns\n///\n/// - A negative integer if `self` is less than `other`\n/// - Zero if `self` is equal to `other` under ASCII case folding\n/// - A positive integer if `self` is greater than `other`\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect(\"Hello\".view().compare_ignore_ascii_case(\"hello\".view()), content=\"0\")\n/// inspect(\"ABC\".view().compare_ignore_ascii_case(\"abd\".view()), content=\"-1\")\n/// inspect(\"abc\".view().compare_ignore_ascii_case(\"AB\".view()), content=\"1\")\n/// }\n/// ```\npub fn StringView::compare_ignore_ascii_case(\n self : StringView,\n other : StringView,\n) -> Int {\n let self_len = self.length()\n let other_len = other.length()\n let min_len = if self_len < other_len { self_len } else { other_len }\n for i in 0..<min_len {\n let a = ascii_fold_lower_u16(self.str().unsafe_get(self.start() + i))\n let b = ascii_fold_lower_u16(other.str().unsafe_get(other.start() + i))\n let cmp = a.compare(b)\n if cmp != 0 {\n return cmp\n }\n }\n self_len.compare(other_len)\n}\n\n///|\n/// Tests two string views for equality, treating ASCII letters as\n/// case-insensitive.\n///\n/// ASCII `'A'..'Z'` are folded onto `'a'..'z'` before comparison; all other\n/// code units (including non-ASCII letters like `'Ä'`) are compared by their\n/// raw UTF-16 value. Use this for ASCII-only protocol text — HTTP headers,\n/// file extensions, identifiers — not for human-language text where Unicode\n/// case folding matters.\n///\n/// Equivalent to `self.compare_ignore_ascii_case(other) == 0` but short-\n/// circuits on length mismatch and on the first differing code unit, so it\n/// is preferred when only equality is needed.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect(\n/// \"Hello\".view().equal_ignore_ascii_case(\"hello\".view()),\n/// content=\"true\",\n/// )\n/// inspect(\n/// \"Hello\".view().equal_ignore_ascii_case(\"world\".view()),\n/// content=\"false\",\n/// )\n/// inspect(\"abc\".view().equal_ignore_ascii_case(\"ab\".view()), content=\"false\")\n/// }\n/// ```\npub fn StringView::equal_ignore_ascii_case(\n self : StringView,\n other : StringView,\n) -> Bool {\n let len = self.length()\n if len != other.length() {\n return false\n }\n for i in 0..<len {\n let a = self.str().unsafe_get(self.start() + i)\n let b = other.str().unsafe_get(other.start() + i)\n // Fast path: identical code units need no folding.\n if a == b {\n continue\n }\n if ascii_fold_lower_u16(a) != ascii_fold_lower_u16(b) {\n return false\n }\n }\n true\n}\n\n///|\n/// Creates a `View` into a `String`.\n/// \n/// # Example\n/// \n/// ```mbt check\n/// test {\n/// let str = \"Hello🤣🤣🤣\"\n/// let view1 = str.view()\n/// inspect(view1, content=\"Hello🤣🤣🤣\")\n/// let start_offset = str.offset_of_nth_char(1).unwrap()\n/// let end_offset = str.offset_of_nth_char(6).unwrap() // the second emoji\n/// let view2 = str.view(start_offset~, end_offset~)\n/// inspect(view2, content=\"ello🤣\")\n/// }\n/// ```\npub fn String::view(\n self : String,\n start_offset? : Int = 0,\n end_offset? : Int,\n) -> StringView {\n let end_offset = if end_offset is Some(o) { o } else { self.length() }\n guard start_offset >= 0 &&\n start_offset <= end_offset &&\n end_offset <= self.length() else {\n abort(\"Invalid index for View\")\n }\n StringView::make_view(self, start_offset, end_offset)\n}\n\n///|\n/// Convert char array to string view.\npub fn StringView::from_array(chars : ArrayView[Char]) -> StringView {\n String::from_array(chars)\n}\n\n///|\n/// Convert char iterator to string view.\n#alias(from_iterator, deprecated)\npub fn StringView::from_iter(iter : Iter[Char]) -> StringView {\n String::from_iter(iter)\n}\n\n///|\n/// Returns a view of the string between `start` and `end`, or `None` if the\n/// range is invalid — either out of bounds or splitting a UTF-16 surrogate\n/// pair. Unlike `String::sub` (a.k.a. `s[start:end]`), this variant does not\n/// abort, making it suitable for composition with pattern matching:\n///\n/// ```mbt check\n/// test {\n/// let s = \"Hello🤣World\"\n/// debug_inspect(\n/// s.get_view(end=5).map(v => v.to_owned()),\n/// content=\"Some(\\\"Hello\\\")\",\n/// )\n/// // Splitting a surrogate pair is rejected rather than panicking.\n/// debug_inspect(s.get_view(end=6), content=\"None\")\n/// debug_inspect(s.get_view(start=100), content=\"None\")\n/// }\n/// ```\npub fn String::get_view(\n self : String,\n start? : Int = 0,\n end? : Int,\n) -> StringView? {\n let len = self.length()\n let end = match end {\n None => len\n Some(end) => if end < 0 { len + end } else { end }\n }\n let start = if start < 0 { len + start } else { start }\n guard start >= 0 && start <= end && end <= len else { None }\n if start < len && self.unsafe_get(start).is_trailing_surrogate() {\n return None\n }\n if end < len && self.unsafe_get(end).is_trailing_surrogate() {\n return None\n }\n Some(StringView::make_view(self, start, end))\n}\n\n///|\n/// Returns a sub-view of the view between `start` and `end`, or `None` if the\n/// range is invalid — either out of bounds or splitting a UTF-16 surrogate\n/// pair. The optional variant of `StringView::sub` (a.k.a. `sv[start:end]`).\npub fn StringView::get_view(\n self : StringView,\n start? : Int = 0,\n end? : Int,\n) -> StringView? {\n let str_len = self.str().length()\n let abs_end = match end {\n None => self.end()\n Some(end) => if end < 0 { self.end() + end } else { self.start() + end }\n }\n let abs_start = if start < 0 {\n self.end() + start\n } else {\n self.start() + start\n }\n guard abs_start >= self.start() &&\n abs_start <= abs_end &&\n abs_end <= self.end() else {\n None\n }\n if abs_start < str_len &&\n self.str().unsafe_get(abs_start).is_trailing_surrogate() {\n return None\n }\n if abs_end < str_len && self.str().unsafe_get(abs_end).is_trailing_surrogate() {\n return None\n }\n Some(StringView::make_view(self.str(), abs_start, abs_end))\n}\n\n///|\n/// Creates a view of a string with proper UTF-16 boundary validation.\n///\n/// # Parameters\n///\n/// - `start` : Starting UTF-16 code unit index (default: 0)\n/// - If positive: counts from the beginning of the string\n/// - If negative: counts from the end of the string (e.g., -1 means last position)\n/// - `end` : Ending UTF-16 code unit index (optional)\n/// - If `None`: extends to the end of the string\n/// - If positive: counts from the beginning of the string\n/// - If negative: counts from the end of the string\n///\n/// # Returns\n///\n/// - A `View` representing the specified substring range\n///\n/// # Panics\n///\n/// - If start or end indices are out of valid range\n/// - If start or end position would split a UTF-16 surrogate pair\n///\n/// This prevents creating views that would split surrogate pairs, which would\n/// result in invalid Unicode characters.\n///\n/// # Performance\n///\n/// This function has O(1) complexity as it only performs boundary checks\n/// without scanning the string content.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let str = \"Hello🤣World\"\n/// let view1 = str[0:5]\n/// inspect(view1, content=\"Hello\")\n/// let view2 = str[-5:]\n/// inspect(view2, content=\"World\")\n/// }\n/// ```\n#alias(\"_[_:_]\")\npub fn String::sub(self : String, start? : Int = 0, end? : Int) -> StringView {\n let len = self.length()\n let end = match end {\n None => len\n Some(end) => if end < 0 { len + end } else { end }\n }\n let start = if start < 0 { len + start } else { start }\n guard start >= 0 && start <= end && end <= len\n if start < len {\n guard !self.unsafe_get(start).is_trailing_surrogate()\n }\n if end < len {\n guard !self.unsafe_get(end).is_trailing_surrogate()\n }\n StringView::make_view(self, start, end)\n}\n\n///|\n/// Creates a subview of an existing view with proper UTF-16 boundary validation.\n///\n/// # Parameters\n///\n/// - `start` : Starting UTF-16 code unit index relative to this view (default: 0)\n/// - If positive: counts from the beginning of this view\n/// - If negative: counts from the end of this view\n/// - `end` : Ending UTF-16 code unit index relative to this view (optional)\n/// - If `None`: extends to the end of this view\n/// - If positive: counts from the beginning of this view\n/// - If negative: counts from the end of this view\n///\n/// # Returns\n///\n/// - A `View` representing the specified subrange of this view\n///\n/// # Panics\n///\n/// - If start or end indices are out of this view's range\n/// - If start or end position would split a UTF-16 surrogate pair\n///\n/// This prevents creating views that would split surrogate pairs, which would\n/// result in invalid Unicode characters.\n///\n/// # Performance\n///\n/// This function has O(1) complexity as it only performs boundary checks\n/// without scanning the string content.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let str = \"Hello🤣World\"[1:-1] // \"ello🤣Worl\"\n/// let view1 = str[0:6]\n/// inspect(view1, content=\"ello🤣\")\n/// let view2 = str[-2:]\n/// inspect(view2, content=\"rl\")\n/// }\n/// ```\n#alias(\"_[_:_]\")\npub fn StringView::sub(\n self : StringView,\n start? : Int = 0,\n end? : Int,\n) -> StringView {\n let str_len = self.str().length()\n\n // Calculate absolute positions in the original string\n let abs_end = match end {\n None => self.end()\n Some(end) => if end < 0 { self.end() + end } else { self.start() + end }\n }\n let abs_start = if start < 0 {\n self.end() + start\n } else {\n self.start() + start\n }\n\n // Validate bounds against the original string\n guard abs_start >= self.start() &&\n abs_start <= abs_end &&\n abs_end <= self.end()\n\n // Check for surrogate pair boundaries\n if abs_start < str_len {\n guard !self.str().unsafe_get(abs_start).is_trailing_surrogate()\n }\n if abs_end < str_len {\n guard !self.str().unsafe_get(abs_end).is_trailing_surrogate()\n }\n StringView::make_view(self.str(), abs_start, abs_end)\n}\n\n///|\n/// Test if the length of the view is equal to the given length.\n/// \n/// This has O(n) complexity where n is the length in the parameter.\npub fn StringView::char_length_eq(self : StringView, len : Int) -> Bool {\n self\n .str()\n .char_length_eq(len, start_offset=self.start(), end_offset=self.end())\n}\n\n///|\n/// Test if the length of the view is greater than or equal to the given length.\n/// \n/// This has O(n) complexity where n is the length in the parameter.\npub fn StringView::char_length_ge(self : StringView, len : Int) -> Bool {\n self\n .str()\n .char_length_ge(len, start_offset=self.start(), end_offset=self.end())\n}\n\n///|\n/// Returns the UTF-16 index of the i-th (zero-indexed) Unicode character of\n/// the view. If i is negative, it returns the index of the (n + i)-th character\n/// where n is the total number of Unicode characters in the view.\npub fn StringView::offset_of_nth_char(self : StringView, i : Int) -> Int? {\n if self\n .str()\n .offset_of_nth_char(i, start_offset=self.start(), end_offset=self.end())\n is Some(index) {\n Some(index - self.start())\n } else {\n None\n }\n}\n\n///|\n/// The empty view of a string\npub impl Default for StringView with default() {\n \"\"\n}\n\n///|\n/// Create a new string by repeating the given character `value` `length` times.\npub fn StringView::make(length : Int, value : Char) -> StringView {\n String::make(length, value)\n}\n\n///|\npub impl ToJson for StringView with to_json(self) {\n String::to_json(self.to_owned())\n}\n\n///|\npub impl Add for StringView with add(self, other) {\n [..self, ..other]\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Evaluates an expression and discards its result. This is useful when you want\n/// to execute an expression for its side effects but don't care about its return\n/// value, or when you want to explicitly indicate that a value is intentionally\n/// unused.\n///\n/// Parameters:\n///\n/// * `value` : The value to be ignored. Can be of any type.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 42\n/// ignore(x) // Explicitly ignore the value\n/// let mut sum = 0\n/// ignore([1, 2, 3].iter().each(x => sum = sum + x)) // Ignore the Unit return value of each()\n/// }\n/// ```\npub fn[T] ignore(t : T) -> Unit = \"%ignore\"\n\n///|\n/// Tests whether two values are physically equal.\n///\n/// This function is intended only for performance optimizations. Do not depend\n/// on its result for program semantics.\n///\n/// NOTE: The result of `physical_equal` may not be consistent across different\n/// backends and/or different compiler optimization settings.\n///\n/// Parameters:\n///\n/// * `first` : The first value to compare.\n/// * `second` : The second value to compare.\n/// * `T` : The type parameter representing the type of values being compared.\n///\n/// Returns a backend- and optimization-dependent result indicating whether the\n/// two values are physically equal.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr1 = [1, 2, 3]\n/// let arr2 = arr1\n/// let arr3 = [1, 2, 3]\n/// inspect(physical_equal(arr1, arr2), content=\"true\") // Same object\n/// inspect(physical_equal(arr1, arr3), content=\"false\") // Different objects with same content\n/// }\n/// ```\npub fn[T] physical_equal(a : T, b : T) -> Bool = \"%refeq\"\n\n///|\npub using @abort {abort}\n\n///|\n/// Raise a panic with no payload.\n///\n/// This function never returns.\npub fn[T] panic() -> T = \"%panic\"\n\n// Bool primitive ops\n\n///|\n/// Performs logical negation on a boolean value.\n///\n/// Parameters:\n///\n/// * `value` : The boolean value to negate.\n///\n/// Returns the logical NOT of the input value: `true` if the input is `false`,\n/// and `false` if the input is `true`.\n///\n#deprecated\npub fn not(x : Bool) -> Bool = \"%bool_not\"\n\n///|\n/// Compares two boolean values for equality.\n///\n/// Parameters:\n///\n/// * `self` : The first boolean value to compare.\n/// * `other` : The second boolean value to compare.\n///\n/// Returns `true` if both boolean values are equal (either both `true` or both\n/// `false`), `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(true == true, content=\"true\")\n/// inspect(false == true, content=\"false\")\n/// inspect(true == false, content=\"false\")\n/// inspect(false == false, content=\"true\")\n/// }\n/// ```\npub impl Eq for Bool with equal(self : Bool, other : Bool) -> Bool = \"%bool_eq\"\n\n///|\n/// Compares two boolean values and returns their relative order. This is a\n/// deprecated method and users should use `compare` instead.\n///\n/// Parameters:\n///\n/// * `self` : The first boolean value to compare.\n/// * `other` : The second boolean value to compare against.\n///\n/// Returns an integer indicating the relative order:\n///\n/// * A negative value if `self` is less than `other` (i.e., `self` is `false`\n/// and `other` is `true`)\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other` (i.e., `self` is `true`\n/// and `other` is `false`)\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let t = true\n/// let f = false\n/// // This usage is deprecated, use compare() instead\n/// inspect(t.compare(f), content=\"1\")\n/// inspect(f.compare(t), content=\"-1\")\n/// inspect(t.compare(t), content=\"0\")\n/// }\n/// ```\n///\n#deprecated(\"Use `compare` instead\")\n#coverage.skip\npub fn Bool::op_compare(self : Bool, other : Bool) -> Int = \"%bool_compare\"\n\n///|\n/// Compares two boolean values and returns their relative order. The comparison\n/// follows the rule that `false` is less than `true`.\n///\n/// Parameters:\n///\n/// * `self` : The first boolean value to compare.\n/// * `other` : The second boolean value to compare against.\n///\n/// Returns an integer indicating the relative order:\n///\n/// * A negative value if `self` is `false` and `other` is `true`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is `true` and `other` is `false`\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(true.compare(false), content=\"1\") // true > false\n/// inspect(false.compare(true), content=\"-1\") // false < true\n/// inspect(true.compare(true), content=\"0\") // true = true\n/// }\n/// ```\npub impl Compare for Bool with compare(self, other) = \"%bool_compare\"\n\n///|\n/// Returns the default value for the `Bool` type, which is `false`.\n///\n/// Returns a `Bool` value that represents the default state of a boolean value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b : Bool = Bool::default()\n/// inspect(b, content=\"false\")\n/// }\n/// ```\npub impl Default for Bool with default() = \"%bool_default\"\n\n// int32 primitive ops\n\n///|\n/// Performs arithmetic negation on an integer value, returning its additive\n/// inverse.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to negate.\n///\n/// Returns the negation of the input value. For all inputs except\n/// `Int::min_value()`, returns the value with opposite sign. When the input is\n/// `Int::min_value()`, returns `Int::min_value()` due to two's complement\n/// representation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(-42, content=\"-42\")\n/// inspect(42, content=\"42\")\n/// inspect(2147483647, content=\"2147483647\") // negating near min value\n/// }\n/// ```\npub impl Neg for Int with neg(self) = \"%i32_neg\"\n\n///|\n/// Adds two 32-bit signed integers. Performs two's complement arithmetic, which\n/// means the operation will wrap around if the result exceeds the range of a\n/// 32-bit integer.\n///\n/// Parameters:\n///\n/// * `self` : The first integer operand.\n/// * `other` : The second integer operand.\n///\n/// Returns a new integer that is the sum of the two operands. If the\n/// mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to\n/// 2,147,483,647), the result wraps around according to two's complement rules.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42 + 1, content=\"43\")\n/// inspect(2147483647 + 1, content=\"-2147483648\") // Overflow wraps around to minimum value\n/// }\n/// ```\npub impl Add for Int with add(self, other) = \"%i32_add\"\n\n///|\n/// Performs subtraction between two 32-bit integers, following standard two's\n/// complement arithmetic rules. When the result overflows or underflows, it\n/// wraps around within the 32-bit integer range.\n///\n/// Parameters:\n///\n/// * `self` : The minuend (the number being subtracted from).\n/// * `other` : The subtrahend (the number to subtract).\n///\n/// Returns the difference between `self` and `other`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42\n/// let b = 10\n/// inspect(a - b, content=\"32\")\n/// let max = 2147483647 // Int maximum value\n/// inspect(max - -1, content=\"-2147483648\") // Overflow case\n/// }\n/// ```\npub impl Sub for Int with sub(self, other) = \"%i32_sub\"\n\n///|\n/// Multiplies two 32-bit integers. This is the implementation of the `*`\n/// operator for `Int`.\n///\n/// Parameters:\n///\n/// * `self` : The first integer operand.\n/// * `other` : The second integer operand.\n///\n/// Returns the product of the two integers. If the result overflows the range of\n/// `Int`, it wraps around according to two's complement arithmetic.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42 * 2, content=\"84\")\n/// inspect(-10 * 3, content=\"-30\")\n/// let max = 2147483647 // Int.max_value\n/// inspect(max * 2, content=\"-2\") // Overflow wraps around\n/// }\n/// ```\npub impl Mul for Int with mul(self, other) = \"%i32_mul\"\n\n///|\n/// Performs integer division between two 32-bit integers. The result is\n/// truncated towards zero (rounds down for positive numbers and up for negative\n/// numbers).\n///\n/// Parameters:\n///\n/// * `dividend` : The first integer operand to be divided.\n/// * `divisor` : The second integer operand that divides the dividend.\n///\n/// Returns the quotient of the division operation.\n///\n/// Throws a panic if `divisor` is zero.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(10 / 3, content=\"3\") // truncates towards zero\n/// inspect(-10 / 3, content=\"-3\")\n/// inspect(10 / -3, content=\"-3\")\n/// }\n/// ```\npub impl Div for Int with div(self, other) = \"%i32_div\"\n\n///|\n/// Calculates the remainder of dividing one integer by another. The result\n/// follows the formula `dividend - (dividend / divisor) * divisor`, maintaining\n/// the same sign as the dividend.\n///\n/// Parameters:\n///\n/// * `self` : The dividend (the number being divided).\n/// * `other` : The divisor (the number to divide by).\n///\n/// Returns the remainder of the division. If `other` is 0, the behavior is\n/// undefined.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(7 % 3, content=\"1\")\n/// inspect(-7 % 3, content=\"-1\")\n/// inspect(7 % -3, content=\"1\")\n/// }\n/// ```\npub impl Mod for Int with mod(self, other) = \"%i32_mod\"\n\n///|\n/// Performs a bitwise NOT operation on a 32-bit integer. Flips each bit in the\n/// integer's binary representation (0 becomes 1 and 1 becomes 0).\n///\n/// Parameters:\n///\n/// * `value` : The 32-bit integer on which to perform the bitwise NOT operation.\n///\n/// Returns a new integer with all bits flipped from the input value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = -1 // All bits are 1\n/// let b = 0 // All bits are 0\n/// inspect(a.lnot(), content=\"0\")\n/// inspect(b.lnot(), content=\"-1\")\n/// }\n/// ```\npub fn Int::lnot(self : Int) -> Int = \"%i32_lnot\"\n\n///|\n/// Performs a bitwise AND operation between two 32-bit integers. Each bit in the\n/// result is set to 1 only if the corresponding bits in both operands are 1.\n///\n/// Parameters:\n///\n/// * `self` : The first 32-bit integer operand.\n/// * `other` : The second 32-bit integer operand.\n///\n/// Returns the result of the bitwise AND operation. The resulting value has a\n/// bit set to 1 at each position where both input integers have a bit set to 1.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xF0 // 11110000\n/// let y = 0xAA // 10101010\n/// inspect(x & y, content=\"160\") // 10100000 = 160\n/// }\n/// ```\npub impl BitAnd for Int with land(self : Int, other : Int) -> Int = \"%i32_land\"\n\n///|\n/// Performs a bitwise OR operation between two 32-bit integers. For each bit\n/// position, the result is 1 if at least one of the corresponding bits in either\n/// operand is 1.\n///\n/// Parameters:\n///\n/// * `self` : The first integer operand.\n/// * `other` : The second integer operand.\n///\n/// Returns a new integer where each bit is set to 1 if at least one of the\n/// corresponding bits in either operand is 1, and 0 otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xF0F0 // 1111_0000_1111_0000\n/// let y = 0x0F0F // 0000_1111_0000_1111\n/// inspect(x | y, content=\"65535\") // 1111_1111_1111_1111 = 65535\n/// }\n/// ```\npub impl BitOr for Int with lor(self : Int, other : Int) -> Int = \"%i32_lor\"\n\n///|\n/// Performs a bitwise XOR operation between two integers.\n///\n/// Parameters:\n///\n/// * `self` : The first integer operand.\n/// * `other` : The second integer operand.\n///\n/// Returns a new integer where each bit is set to 1 if the corresponding bits in\n/// the operands are different, and 0 if they are the same.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xF0F0 // 1111_0000_1111_0000\n/// let y = 0x0F0F // 0000_1111_0000_1111\n/// inspect(x ^ y, content=\"65535\") // 1111_1111_1111_1111\n/// inspect(x ^ x, content=\"0\") // XOR with self gives 0\n/// }\n/// ```\npub impl BitXOr for Int with lxor(self : Int, other : Int) -> Int = \"%i32_lxor\"\n\n///|\n/// Performs a left shift operation on a 32-bit integer. Shifts each bit in the\n/// integer to the left by the specified number of positions, filling the\n/// rightmost positions with zeros.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift. Must be a non-negative value\n/// less than 32. Values outside this range will be masked with `& 31`.\n///\n/// Returns a new integer with bits shifted left by the specified number of\n/// positions. For each position shifted, the rightmost bit is filled with 0, and\n/// the leftmost bit is discarded.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1\n/// inspect(x << 3, content=\"8\") // Binary: 1 -> 1000\n/// let y = -4\n/// inspect(y << 2, content=\"-16\") // Binary: 100 -> 10000\n/// }\n/// ```\npub impl Shl for Int with shl(self, other) = \"%i32_shl\"\n\n///|\n/// Performs an arithmetic right shift operation on an integer value. Shifts the\n/// bits of the first operand to the right by the number of positions specified\n/// by the second operand. The sign bit is preserved and copied to the leftmost\n/// positions.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift the bits to the right. Must be\n/// non-negative.\n///\n/// Returns an integer representing the result of the arithmetic right shift\n/// operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = -16\n/// inspect(n >> 2, content=\"-4\") // Sign bit is preserved during shift\n/// let p = 16\n/// inspect(p >> 2, content=\"4\") // Regular right shift for positive numbers\n/// }\n/// ```\npub impl Shr for Int with shr(self, other) = \"%i32_shr\"\n\n///|\n/// Performs a left shift operation on a 32-bit integer. Shifts each bit in the\n/// integer to the left by the specified number of positions, filling the vacated\n/// bit positions with zeros.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift the bits to the left.\n///\n/// Returns an integer containing the result of shifting `self` left by `shift`\n/// positions.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1\n/// inspect(x << 3, content=\"8\") // Binary: 1 -> 1000\n/// let y = 42\n/// inspect(y << 2, content=\"168\") // Binary: 101010 -> 10101000\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `<<` instead\")\n#coverage.skip\npub fn Int::lsl(self : Int, other : Int) -> Int = \"%i32_shl\"\n\n///|\n/// Performs a left shift operation on a 32-bit integer. Shifts the bits of the\n/// first operand to the left by the specified number of positions. The rightmost\n/// positions are filled with zeros.\n///\n/// Parameters:\n///\n/// * `value` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift left. Must be non-negative and\n/// less than 32.\n///\n/// Returns a new integer value after performing the left shift operation. The\n/// value is equal to multiplying the input by 2 raised to the power of the shift\n/// count.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1\n/// inspect(x << 3, content=\"8\") // Equivalent to x << 3\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `<<` instead\")\n#coverage.skip\npub fn Int::shl(self : Int, other : Int) -> Int = \"%i32_shl\"\n\n///|\n/// Performs a logical right shift operation on a signed 32-bit integer. In a\n/// logical right shift, zeros are shifted in from the left, regardless of the\n/// sign bit. This function is DEPRECATED and users should use `UInt` type with\n/// the infix operator `>>` instead.\n///\n/// Parameters:\n///\n/// * `self` : The signed 32-bit integer value to be shifted.\n/// * `shift` : The number of positions to shift right. Must be non-negative.\n///\n/// Returns a signed 32-bit integer containing the same bits as if the input were\n/// treated as an unsigned integer and shifted right logically.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = -4 // Binary: 11111...11100\n/// let unsigned = x.reinterpret_as_uint() // Convert to UInt first\n/// inspect(unsigned >> 1, content=\"2147483646\") // Using the recommended operator\n/// }\n/// ```\n///\n#deprecated(\"Use UInt type and infix operator `>>` instead\")\n#coverage.skip\npub fn Int::lsr(self : Int, other : Int) -> Int {\n (self.reinterpret_as_uint() >> other).reinterpret_as_int()\n}\n\n///|\n/// Performs an arithmetic right shift operation on a 32-bit integer value,\n/// preserving the sign bit by replicating it into the positions vacated by the\n/// shift. This is a deprecated function; use the infix operator `>>` instead.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift right. Must be non-negative.\n///\n/// Returns a new integer value that is the result of arithmetically shifting\n/// `self` right by `shift` positions.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = -16\n/// inspect(x >> 2, content=\"-4\") // Right shift preserves sign bit\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `>>` instead\")\n#coverage.skip\npub fn Int::asr(self : Int, other : Int) -> Int = \"%i32_shr\"\n\n///|\n/// Performs an arithmetic right shift operation on a 32-bit integer by the\n/// specified number of positions. The operation preserves the sign bit,\n/// replicating it into the positions vacated by the shift.\n///\n/// Parameters:\n///\n/// * `self` : The integer value to be shifted.\n/// * `shift` : The number of positions to shift right.\n///\n/// Returns a new integer representing the result of shifting `self` right by\n/// `shift` positions.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = -1024\n/// inspect(n >> 3, content=\"-128\") // Preserves sign bit during right shift\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `>>` instead\")\n#coverage.skip\npub fn Int::shr(self : Int, other : Int) -> Int = \"%i32_shr\"\n\n///|\n/// Counts the number of consecutive zero bits at the least significant end of\n/// the integer's binary representation.\n///\n/// Parameters:\n///\n/// * `self` : The integer value whose trailing zeros are to be counted.\n///\n/// Returns the number of trailing zero bits (0 to 32). For example, returns 0 if\n/// the value is odd (least significant bit is 1), returns 32 if the value is 0\n/// (all bits are zeros).\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0\n/// inspect(x.ctz(), content=\"32\") // All bits are zero\n/// let y = 1\n/// inspect(y.ctz(), content=\"0\") // No trailing zeros\n/// let z = 16\n/// inspect(z.ctz(), content=\"4\") // Binary: ...10000\n/// }\n/// ```\npub fn Int::ctz(self : Int) -> Int = \"%i32_ctz\"\n\n///|\n/// Count leading zero bits in a 32-bit integer.\npub fn Int::clz(self : Int) -> Int = \"%i32_clz\"\n\n///|\n/// Counts the number of set bits (1s) in the binary representation of a 32-bit\n/// integer.\n///\n/// Parameters:\n///\n/// * `self` : The 32-bit integer whose bits are to be counted.\n///\n/// Returns the number of bits set to 1 in the binary representation of the input\n/// integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0b1011 // Binary: 1011 (3 bits set)\n/// inspect(x.popcnt(), content=\"3\")\n/// let y = -1 // All bits set in two's complement\n/// inspect(y.popcnt(), content=\"32\")\n/// }\n/// ```\npub fn Int::popcnt(self : Int) -> Int = \"%i32_popcnt\"\n\n///|\n/// Compares two integers for equality.\n///\n/// Parameters:\n///\n/// * `self` : The first integer to compare.\n/// * `other` : The second integer to compare.\n///\n/// Returns `true` if both integers have the same value, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42 == 42, content=\"true\")\n/// inspect(42 == -42, content=\"false\")\n/// }\n/// ```\npub impl Eq for Int with equal(self : Int, other : Int) -> Bool = \"%i32_eq\"\n\n///|\n/// Compares two integers for inequality.\n///\n/// Parameters:\n///\n/// * `self` : The first integer to compare.\n/// * `other` : The second integer to compare.\n///\n/// Returns `true` if the integers have different values, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42 != 42, content=\"false\")\n/// inspect(42 != -42, content=\"true\")\n/// }\n/// ```\npub impl Eq for Int with not_equal(self : Int, other : Int) -> Bool = \"%i32_ne\"\n\n///|\n/// Compares two integers and returns their relative order.\n///\n/// Parameters:\n///\n/// * `self` : The first integer to compare.\n/// * `other` : The second integer to compare against.\n///\n/// Returns an integer indicating the relative order:\n///\n/// * A negative value if `self` is less than `other`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other`\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42\n/// let b = 24\n/// inspect(a.compare(b), content=\"1\") // 42 > 24\n/// inspect(b.compare(a), content=\"-1\") // 24 < 42\n/// inspect(a.compare(a), content=\"0\") // 42 = 42\n/// }\n/// ```\npub impl Compare for Int with compare(self, other) = \"%i32_compare\"\n\n///|\npub impl Compare for Int with op_lt(x, y) = \"%i32.lt\"\n\n///|\npub impl Compare for Int with op_le(x, y) = \"%i32.le\"\n\n///|\npub impl Compare for Int with op_gt(x, y) = \"%i32.gt\"\n\n///|\npub impl Compare for Int with op_ge(x, y) = \"%i32.ge\"\n\n///|\n/// Return `true` if integer is strictly positive.\npub fn Int::is_pos(self : Int) -> Bool = \"%i32_is_pos\"\n\n///|\n/// Tests whether an integer is negative.\n///\n/// Parameters:\n///\n/// * `self` : The integer to test.\n///\n/// Returns `true` if the integer is negative, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let neg = -42\n/// let zero = 0\n/// let pos = 42\n/// inspect(neg.is_neg(), content=\"true\")\n/// inspect(zero.is_neg(), content=\"false\")\n/// inspect(pos.is_neg(), content=\"false\")\n/// }\n/// ```\npub fn Int::is_neg(self : Int) -> Bool = \"%i32_is_neg\"\n\n///|\n/// Return `true` if integer is non-positive (`<= 0`).\npub fn Int::is_non_pos(self : Int) -> Bool = \"%i32_is_non_pos\"\n\n///|\n/// Return `true` if integer is non-negative (`>= 0`).\npub fn Int::is_non_neg(self : Int) -> Bool = \"%i32_is_non_neg\"\n\n///|\n/// Returns the default value for integers, which is 0.\n///\n/// Returns an integer value of 0.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x : Int = Int::default()\n/// inspect(x, content=\"0\")\n/// }\n/// ```\npub impl Default for Int with default() = \"%i32_default\"\n\n///|\n/// Converts a 32-bit integer to a double-precision floating-point number. The\n/// conversion preserves the exact value since all integers in the range of `Int`\n/// can be represented exactly as `Double` values.\n///\n/// Parameters:\n///\n/// * `self` : The 32-bit integer to be converted.\n///\n/// Returns a double-precision floating-point number that represents the same\n/// numerical value as the input integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42\n/// inspect(n.to_double(), content=\"42\")\n/// let neg = -42\n/// inspect(neg.to_double(), content=\"-42\")\n/// }\n/// ```\npub fn Int::to_double(self : Int) -> Double = \"%i32_to_f64\"\n\n///|\n/// Converts a double-precision floating-point number to an unsigned 32-bit\n/// integer by truncating the decimal part. When the input is NaN or negative,\n/// returns 0. When the input exceeds the maximum value of UInt (4294967295),\n/// returns 4294967295.\n///\n/// Parameters:\n///\n/// * `value` : The double-precision floating-point number to be converted.\n///\n/// Returns an unsigned 32-bit integer representing the truncated value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(UInt::trunc_double(42.75), content=\"42\")\n/// }\n/// ```\npub fn UInt::trunc_double(val : Double) -> UInt = \"%f64.to_u32\"\n\n///|\n/// reinterpret the signed int as unsigned int, when the value is\n/// non-negative, i.e, 0..=2^31-1, the value is the same. When the\n/// value is negative, it turns into a large number,\n/// for example, -1 turns into 2^32-1\npub fn Int::reinterpret_as_uint(self : Int) -> UInt = \"%i32.to_u32_reinterpret\"\n\n///|\n/// Reinterprets a signed 32-bit integer as an unsigned 32-bit integer. For\n/// numbers within the range \\[0, 2^31-1], the value remains the same. For\n/// negative numbers, they are reinterpreted as large positive numbers in the\n/// range \\[2^31, 2^32-1].\n///\n/// Parameters:\n///\n/// * `value` : The signed 32-bit integer to be reinterpreted.\n///\n/// Returns an unsigned 32-bit integer that has the same bit pattern as the\n/// input.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let pos = 42\n/// let neg = -1\n/// inspect(pos.reinterpret_as_uint(), content=\"42\")\n/// inspect(neg.reinterpret_as_uint(), content=\"4294967295\") // 2^32 - 1\n/// }\n/// ```\n///\n#deprecated(\"Use `reinterpret_as_uint` instead\")\n#coverage.skip\npub fn Int::to_uint(self : Int) -> UInt = \"%i32.to_u32_reinterpret\"\n// Double primitive ops\n\n///|\n/// Converts a 32-bit signed integer to an unsigned 64-bit integer by first\n/// converting it to a signed 64-bit integer and then reinterpreting the bits as\n/// an unsigned value.\n///\n/// Parameters:\n///\n/// * `value` : The 32-bit signed integer to be converted.\n///\n/// Returns an unsigned 64-bit integer representing the same bit pattern as the\n/// input value when extended to 64 bits.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let pos = 42\n/// inspect(pos.to_uint64(), content=\"42\")\n/// let neg = -1\n/// inspect(neg.to_uint64(), content=\"18446744073709551615\") // 2^64 - 1\n/// }\n/// ```\npub fn Int::to_uint64(self : Int) -> UInt64 {\n self.to_int64().reinterpret_as_uint64()\n}\n\n///|\n/// Negates a double-precision floating-point number. For non-NaN inputs, changes\n/// the sign of the number. For NaN inputs, returns NaN.\n///\n/// Parameters:\n///\n/// * `number` : The double-precision floating-point number to negate.\n///\n/// Returns a new double-precision floating-point number that is the negation of\n/// the input number.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(-42.0, content=\"-42\")\n/// inspect(42.0, content=\"42\")\n/// inspect(-(0.0 / 0.0), content=\"NaN\") // Negating NaN returns NaN\n/// }\n/// ```\npub impl Neg for Double with neg(self) = \"%f64_neg\"\n\n///|\n/// Adds two double-precision floating-point numbers together following IEEE 754\n/// standards.\n///\n/// Parameters:\n///\n/// * `self` : The first double-precision floating-point number.\n/// * `other` : The second double-precision floating-point number to add.\n///\n/// Returns the sum of the two numbers. Special cases follow IEEE 754 rules:\n///\n/// * If either operand is NaN, returns NaN\n/// * If adding +∞ and -∞, returns NaN\n/// * If adding ±∞ with any finite number, returns ±∞\n/// * If adding +0.0 and -0.0, returns +0.0\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(2.5 + 3.7, content=\"6.2\")\n/// inspect(1.0 / 0.0 + -1.0 / 0.0, content=\"NaN\") // Infinity + -Infinity = NaN\n/// }\n/// ```\npub impl Add for Double with add(self, other) = \"%f64_add\"\n\n///|\n/// Performs subtraction between two double-precision floating-point numbers.\n///\n/// Parameters:\n///\n/// * `self` : The first operand (minuend).\n/// * `other` : The second operand (subtrahend).\n///\n/// Returns the difference between the two numbers according to IEEE 754\n/// double-precision arithmetic rules.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 5.0\n/// let b = 3.0\n/// inspect(a - b, content=\"2\")\n/// inspect(0.0 / 0.0 - 1.0, content=\"NaN\") // NaN - anything = NaN\n/// }\n/// ```\npub impl Sub for Double with sub(self, other) = \"%f64_sub\"\n\n///|\n/// Multiplies two double-precision floating-point numbers. This is the\n/// implementation of the `*` operator for `Double` type.\n///\n/// Parameters:\n///\n/// * `self` : The first double-precision floating-point operand.\n/// * `other` : The second double-precision floating-point operand.\n///\n/// Returns a new double-precision floating-point number representing the product\n/// of the two operands. Special cases follow IEEE 754 standard:\n///\n/// * If either operand is NaN, returns NaN\n/// * If one operand is infinity and the other is zero, returns NaN\n/// * If one operand is infinity and the other is a non-zero finite number,\n/// returns infinity with the appropriate sign\n/// * If both operands are infinity, returns infinity with the appropriate sign\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(2.5 * 2.0, content=\"5\")\n/// inspect(-2.0 * 3.0, content=\"-6\")\n/// let nan = 0.0 / 0.0 // NaN\n/// inspect(nan * 1.0, content=\"NaN\")\n/// }\n/// ```\npub impl Mul for Double with mul(self, other) = \"%f64_mul\"\n\n///|\n/// Performs division between two double-precision floating-point numbers.\n/// Follows IEEE 754 standard for floating-point arithmetic, including handling\n/// of special cases like division by zero (returns infinity) and operations\n/// involving NaN.\n///\n/// Parameters:\n///\n/// * `self` : The dividend (numerator) in the division operation.\n/// * `other` : The divisor (denominator) in the division operation.\n///\n/// Returns the result of dividing `self` by `other`. Special cases follow IEEE\n/// 754:\n///\n/// * Division by zero returns positive or negative infinity based on the\n/// dividend's sign\n/// * Operations involving NaN return NaN\n/// * Division of infinity by infinity returns NaN\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(6.0 / 2.0, content=\"3\")\n/// inspect(-6.0 / 2.0, content=\"-3\")\n/// inspect(1.0 / 0.0, content=\"Infinity\")\n/// }\n/// ```\npub impl Div for Double with div(self, other) = \"%f64_div\"\n\n///|\n/// Calculates the square root of a double-precision floating-point number. For\n/// non-negative numbers, returns the positive square root. For negative numbers\n/// or NaN, returns NaN.\n///\n/// Parameters:\n///\n/// * `self` : The double-precision floating-point number whose square root is to\n/// be calculated.\n///\n/// Returns the square root of the input number, or NaN if the input is negative\n/// or NaN.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(4.0.sqrt(), content=\"2\")\n/// inspect(0.0.sqrt(), content=\"0\")\n/// inspect((-1.0).sqrt(), content=\"NaN\")\n/// }\n/// ```\npub fn Double::sqrt(self : Double) -> Double = \"%f64_sqrt\"\n\n///|\n/// Compares two double-precision floating-point numbers for equality following\n/// IEEE 754 rules. Returns `true` if both numbers are equal, including when both\n/// are `NaN`. Note that this differs from the standard IEEE 754 behavior where\n/// `NaN` is not equal to any value, including itself.\n///\n/// Parameters:\n///\n/// * `self` : The first double-precision floating-point number to compare.\n/// * `other` : The second double-precision floating-point number to compare.\n///\n/// Returns `true` if both numbers are equal, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 3.14\n/// let b = 3.14\n/// let c = 2.718\n/// inspect(a == b, content=\"true\")\n/// inspect(a == c, content=\"false\")\n/// let nan = 0.0 / 0.0 // NaN\n/// inspect(nan == nan, content=\"false\") // NaN != NaN\n/// }\n/// ```\npub impl Eq for Double with equal(self : Double, other : Double) -> Bool = \"%f64_eq\"\n\n///|\n/// Compares two double-precision floating-point numbers for inequality following\n/// IEEE 754 rules. Returns `true` if the numbers are not equal.\n///\n/// Parameters:\n///\n/// * `self` : The first double-precision floating-point number to compare.\n/// * `other` : The second double-precision floating-point number to compare.\n///\n/// Returns `true` if the numbers are not equal, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 3.14\n/// let b = 3.14\n/// let c = 2.718\n/// inspect(a != b, content=\"false\")\n/// inspect(a != c, content=\"true\")\n/// let nan = 0.0 / 0.0 // NaN\n/// inspect(nan != nan, content=\"true\") // NaN != NaN is true\n/// }\n/// ```\npub impl Eq for Double with not_equal(self : Double, other : Double) -> Bool = \"%f64_ne\"\n\n///|\n/// Deprecated inequality helper; use `a != b`.\n/// Operator helper `op_neq`.\n#deprecated(\"Use `a != b` instead\")\n#doc(hidden)\npub fn Double::op_neq(self : Double, other : Double) -> Bool = \"%f64_ne\"\n\n///|\n/// Compares two double-precision floating-point numbers and returns their\n/// relative order. Follows IEEE 754 rules for floating-point comparisons,\n/// including handling of special values like NaN.\n///\n/// Parameters:\n///\n/// * `self` : The first double-precision floating-point number to compare.\n/// * `other` : The second double-precision floating-point number to compare\n/// against.\n///\n/// Returns an integer indicating the relative order:\n///\n/// * A negative value if `self` is less than `other`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other`\n/// * If either value is NaN, returns an implementation-defined value that is\n/// consistent with total ordering\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 3.14\n/// let b = 2.718\n/// inspect(a.compare(b), content=\"1\") // 3.14 > 2.718\n/// inspect(b.compare(a), content=\"-1\") // 2.718 < 3.14\n/// inspect(a.compare(a), content=\"0\") // 3.14 = 3.14\n/// }\n/// ```\npub impl Compare for Double with compare(self, other) = \"%f64_compare\"\n\n///|\npub impl Compare for Double with op_lt(x, y) = \"%f64.lt\"\n\n///|\npub impl Compare for Double with op_le(x, y) = \"%f64.le\"\n\n///|\npub impl Compare for Double with op_gt(x, y) = \"%f64.gt\"\n\n///|\npub impl Compare for Double with op_ge(x, y) = \"%f64.ge\"\n\n///|\n/// Returns the default value for double-precision floating-point numbers (0.0).\n///\n/// Returns a `Double` value initialized to 0.0.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(Double::default(), content=\"0\")\n/// }\n/// ```\npub impl Default for Double with default() = \"%f64_default\"\n\n///|\n/// Converts an unsigned 32-bit integer to a double-precision floating-point\n/// number. Since the range of unsigned 32-bit integers is smaller than what can\n/// be precisely represented by a double-precision floating-point number, this\n/// conversion is guaranteed to be exact.\n///\n/// Parameters:\n///\n/// * `value` : The unsigned 32-bit integer to be converted.\n///\n/// Returns a double-precision floating-point number that exactly represents the\n/// input value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42U\n/// inspect(Double::convert_uint(n), content=\"42\")\n/// let max = 4294967295U // maximum value of UInt\n/// inspect(Double::convert_uint(max), content=\"4294967295\")\n/// }\n/// ```\npub fn Double::convert_uint(val : UInt) -> Double = \"%u32.to_f64\"\n\n// Char primitive ops\n\n///|\n/// Converts a character to its Unicode code point value as an integer.\n///\n/// Parameters:\n///\n/// * `self` : The character to be converted.\n///\n/// Returns an integer representing the Unicode code point value of the\n/// character.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect('A'.to_int(), content=\"65\") // ASCII value of 'A'\n/// inspect('あ'.to_int(), content=\"12354\") // Unicode code point of 'あ'\n/// }\n/// ```\npub fn Char::to_int(self : Char) -> Int = \"%char_to_int\"\n\n///|\n/// Converts a Unicode character to its unsigned 32-bit integer code point\n/// representation. The character's code point value is first converted to a\n/// signed integer and then reinterpreted as an unsigned integer.\n///\n/// Parameters:\n///\n/// * `character` : The Unicode character to be converted.\n///\n/// Returns an unsigned 32-bit integer representing the character's Unicode code\n/// point.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let c = 'A'\n/// inspect(c.to_uint(), content=\"65\") // ASCII value of 'A'\n/// let emoji = '🤣'\n/// inspect(emoji.to_uint(), content=\"129315\") // Unicode code point U+1F923\n/// }\n/// ```\npub fn Char::to_uint(self : Char) -> UInt {\n self.to_int().reinterpret_as_uint()\n}\n\n///|\n/// Deprecated constructor from raw code point.\n/// Create from `int`.\n#deprecated(\"Use `Int::unsafe_to_char` instead, and use `Int::to_char` for safe conversion\")\npub fn Char::from_int(val : Int) -> Char = \"%char_from_int\"\n\n///|\n/// Compares two characters for equality.\n///\n/// Parameters:\n///\n/// * `self` : The first character to compare.\n/// * `other` : The second character to compare.\n///\n/// Returns `true` if both characters represent the same Unicode code point,\n/// `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 'A'\n/// let b = 'A'\n/// let c = 'B'\n/// inspect(a == b, content=\"true\")\n/// inspect(a == c, content=\"false\")\n/// }\n/// ```\npub impl Eq for Char with equal(self : Char, other : Char) -> Bool = \"%char_eq\"\n\n///|\n/// Compares two characters for inequality.\n///\n/// Parameters:\n///\n/// * `self` : The first character to compare.\n/// * `other` : The second character to compare.\n///\n/// Returns `true` if the characters represent different Unicode code points,\n/// `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 'A'\n/// let b = 'A'\n/// let c = 'B'\n/// inspect(a != b, content=\"false\")\n/// inspect(a != c, content=\"true\")\n/// }\n/// ```\npub impl Eq for Char with not_equal(self : Char, other : Char) -> Bool = \"%i32_ne\"\n\n///|\n/// Compares two characters based on their Unicode code points. Returns a\n/// negative value if the first character comes before the second, zero if they\n/// are equal, and a positive value if the first character comes after the\n/// second.\n///\n/// Parameters:\n///\n/// * `self` : The first character to compare.\n/// * `other` : The second character to compare against.\n///\n/// Returns an integer indicating the relative ordering:\n///\n/// * A negative value if `self` is less than `other`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other`\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect('a'.compare('b'), content=\"-1\")\n/// inspect('b'.compare('a'), content=\"1\")\n/// inspect('a'.compare('a'), content=\"0\")\n/// }\n/// ```\npub impl Compare for Char with compare(self, other) = \"%char_compare\"\n\n///|\npub impl Compare for Char with op_lt(x, y) = \"%i32.lt\"\n\n///|\npub impl Compare for Char with op_le(x, y) = \"%i32.le\"\n\n///|\npub impl Compare for Char with op_gt(x, y) = \"%i32.gt\"\n\n///|\npub impl Compare for Char with op_ge(x, y) = \"%i32.ge\"\n\n///|\n/// Returns the default value for the `Char` type, which is the null character\n/// (`'\\x00'`).\n///\n/// Returns a `Char` value representing the null character.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(Char::default().to_string() == \"\\u0000\")\n/// }\n/// ```\npub impl Default for Char with default() = \"%char_default\"\n\n// Bytes primitive ops\n\n///|\n/// Retrieves a byte at the specified index from a byte sequence.\n///\n/// Parameters:\n///\n/// * `bytes` : The byte sequence to access.\n/// * `index` : The position in the byte sequence from which to retrieve the\n/// byte.\n///\n/// Returns a byte value from the specified position in the sequence.\n///\n/// Throws a panic if the index is negative or greater than or equal to the\n/// length of the byte sequence.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = b\"\\x01\\x02\\x03\"\n/// inspect(bytes[1], content=\"b'\\\\x02'\")\n/// }\n/// ```\n#alias(\"_[_]\")\npub fn Bytes::at(self : Bytes, idx : Int) -> Byte = \"%bytes_get\"\n\n///|\n/// Retrieves a byte at the specified index from a byte sequence without\n/// performing bounds checking. This is a low-level operation that should be used\n/// with caution.\n///\n/// Parameters:\n///\n/// * `bytes` : The byte sequence to retrieve the byte from.\n/// * `index` : The position in the byte sequence from which to retrieve the\n/// byte.\n///\n/// Returns a single byte from the specified position in the byte sequence.\n///\n/// Throws a panic if the index is negative or greater than or equal to the\n/// length of the byte sequence.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = b\"\\x01\\x02\\x03\"\n/// inspect(bytes.unsafe_get(1), content=\"b'\\\\x02'\")\n/// }\n/// ```\n///\n#internal(unsafe, \"Panic if index is out of bounds\")\n#doc(hidden)\npub fn Bytes::unsafe_get(self : Bytes, idx : Int) -> Byte = \"%bytes.unsafe_get\"\n\n///|\n/// Returns the number of bytes in a byte sequence.\n///\n/// Parameters:\n///\n/// * `bytes` : The byte sequence whose length is to be determined.\n///\n/// Returns an integer representing the length (number of bytes) of the sequence.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = b\"\\x01\\x02\\x03\"\n/// inspect(bytes.length(), content=\"3\")\n/// let empty = b\"\"\n/// inspect(empty.length(), content=\"0\")\n/// }\n/// ```\npub fn Bytes::length(self : Bytes) -> Int = \"%bytes_length\"\n\n///|\n/// Creates a new byte sequence of the specified length, where each byte is\n/// initialized to the given value. Returns an empty byte sequence if the\n/// length is negative.\n///\n/// Parameters:\n///\n/// * `length` : The length of the byte sequence to create. Must be non-negative.\n/// * `initial_value` : The byte value used to initialize each position in the\n/// sequence.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = Bytes::make(3, b'\\xFF')\n/// inspect(\n/// bytes,\n/// content=(\n/// #|b\"\\xff\\xff\\xff\"\n/// ),\n/// )\n/// let empty = Bytes::make(0, b'\\x00')\n/// inspect(empty, content=\"b\\\"\\\"\")\n/// }\n/// ```\npub fn Bytes::make(len : Int, init : Byte) -> Bytes {\n if len < 0 {\n return []\n }\n Bytes::unsafe_make(len, init)\n}\n\n///|\nfn Bytes::unsafe_make(len : Int, init : Byte) -> Bytes = \"%bytes_make\"\n\n///|\n/// Creates a new byte sequence filled with zero bytes.\n///\n/// Parameters:\n///\n/// * `length` : The length of the byte sequence to create. Must be a\n/// non-negative integer.\n///\n/// Returns a new byte sequence of the specified length, with all bytes\n/// initialized to zero.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let bytes = Bytes::new(3)\n/// inspect(bytes, content=\"b\\\"\\\\x00\\\\x00\\\\x00\\\"\")\n/// let bytes = Bytes::new(0)\n/// inspect(bytes, content=\"b\\\"\\\"\")\n/// }\n/// ```\npub fn Bytes::new(len : Int) -> Bytes {\n Bytes::make(len, b'\\x00')\n}\n\n///|\n/// Converts a 32-bit signed integer to a byte by taking its least significant 8\n/// bits. Any bits beyond the first 8 bits are truncated.\n///\n/// Parameters:\n///\n/// * `value` : The 32-bit signed integer to be converted. Only the least\n/// significant 8 bits will be used.\n///\n/// Returns a byte containing the least significant 8 bits of the input integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 258 // In binary: 100000010\n/// inspect(n.to_byte(), content=\"b'\\\\x02'\") // Only keeps 00000010\n/// let neg = -1 // In binary: all 1's\n/// inspect(neg.to_byte(), content=\"b'\\\\xFF'\") // Only keeps 11111111\n/// }\n/// ```\npub fn Int::to_byte(self : Int) -> Byte = \"%i32_to_byte\"\n\n///|\n/// Convert integer to char without validity checks.\n///\n/// Undefined behavior for surrogate or out-of-range values.\npub fn Int::unsafe_to_char(self : Int) -> Char = \"%char_from_int\"\n\n///|\n/// Convert integer to `Char` if it is a valid Unicode scalar value.\npub fn Int::to_char(self : Int) -> Char? {\n if self is (0..=0xD7FF) || self is (0xE000..=0x10FFFF) {\n Some(self.unsafe_to_char())\n } else {\n None\n }\n}\n\n///|\n/// Converts an unsigned 64-bit integer to a byte by truncating it to fit within\n/// the byte range (0 to 255).\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 64-bit integer to be converted.\n///\n/// Returns a byte containing the least significant 8 bits of the input integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 258UL // In binary: 100000010\n/// inspect(n.to_byte(), content=\"b'\\\\x02'\") // Only keeps 00000010\n/// }\n/// ```\npub fn UInt64::to_byte(self : UInt64) -> Byte {\n self.to_int().to_byte()\n}\n\n// FixedArray primitive ops\n\n///|\n/// Retrieves an element at the specified index from a fixed-size array. This\n/// function implements the array indexing operator `[]`.\n///\n/// Parameters:\n///\n/// * `array` : The fixed-size array to access.\n/// * `index` : The position in the array from which to retrieve the element.\n///\n/// Returns the element at the specified index.\n///\n/// Panics if the index is out of bounds.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = FixedArray::make(3, 42)\n/// inspect(arr[1], content=\"42\")\n/// }\n/// ```\n#alias(\"_[_]\")\npub fn[T] FixedArray::at(self : FixedArray[T], idx : Int) -> T = \"%fixedarray.get\"\n\n///|\n/// Retrieves an element from a fixed-size array at the specified index without\n/// performing bounds checking. This is an unsafe operation that may cause\n/// undefined behavior if used incorrectly.\n///\n/// Parameters:\n///\n/// * `array` : The fixed-size array to retrieve the element from.\n/// * `index` : The position in the array from which to retrieve the element.\n///\n/// Returns the element at the specified index in the array.\n///\n/// Throws a panic if the index is out of bounds (negative or greater than or\n/// equal to the array's length).\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = FixedArray::make(3, 42)\n/// inspect(arr.unsafe_get(1), content=\"42\")\n/// }\n/// ```\n///\n#internal(unsafe, \"Panic if index is out of bounds\")\n#doc(hidden)\npub fn[T] FixedArray::unsafe_get(self : FixedArray[T], idx : Int) -> T = \"%fixedarray.unsafe_get\"\n\n///|\n/// Set fixed-array element without safe bounds checks.\n/// Unsafe variant of `set`.\n#internal(unsafe, \"Panic if index is out of bounds\")\n#doc(hidden)\npub fn[T] FixedArray::unsafe_set(\n self : FixedArray[T],\n idx : Int,\n val : T,\n) -> Unit = \"%fixedarray.unsafe_set\"\n\n///|\n/// Sets the value at the specified index in a fixed-size array.\n///\n/// Parameters:\n///\n/// * `array` : The fixed-size array to be modified.\n/// * `index` : The index at which to set the value. Must be non-negative and\n/// less than the array's length.\n/// * `value` : The value to be set at the specified index.\n///\n/// Throws a runtime error if the index is out of bounds (less than 0 or greater\n/// than or equal to the array's length).\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = FixedArray::make(3, 0)\n/// arr.set(1, 42)\n/// inspect(arr[1], content=\"42\")\n/// }\n/// ```\n#alias(\"_[_]=_\")\npub fn[T] FixedArray::set(self : FixedArray[T], idx : Int, val : T) -> Unit = \"%fixedarray.set\"\n\n///|\n/// Returns the number of elements in a fixed-size array.\n///\n/// Parameters:\n///\n/// * `array` : The fixed-size array whose length is to be determined.\n///\n/// Returns an integer representing the number of elements in the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = FixedArray::make(3, 42)\n/// inspect(arr.length(), content=\"3\")\n/// }\n/// ```\npub fn[T] FixedArray::length(self : FixedArray[T]) -> Int = \"%fixedarray.length\"\n\n///|\n/// Creates a new fixed-size array with the specified length, initializing all\n/// elements with the given value.\n///\n/// Parameters:\n///\n/// * `length` : The length of the array to create. Must be non-negative.\n/// * `initial_value` : The value used to initialize all elements in the array.\n///\n/// Returns a new fixed-size array of type `FixedArray[T]` with `length`\n/// elements, where each element is initialized to `initial_value`.\n///\n/// Throws a panic if `length` is negative.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = FixedArray::make(3, 42)\n/// inspect(arr[0], content=\"42\")\n/// inspect(arr.length(), content=\"3\")\n/// }\n/// ```\n/// \n/// WARNING: A common pitfall is creating with the same initial value, for example:\n/// ```mbt check\n/// test {\n/// let two_dimension_array = FixedArray::make(10, FixedArray::make(10, 0))\n/// two_dimension_array[0][5] = 10\n/// assert_eq(two_dimension_array[5][5], 10)\n/// }\n/// ```\n/// This is because all the cells reference to the same object (the FixedArray[Int] in this case). \n/// One should use makei() instead which creates an object for each index.\npub fn[T] FixedArray::make(len : Int, init : T) -> FixedArray[T] = \"%fixedarray.make\"\n\n// String primitive ops\n\n///|\n/// Returns the number of UTF-16 code units in the string. Note that this is not\n/// necessarily equal to the number of Unicode characters (code points) in the\n/// string, as some characters may be represented by multiple UTF-16 code units.\n///\n/// Parameters:\n///\n/// * `string` : The string whose length is to be determined.\n///\n/// Returns the number of UTF-16 code units in the string.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(\"hello\".length(), content=\"5\")\n/// inspect(\"🤣\".length(), content=\"2\") // Emoji uses two UTF-16 code units\n/// inspect(\"\".length(), content=\"0\") // Empty string\n/// }\n/// ```\n#alias(charcode_length, deprecated)\npub fn String::length(self : String) -> Int = \"%string_length\"\n\n///|\n/// Returns the UTF-16 code unit at the given index.\n/// \n/// This method has O(1) complexity.\n/// Panics if the index is out of bounds.\n#alias(\"_[_]\")\n#alias(code_unit_at)\npub fn String::at(self : String, idx : Int) -> UInt16 = \"%string_get\"\n\n///|\n/// Get string UTF-16 code unit without bounds checks.\n/// Unsafe variant of `get`.\n#internal(unsafe, \"Undefined behavior if index is out of bounds.\")\n#doc(hidden)\npub fn String::unsafe_get(self : String, idx : Int) -> UInt16 = \"%string.unsafe_get\"\n\n///|\n/// Returns the UTF-16 code unit at a given position in the string without\n/// performing bounds checking. This is a low-level function that provides direct\n/// access to the internal representation of the string.\n///\n/// Parameters:\n///\n/// * `string` : The string from which to retrieve the code unit.\n/// * `index` : The position of the code unit to retrieve.\n///\n/// Returns the UTF-16 code unit at the specified position as an integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let str = \"B🤣🤣C\"\n/// inspect(str.unsafe_get(0), content=\"66\") // 'B'\n/// inspect(str.unsafe_get(1), content=\"55358\") // First surrogate of 🤣\n/// inspect(str.unsafe_get(2), content=\"56611\") // Second surrogate of 🤣\n/// inspect(str.unsafe_get(3), content=\"55358\") // First surrogate of 🤣\n/// inspect(str.unsafe_get(4), content=\"56611\") // Second surrogate of 🤣\n/// inspect(str.unsafe_get(5), content=\"67\") // 'C'\n/// }\n/// ```\n/// TODO: rename to `unsafe_get`\n#internal(unsafe, \"Panic if index is out of bounds.\")\n#doc(hidden)\n#deprecated(\"Use `String::unsafe_get` instead\")\npub fn String::unsafe_charcode_at(self : String, idx : Int) -> Int = \"%string.unsafe_get\"\n\n///|\n/// Concatenates two strings, creating a new string that contains all characters\n/// from the first string followed by all characters from the second string.\n///\n/// Parameters:\n///\n/// * `self` : The first string to concatenate.\n/// * `other` : The second string to concatenate.\n///\n/// Returns a new string containing the concatenation of both input strings.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let hello = \"Hello\"\n/// let world = \" World!\"\n/// inspect(hello + world, content=\"Hello World!\")\n/// inspect(\"\" + \"abc\", content=\"abc\") // concatenating with empty string\n/// }\n/// ```\npub impl Add for String with add(self, other) = \"%string_add\"\n\n///|\n/// Tests whether two strings are equal by comparing their characters.\n///\n/// Parameters:\n///\n/// * `self` : The first string to compare.\n/// * `other` : The second string to compare.\n///\n/// Returns `true` if both strings contain exactly the same sequence of\n/// characters, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let str1 = \"hello\"\n/// let str2 = \"hello\"\n/// let str3 = \"world\"\n/// inspect(str1 == str2, content=\"true\")\n/// inspect(str1 == str3, content=\"false\")\n/// }\n/// ```\npub impl Eq for String with equal(self : String, other : String) -> Bool = \"%string_eq\"\n\n// For internal use only\n\n///|\npriv type UnsafeMaybeUninit[_]\n\n///|\n/// Converts a byte value to a 32-bit signed integer. The resulting integer will\n/// have the same binary representation as the byte value, preserving the\n/// numerical value in the range \\[0, 255].\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted to an integer.\n///\n/// Returns a 32-bit signed integer representing the same numerical value as the\n/// input byte.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b = b'\\xFF' // byte with value 255\n/// inspect(b.to_int(), content=\"255\")\n/// let zero = b'\\x00'\n/// inspect(zero.to_int(), content=\"0\")\n/// }\n/// ```\npub fn Byte::to_int(self : Byte) -> Int = \"%byte_to_int\"\n\n///|\n/// Converts a byte value to a character.\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted.\n///\n/// Returns the character corresponding to the byte value.\npub fn Byte::to_char(self : Byte) -> Char {\n self.to_int().unsafe_to_char()\n}\n\n///|\n/// Converts a byte value to a 64-bit signed integer by first converting it to a\n/// 32-bit integer and then extending it to a 64-bit integer.\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted.\n///\n/// Returns a 64-bit signed integer representing the same numerical value as the\n/// input byte.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b = b'\\xFF'\n/// inspect(b.to_int64(), content=\"255\")\n/// }\n/// ```\npub fn Byte::to_int64(self : Byte) -> Int64 {\n self.to_int().to_int64()\n}\n\n///|\n/// reinterpret the unsigned int as signed int\n/// For number within the range of 0..=2^31-1,\n/// the value is the same. For number within the range of 2^31..=2^32-1,\n/// the value is negative\npub fn UInt::reinterpret_as_int(self : UInt) -> Int = \"%u32.to_i32_reinterpret\"\n\n///|\n/// Reinterprets an unsigned 32-bit integer as a signed 32-bit integer. For\n/// values within the range of 0 to 2^31-1, the value remains the same. For\n/// values within the range of 2^31 to 2^32-1, the value becomes negative due to\n/// two's complement representation.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be reinterpreted.\n///\n/// Returns a signed 32-bit integer that has the same bit pattern as the input\n/// unsigned integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// inspect(a.reinterpret_as_int(), content=\"42\")\n/// let b = 4294967295U // maximum value of UInt (2^32 - 1)\n/// inspect(b.reinterpret_as_int(), content=\"-1\") // becomes -1 when reinterpreted as Int\n/// }\n/// ```\n///\n#deprecated(\"Use `reinterpret_as_int` instead\")\n#coverage.skip\npub fn UInt::to_int(self : UInt) -> Int = \"%u32.to_i32_reinterpret\"\n\n///|\n/// Performs addition between two unsigned 32-bit integers. If the result\n/// overflows, it wraps around according to the rules of modular arithmetic\n/// (2^32).\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned 32-bit integer operand.\n/// * `other` : The second unsigned 32-bit integer operand to be added.\n///\n/// Returns the sum of the two unsigned integers, wrapped around if necessary.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// let b = 100U\n/// inspect(a + b, content=\"142\")\n///\n/// // Demonstrate overflow behavior\n/// let max = 4294967295U // UInt::max_value\n/// inspect(max + 1U, content=\"0\")\n/// }\n/// ```\npub impl Add for UInt with add(self, other) = \"%u32.add\"\n\n///|\n/// Performs subtraction between two unsigned 32-bit integers. When the result\n/// would be negative, the function wraps around using modular arithmetic (2^32).\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned 32-bit integer (minuend).\n/// * `other` : The second unsigned 32-bit integer to subtract from the first\n/// (subtrahend).\n///\n/// Returns a new unsigned 32-bit integer representing the difference between the\n/// two numbers. If the result would be negative, it wraps around to a positive\n/// number by adding 2^32 repeatedly until the result is in range.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 5U\n/// let b = 3U\n/// inspect(a - b, content=\"2\")\n/// let c = 3U\n/// let d = 5U\n/// inspect(c - d, content=\"4294967294\") // wraps around to 2^32 - 2\n/// }\n/// ```\npub impl Sub for UInt with sub(self, other) = \"%u32.sub\"\n\n///|\n/// Performs multiplication between two unsigned 32-bit integers. The result\n/// wraps around if it exceeds the maximum value of `UInt`.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned integer operand.\n/// * `other` : The second unsigned integer operand.\n///\n/// Returns the product of the two unsigned integers. If the result exceeds the\n/// maximum value of `UInt` (4294967295), it wraps around to the corresponding\n/// value modulo 2^32.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 3U\n/// let b = 4U\n/// inspect(a * b, content=\"12\")\n/// let max = 4294967295U\n/// inspect(max * 2U, content=\"4294967294\") // Wraps around to max * 2 % 2^32\n/// }\n/// ```\npub impl Mul for UInt with mul(self, other) = \"%u32.mul\"\n\n///|\n/// Performs division between two unsigned 32-bit integers. The operation follows\n/// standard unsigned integer division rules, where the result is truncated\n/// towards zero.\n///\n/// Parameters:\n///\n/// * `self` : The dividend (the number to be divided).\n/// * `other` : The divisor (the number to divide by).\n///\n/// Returns an unsigned 32-bit integer representing the quotient of the division.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// let b = 5U\n/// inspect(a / b, content=\"8\") // Using infix operator\n/// }\n/// ```\npub impl Div for UInt with div(self, other) = \"%u32.div\"\n\n///|\n/// Calculates the remainder of dividing one unsigned integer by another.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned integer dividend.\n/// * `other` : The unsigned integer divisor.\n///\n/// Returns the remainder of the division operation.\n///\n/// Throws a panic if `other` is zero.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 17U\n/// let b = 5U\n/// inspect(a % b, content=\"2\") // 17 divided by 5 gives quotient 3 and remainder 2\n/// inspect(7U % 4U, content=\"3\")\n/// }\n/// ```\npub impl Mod for UInt with mod(self, other) = \"%u32.mod\"\n\n///|\n/// Compares two unsigned 32-bit integers for equality.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned integer operand.\n/// * `other` : The second unsigned integer operand to compare with.\n///\n/// Returns `true` if both integers have the same value, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// let b = 42U\n/// let c = 24U\n/// inspect(a == b, content=\"true\")\n/// inspect(a == c, content=\"false\")\n/// }\n/// ```\npub impl Eq for UInt with equal(self : UInt, other : UInt) -> Bool = \"%u32.eq\"\n\n///|\n/// Compares two unsigned 32-bit integers for inequality.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned integer operand.\n/// * `other` : The second unsigned integer operand to compare with.\n///\n/// Returns `true` if the integers have different values, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// let b = 42U\n/// let c = 24U\n/// inspect(a != b, content=\"false\")\n/// inspect(a != c, content=\"true\")\n/// }\n/// ```\npub impl Eq for UInt with not_equal(self : UInt, other : UInt) -> Bool = \"%u32.ne\"\n\n///|\n/// Deprecated inequality helper; use `a != b`.\n/// Operator helper `op_neq`.\n#deprecated(\"Use `a != b` instead\")\n#doc(hidden)\npub fn UInt::op_neq(self : UInt, other : UInt) -> Bool = \"%u32.ne\"\n\n///|\n/// Compares two unsigned 32-bit integers and returns their relative order.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned integer to compare.\n/// * `other` : The second unsigned integer to compare against.\n///\n/// Returns an integer indicating the relative order:\n///\n/// * A negative value if `self` is less than `other`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other`\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 42U\n/// let b = 24U\n/// inspect(a.compare(b), content=\"1\") // 42 > 24\n/// inspect(b.compare(a), content=\"-1\") // 24 < 42\n/// inspect(a.compare(a), content=\"0\") // 42 = 42\n/// }\n/// ```\npub impl Compare for UInt with compare(self, other) = \"%u32.compare\"\n\n///|\npub impl Compare for UInt with op_lt(x, y) = \"%u32.lt\"\n\n///|\npub impl Compare for UInt with op_le(x, y) = \"%u32.le\"\n\n///|\npub impl Compare for UInt with op_gt(x, y) = \"%u32.gt\"\n\n///|\npub impl Compare for UInt with op_ge(x, y) = \"%u32.ge\"\n\n///|\n/// Performs a bitwise AND operation between two unsigned 32-bit integers. For\n/// each bit position, the result is 1 if the bits at that position in both\n/// operands are 1, and 0 otherwise.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned 32-bit integer operand.\n/// * `other` : The second unsigned 32-bit integer operand.\n///\n/// Returns an unsigned 32-bit integer representing the result of the bitwise AND\n/// operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 0xF0F0U // 1111_0000_1111_0000\n/// let b = 0xFF00U // 1111_1111_0000_0000\n/// inspect(a & b, content=\"61440\") // 1111_0000_0000_0000 = 61440\n/// }\n/// ```\npub impl BitAnd for UInt with land(self : UInt, other : UInt) -> UInt = \"%u32.bitand\"\n\n///|\n/// Performs a bitwise OR operation between two unsigned 32-bit integers. For\n/// each bit position, the result is 1 if at least one of the corresponding bits\n/// in either operand is 1.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned 32-bit integer operand.\n/// * `other` : The second unsigned 32-bit integer operand.\n///\n/// Returns the result of the bitwise OR operation as an unsigned 32-bit integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 0xF0F0U // Binary: 1111_0000_1111_0000\n/// let b = 0x0F0FU // Binary: 0000_1111_0000_1111\n/// inspect(a | b, content=\"65535\") // Binary: 1111_1111_1111_1111\n/// }\n/// ```\npub impl BitOr for UInt with lor(self : UInt, other : UInt) -> UInt = \"%u32.bitor\"\n\n///|\n/// Performs a bitwise XOR (exclusive OR) operation between two unsigned 32-bit\n/// integers. Each bit in the result is set to 1 if the corresponding bits in the\n/// operands are different, and 0 if they are the same.\n///\n/// Parameters:\n///\n/// * `self` : The first unsigned 32-bit integer operand.\n/// * `other` : The second unsigned 32-bit integer operand.\n///\n/// Returns the result of the bitwise XOR operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = 0xFF00U // Binary: 1111_1111_0000_0000\n/// let b = 0x0F0FU // Binary: 0000_1111_0000_1111\n/// inspect(a ^ b, content=\"61455\") // Binary: 1111_0000_0000_1111\n/// }\n/// ```\npub impl BitXOr for UInt with lxor(self : UInt, other : UInt) -> UInt = \"%u32.bitxor\"\n\n///|\n/// Performs a bitwise NOT operation on an unsigned 32-bit integer. Flips all\n/// bits in the number (changes each 0 to 1 and each 1 to 0).\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer value on which to perform the bitwise\n/// NOT operation.\n///\n/// Returns a new unsigned 32-bit integer where each bit is inverted from the\n/// input value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xFF00U // Binary: 1111_1111_0000_0000\n/// inspect(x.lnot(), content=\"4294902015\") // Binary: ...0000_0000_1111_1111\n/// }\n/// ```\npub fn UInt::lnot(self : UInt) -> UInt = \"%u32.bitnot\"\n\n///|\n/// Performs a left shift operation on an unsigned 32-bit integer. Shifts each\n/// bit in the number to the left by the specified number of positions, filling\n/// the rightmost positions with zeros.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift the bits. Must be non-negative\n/// and less than 32. Values outside this range are wrapped to fit within it\n/// (i.e., `shift & 31`).\n///\n/// Returns a new `UInt` value representing the result of shifting the bits left\n/// by the specified number of positions. Each position shifted multiplies the\n/// number by 2.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1U\n/// inspect(x << 3, content=\"8\") // Using the recommended operator\n/// let y = 8U\n/// inspect(y << 1, content=\"16\") // Using the recommended operator\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `<<` instead\")\n#coverage.skip\npub fn UInt::lsl(self : UInt, shift : Int) -> UInt = \"%u32.shl\"\n\n///|\n/// Performs a left shift operation on an unsigned 32-bit integer. Shifts each\n/// bit in the integer to the left by the specified number of positions, filling\n/// the rightmost positions with zeros.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift left. Must be between 0 and 31\n/// inclusive. Values outside this range will be masked with `& 31`.\n///\n/// Returns a new `UInt` value containing the result of the left shift operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1U\n/// inspect(x << 3, content=\"8\") // Binary: 1 -> 1000\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `<<` instead\")\n#coverage.skip\npub fn UInt::shl(self : UInt, shift : Int) -> UInt = \"%u32.shl\"\n\n///|\n/// Performs a logical right shift on an unsigned 32-bit integer. Each bit in the\n/// input value is shifted right by the specified number of positions, with zeros\n/// shifted in from the left. DEPRECATED: Use the `>>` operator instead.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift right. Must be non-negative.\n///\n/// Returns a new `UInt` value representing the result of the logical right shift\n/// operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xF0000000U\n/// inspect(x >> 4, content=\"251658240\") // Using the recommended operator\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `>>` instead\")\n#coverage.skip\npub fn UInt::lsr(self : UInt, shift : Int) -> UInt = \"%u32.shr\"\n\n///|\n/// Performs a logical right shift operation on an unsigned 32-bit integer by a\n/// specified number of positions. All bits shifted in from the left are zeros.\n///\n/// Parameters:\n///\n/// * `number` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift right. Must be non-negative.\n///\n/// Returns a new `UInt` value that represents the result of shifting all bits in\n/// `number` to the right by `shift` positions.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xFF000000U\n/// inspect(x >> 8, content=\"16711680\") // 0x00FF0000\n/// }\n/// ```\n///\n#deprecated(\"Use infix operator `>>` instead\")\n#coverage.skip\npub fn UInt::shr(self : UInt, shift : Int) -> UInt = \"%u32.shr\"\n\n///|\n/// Performs a left shift operation on an unsigned 32-bit integer. Each bit in\n/// the integer is shifted left by the specified number of positions, and zeros\n/// are filled in from the right.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift. Only the least significant 5\n/// bits are used, effectively making the shift count always between 0 and 31.\n///\n/// Returns a new unsigned 32-bit integer that is the result of shifting `self`\n/// left by `shift` positions.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1U\n/// inspect(x << 3, content=\"8\") // Binary: 1 -> 1000\n/// let y = 0xFFFFFFFFU\n/// inspect(y << 16, content=\"4294901760\") // All bits after position 16 are discarded\n/// }\n/// ```\npub impl Shl for UInt with shl(self, shift) = \"%u32.shl\"\n\n///|\n/// Performs a logical right shift operation on an unsigned 32-bit integer. The\n/// operation shifts all bits to the right by a specified number of positions,\n/// filling the leftmost positions with zeros.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be shifted.\n/// * `shift` : The number of positions to shift right. If this value is\n/// negative, the behavior is undefined. Values larger than 31 are masked with `&\n/// 31`.\n///\n/// Returns a new unsigned 32-bit integer containing the result of the right\n/// shift operation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xFF000000U\n/// inspect(x >> 8, content=\"16711680\") // 0x00FF0000\n/// inspect(x >> 24, content=\"255\") // 0x000000FF\n/// let x = 0xFF000000U\n/// inspect(x >> 32, content=\"4278190080\") // Same as x >> 0 due to masking\n/// }\n/// ```\npub impl Shr for UInt with shr(self, shift) = \"%u32.shr\"\n\n///|\n/// Counts the number of leading zero bits in an unsigned 32-bit integer,\n/// starting from the most significant bit.\n///\n/// Parameters:\n///\n/// * `value` : The unsigned 32-bit integer whose leading zeros are to be\n/// counted.\n///\n/// Returns the number of consecutive zeros starting from the most significant\n/// bit. For a zero value, returns 32.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(0U.clz(), content=\"32\")\n/// inspect(1U.clz(), content=\"31\")\n/// inspect(0x80000000U.clz(), content=\"0\")\n/// }\n/// ```\npub fn UInt::clz(self : UInt) -> Int = \"%u32.clz\"\n\n///|\n/// Counts the number of trailing zero bits in an unsigned 32-bit integer,\n/// starting from the least significant bit. For a zero input, returns 32.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer whose trailing zeros are to be\n/// counted.\n///\n/// Returns the number of consecutive zeros at the least significant end of the\n/// binary representation. Returns 32 if the input is zero.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 24U // Binary: ...011000\n/// inspect(x.ctz(), content=\"3\") // 3 trailing zeros\n/// let y = 0U\n/// inspect(y.ctz(), content=\"32\") // All bits are zero\n/// }\n/// ```\npub fn UInt::ctz(self : UInt) -> Int = \"%u32.ctz\"\n\n///|\n/// Counts the number of 1 bits (population count) in the binary representation\n/// of an unsigned 32-bit integer.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer whose bits are to be counted.\n///\n/// Returns an integer representing the count of set bits (1s) in the binary\n/// representation.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 0xF0F0U // Binary: 1111 0000 1111 0000\n/// inspect(x.popcnt(), content=\"8\") // Has 8 bits set to 1\n/// }\n/// ```\npub fn UInt::popcnt(self : UInt) -> Int = \"%u32.popcnt\"\n\n///|\n/// Converts an unsigned 32-bit integer to an unsigned 64-bit integer by\n/// zero-extending it. The resulting value preserves the original number's\n/// magnitude while using 64 bits to represent it.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer (`UInt`) to be converted.\n///\n/// Returns an unsigned 64-bit integer (`UInt64`) representing the same numerical\n/// value as the input.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42U\n/// inspect(n.to_uint64(), content=\"42\")\n/// let max = 4294967295U // Maximum value of UInt\n/// inspect(max.to_uint64(), content=\"4294967295\")\n/// }\n/// ```\npub fn UInt::to_uint64(self : UInt) -> UInt64 {\n UInt64::extend_uint(self)\n}\n\n///|\n/// Converts an unsigned 32-bit integer to a byte by taking its least significant\n/// 8 bits. Any bits beyond the first 8 bits are truncated.\n///\n/// Parameters:\n///\n/// * `self` : The unsigned 32-bit integer to be converted. Only the least\n/// significant 8 bits will be used.\n///\n/// Returns a byte containing the least significant 8 bits of the input integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 258U // In binary: 100000010\n/// inspect(n.to_byte(), content=\"b'\\\\x02'\") // Only keeps 00000010\n/// let big = 4294967295U // Maximum value of UInt\n/// inspect(big.to_byte(), content=\"b'\\\\xFF'\") // Only keeps 11111111\n/// }\n/// ```\npub fn UInt::to_byte(self : UInt) -> Byte {\n self.reinterpret_as_int().to_byte()\n}\n\n///|\n/// Converts an unsigned 32-bit integer to a double-precision floating-point\n/// number. Since the range of unsigned 32-bit integers is smaller than what can\n/// be precisely represented by a double-precision floating-point number, this\n/// conversion is guaranteed to be exact.\n///\n/// Parameters:\n///\n/// * `value` : The unsigned 32-bit integer to be converted.\n///\n/// Returns a double-precision floating-point number that exactly represents the\n/// input value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42U\n/// inspect(n.to_double(), content=\"42\")\n/// let max = 4294967295U // maximum value of UInt\n/// inspect(max.to_double(), content=\"4294967295\")\n/// }\n/// ```\npub fn UInt::to_double(self : UInt) -> Double = \"%u32.to_f64\"\n\n///|\n/// Convert `Int` to `Float` (deprecated alias).\n/// Convert to `float`.\n#deprecated(\"Use `Float::from_int` instead\")\npub fn Int::to_float(self : Int) -> Float = \"%i32.to_f32\"\n\n///|\n/// Reinterpret `Int` bit pattern as `Float` (deprecated alias).\n/// Function `reinterpret_as_float`.\n#deprecated(\"Use `Float::reinterpret_from_int` instead\")\npub fn Int::reinterpret_as_float(self : Int) -> Float = \"%i32.to_f32_reinterpret\"\n\n///|\n/// Reinterpret `UInt` bit pattern as `Float` (deprecated alias).\n/// Function `reinterpret_as_float`.\n#deprecated(\"Use `Float::reinterpret_from_uint` instead\")\npub fn UInt::reinterpret_as_float(self : UInt) -> Float = \"%i32.to_f32_reinterpret\"\n\n///|\n/// Convert `Byte` to `Float` (deprecated alias).\n/// Convert to `float`.\n#deprecated(\"Use `Float::from_byte` instead\")\npub fn Byte::to_float(self : Byte) -> Float = \"%byte.to_f32\"\n\n///|\n/// TODO: use intrinsics implement this\npub fn Byte::to_double(self : Byte) -> Double {\n self.to_int().to_double()\n}\n\n///|\n/// TODO: enable skip_current_package=false\n/// Convert `Double` to `Float` (deprecated alias).\n#deprecated(\"Use `Float::from_double` instead\", skip_current_package=true)\npub fn Double::to_float(self : Double) -> Float = \"%f64.to_f32\"\n\n///|\n/// Convert `UInt` to `Float` (deprecated alias).\n/// Convert to `float`.\n#deprecated(\"Use `Float::from_uint` instead\")\npub fn UInt::to_float(self : UInt) -> Float = \"%u32.to_f32\"\n\n///|\n/// Convert `Int` to `Int16` (deprecated alias).\n/// Convert to `int16`.\n#deprecated(\"Use `Int16::from_int` instead\")\npub fn Int::to_int16(self : Int) -> Int16 = \"%i32_to_i16\"\n\n///|\n/// Converts a byte value to a 16-bit signed integer. The byte value is\n/// sign-extended to 16 bits during the conversion.\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted to an `Int16`.\n///\n/// Returns a 16-bit signed integer representing the same value as the input\n/// byte.\n#deprecated(\"Use `Int16::from_byte` instead\")\npub fn Byte::to_int16(self : Byte) -> Int16 = \"%byte_to_i16\"\n\n///|\n/// Converts an unsigned 16-bit integer to a 32-bit signed integer. The value is\n/// zero-extended to fill the higher bits.\n///\n/// Parameters:\n///\n/// * `value` : The unsigned 16-bit integer to be converted.\n///\n/// Returns a 32-bit signed integer. Since the input value is always non-negative\n/// and less than 65536, the conversion never results in overflow.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = Int::to_uint16(42)\n/// inspect(x.to_int(), content=\"42\")\n/// let max = Int::to_uint16(65535) // maximum value of UInt16\n/// inspect(max.to_int(), content=\"65535\")\n/// }\n/// ```\npub fn UInt16::to_int(self : UInt16) -> Int = \"%u16_to_i32\"\n\n///|\n/// Converts a 16-bit unsigned integer to an 8-bit byte by truncating the higher\n/// bits.\n///\n/// Parameters:\n///\n/// * `value` : The 16-bit unsigned integer to be converted.\n///\n/// Returns a byte containing the least significant 8 bits of the input value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = Int::to_uint16(258) // Binary: 0000_0001_0000_0010\n/// inspect(x.to_byte(), content=\"b'\\\\x02'\") // Only keeps 0000_0010\n/// }\n/// ```\npub fn UInt16::to_byte(self : UInt16) -> Byte = \"%u16_to_byte\"\n\n///|\n/// Converts a 32-bit unsigned integer to a 16-bit unsigned integer by truncating\n/// its value to fit within the range of 0 to 65535.\n///\n/// Parameters:\n///\n/// * `integer` : The 32-bit unsigned integer to be converted. Values outside the\n/// range of UInt16 will be truncated to fit.\n///\n/// Returns a 16-bit unsigned integer containing the lower 16 bits of the input\n/// value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42U\n/// inspect(n.to_uint16(), content=\"42\")\n/// let max = 4294967295U\n/// inspect(max.to_uint16(), content=\"65535\") // -1 becomes max value of UInt16\n/// let large = 65536U\n/// inspect(large.to_uint16(), content=\"0\") // Values wrap around\n/// }\n/// ```\npub fn UInt::to_uint16(self : UInt) -> UInt16 {\n self.reinterpret_as_int().to_uint16()\n}\n\n///|\n/// Converts a 32-bit signed integer to a 16-bit unsigned integer by truncating\n/// its value to fit within the range of 0 to 65535.\n///\n/// Parameters:\n///\n/// * `integer` : The 32-bit signed integer to be converted. Values outside the\n/// range of UInt16 will be truncated to fit.\n///\n/// Returns a 16-bit unsigned integer containing the lower 16 bits of the input\n/// value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let n = 42\n/// inspect(n.to_uint16(), content=\"42\")\n/// let neg = -1\n/// inspect(neg.to_uint16(), content=\"65535\") // -1 becomes max value of UInt16\n/// let large = 65536\n/// inspect(large.to_uint16(), content=\"0\") // Values wrap around\n/// }\n/// ```\npub fn Int::to_uint16(self : Int) -> UInt16 = \"%i32_to_u16\"\n\n///|\n/// Converts a byte value to a 16-bit unsigned integer by zero-extending it.\n///\n/// Parameters:\n///\n/// * `byte` : The byte value to be converted.\n///\n/// Returns a 16-bit unsigned integer (`UInt16`) representing the same value as\n/// the input byte.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let b = b'\\xFF' // byte with value 255\n/// inspect(b.to_uint16(), content=\"255\")\n/// let zero = b'\\x00'\n/// inspect(zero.to_uint16(), content=\"0\")\n/// }\n/// ```\npub fn Byte::to_uint16(self : Byte) -> UInt16 = \"%byte_to_u16\"\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// External iterator type.\n/// `Iterator[X]` is a mutable type: iterators internally maintain mutable state\n/// to advance iteration.\n/// All read operations on `Iterator` will advance the iterator,\n/// and would give different result when called multiple times.\n#alias(Iterator, deprecated=\"The name `Iterator` is deprecated, use `Iter` instead. Note that if you have defined `iterator()` method to support `for .. in` loop, you should also rename `iterator()` to `iter()`. See https://github.com/moonbitlang/core/pull/3127 for more details.\")\nstruct Iter[X] {\n f : () -> X?\n mut size_hint : Int?\n}\n\n///|\npriv enum IntersperseState[X] {\n IntersperseInit\n IntersperseElem(X)\n IntersperseSep\n}\n\n///|\n/// Get the next element from an iterator, or return `None` if no more element exists.\n/// The returned element will be consumed from the iterator.\n/// Calling `next` repeatedly will iterate through all elements in the iterator.\n#alias(peek, deprecated)\n#alias(head)\npub fn[X] Iter::next(self : Iter[X]) -> X? {\n let result = (self.f)()\n match (result, self.size_hint) {\n (Some(_), Some(n)) =>\n self.size_hint = if n > 0 { Some(n - 1) } else { Some(0) }\n (None, _) => self.size_hint = Some(0)\n _ => ()\n }\n result\n}\n\n///|\n/// Returns the hinted number of remaining elements if it is known.\n///\n/// The hint is intended to be exact for iterators produced by trusted\n/// collection APIs and adapters, but it must not be used for correctness.\npub fn[X] Iter::size_hint(self : Iter[X]) -> Int? {\n self.size_hint\n}\n\n///|\n/// Consume iterator elements while callback returns `IterContinue`.\n///\n/// Deprecated: prefer explicit loops.\n/// Function `run`.\n#locals(f)\n#deprecated(\"write a loop instead.\")\npub fn[X] Iter::run(self : Iter[X], f : (X) -> IterResult) -> IterResult {\n while self.next() is Some(x) {\n guard f(x) is IterContinue else { break IterEnd }\n } nobreak {\n IterContinue\n }\n}\n\n///|\n/// Consume iterator elements and ignore final continuation state.\n///\n/// Deprecated: prefer explicit loops.\n/// Function `just_run`.\n#deprecated(\"write a loop instead.\")\npub fn[X] Iter::just_run(self : Iter[X], f : (X) -> IterResult) -> Unit {\n while self.next() is Some(x) {\n if f(x) is IterEnd {\n break\n }\n }\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[X : Show] Show for Iter[X]\n\n///|\npub impl[X : Show] Show for Iter[X] with output(self, logger) {\n logger.write_string(\"[\")\n if self.next() is Some(x) {\n logger.write_object(x)\n while self.next() is Some(x) {\n logger.write_string(\", \")\n logger.write_object(x)\n }\n }\n logger.write_string(\"]\")\n}\n\n///|\npub impl[X : ToJson] ToJson for Iter[X] with to_json(self) {\n [\n for x in self => x\n ]\n}\n\n///|\n/// Iterates over each element in the iterator, applying the function `f` to each element.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// - `self`: The iterator to consume.\n/// - `f`: A function that takes an element of type `X` and returns `Unit`. This function is applied to each element of the iterator.\n#locals(f)\npub fn[X] Iter::each(self : Iter[X], f : (X) -> Unit raise?) -> Unit raise? {\n while self.next() is Some(x) {\n f(x)\n }\n}\n\n///|\n/// Return `true` if any element satisfies predicate `f`.\n/// Function `any`.\n#locals(f)\npub fn[X] Iter::any(self : Iter[X], f : (X) -> Bool) -> Bool {\n while self.next() is Some(x) {\n if f(x) {\n break true\n }\n } nobreak {\n false\n }\n}\n\n///|\n/// Return `true` if all elements satisfy predicate `f`.\n/// Function `all`.\n#locals(f)\npub fn[X] Iter::all(self : Iter[X], f : (X) -> Bool) -> Bool {\n while self.next() is Some(x) {\n guard f(x) else { break false }\n } nobreak {\n true\n }\n}\n\n///|\n/// Iterates over each element in the iterator, applying the function `f` to each element with index.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// - `self`: The iterator to consume.\n/// - `f`: A function that takes an index of type `Int` and an element of type `X` and returns `Unit`. This function is applied to each element of the iterator.\n#locals(f)\npub fn[X] Iter::eachi(\n self : Iter[X],\n f : (Int, X) -> Unit raise?,\n) -> Unit raise? {\n let mut i = 0\n while self.next() is Some(x) {\n f(i, x)\n i += 1\n }\n}\n\n///|\n/// Folds the elements of the iterator using the given function, starting with the given initial value.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n/// - `R`: The type of the accumulator (result) value.\n///\n/// # Arguments\n///\n/// - `self`: The iterator to consume.\n/// - `f`: A function that takes an accumulator of type `R` and an element of type `X`, and returns a new accumulator value.\n/// - `init`: The initial value for the fold operation.\n///\n/// # Returns\n///\n/// Returns the final accumulator value after folding all elements of the iterator.\n#locals(f)\npub fn[X, R] Iter::fold(\n self : Iter[X],\n init~ : R,\n f : (R, X) -> R raise?,\n) -> R raise? {\n let mut acc = init\n while self.next() is Some(x) {\n acc = f(acc, x)\n }\n acc\n}\n\n///|\n/// Counts the number of elements in the iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// - `self`: The iterator to consume.\n///\n/// # Returns\n///\n/// Returns the number of elements in the iterator.\npub fn[X] Iter::count(self : Iter[X]) -> Int {\n self.fold((acc, _) => acc + 1, init=0)\n}\n\n// Producers\n\n///|\n/// Create a new iterator by supplying a `next` function directly.\n/// The supplied function should output the next element being iterated\n/// everytime it is called.\n/// If the number of remaining elements is known, pass it as `size_hint`.\n///\n/// This function is intended for use by data structure authors,\n/// and should not be called by end users in general.\npub fn[X] Iter::new(f : () -> X?, size_hint? : Int) -> Iter[X] {\n let size_hint = match size_hint {\n Some(n) if n > 0 => Some(n)\n Some(_) => Some(0)\n None => None\n }\n { f, size_hint }\n}\n\n///|\n/// Creates an empty iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Returns\n///\n/// Returns an empty iterator of type `Iter[X]`.\npub fn[X] Iter::empty() -> Iter[X] {\n Iter::new(() => None, size_hint=0)\n}\n\n///|\n/// Creates an iterator that contains a single element.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the element in the iterator.\n///\n/// # Arguments\n///\n/// - `elem`: The single element to be contained in the iterator.\n///\n/// # Returns\n///\n/// Returns an iterator of type `Iter[X]` that contains the single element `a`.\npub fn[X] Iter::singleton(elem : X) -> Iter[X] {\n let mut consumed = false\n Iter::new(\n fn() {\n if consumed {\n None\n } else {\n consumed = true\n Some(elem)\n }\n },\n size_hint=1,\n )\n}\n\n///|\n/// Creates an iterator that repeats the given element indefinitely.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// - `x`: The element to be repeated.\n///\n/// # Returns\n///\n/// Returns an iterator of type `Iter[X]` that repeats the element `x` indefinitely.\npub fn[X] Iter::repeat(x : X) -> Iter[X] {\n Iter::new(() => Some(x))\n}\n\n///|\n/// Filters the elements of the iterator based on a predicate function.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The predicate function that determines whether an element should be included in the filtered iterator.\n///\n/// # Returns\n///\n/// A new iterator that only contains the elements for which the predicate function returns `IterContinue`.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `filter`.\npub fn[X] Iter::filter(self : Iter[X], f : (X) -> Bool) -> Iter[X] {\n Iter::new(fn() {\n while self.next() is Some(x) {\n if f(x) {\n break Some(x)\n }\n } nobreak {\n None\n }\n })\n}\n\n///|\n/// Transforms the elements of the iterator using a mapping function.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n/// - `Y`: The type of the transformed elements.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The mapping function that transforms each element of the iterator.\n///\n/// # Returns\n///\n/// A new iterator that contains the transformed elements.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `map`.\npub fn[X, Y] Iter::map(self : Iter[X], f : (X) -> Y) -> Iter[Y] {\n {\n f: fn() {\n match self.next() {\n Some(x) => Some(f(x))\n None => None\n }\n },\n size_hint: self.size_hint,\n }\n}\n\n///|\n/// Transforms the elements of the iterator using a mapping function.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n/// - `Y`: The type of the transformed elements.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The mapping function that transforms each element of the iterator with index.\n///\n/// # Returns\n///\n/// A new iterator that contains the transformed elements.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `mapi`.\npub fn[X, Y] Iter::mapi(self : Iter[X], f : (Int, X) -> Y) -> Iter[Y] {\n let mut i = 0\n {\n f: fn() {\n match self.next() {\n Some(x) => {\n let result = f(i, x)\n i += 1\n Some(result)\n }\n None => None\n }\n },\n size_hint: self.size_hint,\n }\n}\n\n///|\n/// Transforms the elements of the iterator using a mapping function that returns an `Option`.\n/// The elements for which the function returns `None` are filtered out.\n///\n/// The old iterator `self` must not be used again after calling `filter_map`.\npub fn[X, Y] Iter::filter_map(self : Iter[X], f : (X) -> Y?) -> Iter[Y] {\n Iter::new(fn() {\n while self.next() is Some(x) {\n match f(x) {\n Some(_) as y => break y\n None => ()\n }\n } nobreak {\n None\n }\n })\n}\n\n///|\n/// Transforms each element of the iterator into an iterator and flattens the resulting iterators into a single iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n/// - `Y`: The type of the transformed elements.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The function that transforms each element of the iterator into an iterator.\n///\n/// # Returns\n///\n/// A new iterator that contains the flattened elements.\n///\n/// # Note\n/// The old iterator `self` and the iterators returned by `f`\n/// must not be used again after calling `flat_map`.\npub fn[X, Y] Iter::flat_map(self : Iter[X], f : (X) -> Iter[Y]) -> Iter[Y] {\n let mut current_iter = Some(Iter::empty())\n Iter::new(fn() {\n guard current_iter is Some(iter) else { None }\n for x = iter.next() {\n match x {\n Some(_) as elem => break elem\n None => {\n guard self.next() is Some(x) else { break None }\n let iter = f(x)\n current_iter = Some(iter)\n continue iter.next()\n }\n }\n }\n })\n}\n\n///|\n/// `iter.map(f).flatten() == iter.flat_map(f)`\npub fn[X] Iter::flatten(self : Iter[Iter[X]]) -> Iter[X] {\n self.flat_map(it => it)\n}\n\n///|\n/// Collects the string-renderable elements of the iterator into a single\n/// string, separated by `sep`.\n/// The old iterator `self` must not be used again after calling `join`.\npub fn[A : ToStringView] Iter::join(self : Iter[A], sep : StringView) -> String {\n let result = StringBuilder()\n if self.next() is Some(x) {\n result.write_view(x.to_string_view())\n while self.next() is Some(x) {\n result.write_view(sep)\n result.write_view(x.to_string_view())\n }\n }\n result.to_string()\n}\n\n///|\n/// Applies a function to each element of the iterator without modifying the iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The function to apply to each element of the iterator.\n///\n/// # Returns\n///\n/// The same iterator.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `tap`.\npub fn[X] Iter::tap(self : Iter[X], f : (X) -> Unit) -> Iter[X] {\n {\n f: fn() {\n let result = self.next()\n if result is Some(x) {\n f(x)\n }\n result\n },\n size_hint: self.size_hint,\n }\n}\n\n///|\n/// Takes the first `n` elements from the iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `n` - The number of elements to take.\n///\n/// # Returns\n///\n/// A new iterator that contains the first `n` elements.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `take`.\npub fn[X] Iter::take(self : Iter[X], n : Int) -> Iter[X] {\n let mut remaining = n\n let size_hint = match self.size_hint {\n Some(_) if n <= 0 => Some(0)\n Some(len) if n < len => Some(n)\n Some(len) => Some(len)\n None if n <= 0 => Some(0)\n None => None\n }\n {\n f: fn() {\n guard remaining > 0 else { None }\n let result = self.next()\n if result is Some(_) {\n remaining -= 1\n }\n result\n },\n size_hint,\n }\n}\n\n///|\n/// Takes elements from the iterator as long as the predicate function returns `true`.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The predicate function that determines whether an element should be taken.\n///\n/// # Returns\n///\n/// A new iterator that contains the elements as long as the predicate function returns `true`.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `take_while`.\npub fn[X] Iter::take_while(self : Iter[X], f : (X) -> Bool) -> Iter[X] {\n let mut still_running = true\n Iter::new(fn() {\n guard still_running else { None }\n let result = self.next()\n if result is Some(x) && !f(x) {\n still_running = false\n None\n } else {\n result\n }\n })\n}\n\n///|\n/// Transforms the elements of the iterator using a mapping function upto the function returns `None`.\n/// The old iterator `self` must not be used again after calling `map_while`.\npub fn[X, Y] Iter::map_while(self : Iter[X], f : (X) -> Y?) -> Iter[Y] {\n let mut still_running = true\n Iter::new(fn() {\n guard still_running else { None }\n let src = self.next()\n guard src is Some(x) else { None }\n let result = f(x)\n if result is None {\n still_running = false\n }\n result\n })\n}\n\n///|\n/// Skips the first `n` elements from the iterator.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `n` - The number of elements to skip.\n///\n/// # Returns\n///\n/// A new iterator that starts after skipping the first `n` elements.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `drop`.\npub fn[X] Iter::drop(self : Iter[X], n : Int) -> Iter[X] {\n let mut remaining = n\n let size_hint = match self.size_hint {\n Some(len) if n <= 0 => Some(len)\n Some(len) if n < len => Some(len - n)\n Some(_) => Some(0)\n None => None\n }\n {\n f: fn() {\n while remaining > 0 {\n guard self.next() is Some(_) else { break None }\n remaining -= 1\n } nobreak {\n self.next()\n }\n },\n size_hint,\n }\n}\n\n///|\n/// Skips elements from the iterator as long as the predicate function returns `true`.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The predicate function that determines whether an element should be skipped.\n///\n/// # Returns\n///\n/// A new iterator that starts after skipping the elements as long as the predicate function returns `true`.\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `drop_while`.\npub fn[X] Iter::drop_while(self : Iter[X], f : (X) -> Bool) -> Iter[X] {\n let mut dropped = false\n Iter::new(fn() {\n if !dropped {\n dropped = true\n for x = self.next() {\n match x {\n Some(x) if f(x) => continue self.next()\n result => break result\n }\n }\n } else {\n self.next()\n }\n })\n}\n\n///|\n/// Finds the first element in the iterator that satisfies the predicate function.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterator.\n///\n/// # Arguments\n///\n/// * `self` - The input iterator.\n/// * `f` - The predicate function that determines whether an element is the first element to be found.\n///\n/// # Returns\n///\n/// An `Option` that contains the first element that satisfies the predicate function, or `None` if no such element is found.\n///\n/// # Note\n/// The iterator `self` will advance past the returned element.\npub fn[X] Iter::find_first(self : Iter[X], f : (X) -> Bool) -> X? {\n while self.next() is Some(x) {\n if f(x) {\n break Some(x)\n }\n } nobreak {\n None\n }\n}\n\n///|\n/// Combines two iterators into one by appending the elements of the second iterator to the first.\n///\n/// # Type Parameters\n///\n/// - `X`: The type of the elements in the iterators.\n///\n/// # Arguments\n///\n/// * `self` - The first input iterator.\n/// * `other` - The second input iterator to be appended to the first.\n///\n/// # Returns\n///\n/// Returns a new iterator that contains the elements of `self` followed by the elements of `other`.\n///\n/// # Note\n/// The old iterator `self` and `other` must not be used again after calling `tap`.\npub fn[X] Iter::concat(self : Iter[X], other : Iter[X]) -> Iter[X] {\n let mut in_first = true\n let size_hint = match (self.size_hint, other.size_hint) {\n (Some(n), Some(m)) => Some(n + m)\n _ => None\n }\n {\n f: fn() {\n if in_first {\n let result = self.next()\n if result is None {\n in_first = false\n other.next()\n } else {\n result\n }\n } else {\n other.next()\n }\n },\n size_hint,\n }\n}\n\n///|\n/// Combines two iterators element-wise into an iterator of pairs.\n///\n/// The resulting iterator stops as soon as either input iterator is exhausted.\n///\n/// # Type Parameters\n///\n/// - `X`: The element type of `self`.\n/// - `Y`: The element type of `other`.\n///\n/// # Arguments\n///\n/// * `self` - The first input iterator.\n/// * `other` - The second input iterator.\n///\n/// # Returns\n///\n/// Returns a new iterator yielding tuples `(x, y)` where `x` comes from `self`\n/// and `y` comes from `other`.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let numbers = (1).until(5)\n/// let letters = [\"a\", \"b\", \"c\"].iter()\n/// debug_inspect(\n/// numbers.zip(letters).collect(),\n/// content=\"[(1, \\\"a\\\"), (2, \\\"b\\\"), (3, \\\"c\\\")]\",\n/// )\n/// }\n/// ```\n///\n/// # Note\n/// The old iterators `self` and `other` must not be used again after calling `zip`.\n#alias(combine)\npub fn[X, Y] Iter::zip(self : Iter[X], other : Iter[Y]) -> Iter[(X, Y)] {\n let size_hint = match (self.size_hint, other.size_hint) {\n (Some(n), Some(m)) if n < m => Some(n)\n (Some(_), Some(m)) => Some(m)\n (Some(0), _) => Some(0)\n (_, Some(0)) => Some(0)\n _ => None\n }\n {\n f: fn() {\n guard self.next() is Some(x) else { None }\n guard other.next() is Some(y) else { None }\n Some((x, y))\n },\n size_hint,\n }\n}\n\n///|\npub impl[T] Add for Iter[T] with add(self, other) {\n self.concat(other)\n}\n\n///|\n/// Collects the elements of the iterator into an array.\n/// The old iterator `self` must not be used again.\n#alias(collect)\npub fn[X] Iter::to_array(self : Iter[X]) -> Array[X] {\n let result = match self.size_hint {\n Some(n) => Array::new(capacity=n)\n None => []\n }\n while self.next() is Some(x) {\n result.push(x)\n }\n result\n}\n\n///|\n/// Return this iterator itself.\n/// Return an iterator via `iter`.\n#alias(iterator)\npub fn[X] Iter::iter(self : Iter[X]) -> Iter[X] {\n self\n}\n\n///|\n/// Return an indexed view of this iterator.\n/// Return an iterator via `iter2`.\n#alias(iterator2)\npub fn[X] Iter::iter2(self : Iter[X]) -> Iter2[Int, X] {\n let mut i = 0\n Iter2({\n f: () => {\n guard self.next() is Some(elem) else { None }\n let result = Some((i, elem))\n i += 1\n result\n },\n size_hint: self.size_hint,\n })\n}\n\n///|\n/// Returns the last element of the iterator, or `None` if the iterator is empty.\n/// The old iterator `self` must not be used again after calling `last`.\npub fn[X] Iter::last(self : Iter[X]) -> X? {\n for x = (None : X?), y = self.next() {\n match (x, y) {\n (last, None) => break last\n (_, Some(_) as x) => continue x, self.next()\n }\n }\n}\n\n///|\n/// Inserts a separator element `sep` between each element of the iterator.\n///\n/// # Parameters\n///\n/// - `self` : The iterator to intersperse the separator into.\n/// - `sep` : The separator element to insert between each element of the iterator.\n///\n/// # Examples\n///\n/// ```mbt check\n/// test {\n/// let arr = []\n/// [1, 2, 3].iter().intersperse(0).each(i => arr.push(i))\n/// assert_eq(arr, [1, 0, 2, 0, 3])\n/// }\n/// ```\n///\n/// # Note\n/// The old iterator `self` must not be used again after calling `intersperse`.\npub fn[X] Iter::intersperse(self : Iter[X], sep : X) -> Iter[X] {\n let mut state : IntersperseState[X] = IntersperseInit\n let size_hint = match self.size_hint {\n Some(0) => Some(0)\n Some(n) => Some(n * 2 - 1)\n None => None\n }\n {\n f: fn() {\n match state {\n IntersperseInit => {\n let result = self.next()\n state = IntersperseSep\n result\n }\n IntersperseElem(x) => {\n state = IntersperseSep\n Some(x)\n }\n IntersperseSep =>\n // make sure we only output the separator when there is remaining element\n match self.next() {\n Some(x) => {\n state = IntersperseElem(x)\n Some(sep)\n }\n None => None\n }\n }\n },\n size_hint,\n }\n}\n\n///|\n/// Return a sliced iterator view in range `[start, end)`.\n/// Function `view`.\n#alias(\"_[_:_]\")\n#alias(sub, deprecated=\"Use _[_:_] instead\")\npub fn[X] Iter::view(self : Iter[X], start? : Int = 0, end? : Int) -> Iter[X] {\n match (start, end) {\n (_..=0, None) => self\n (_..=0, Some(end)) => self.take(end)\n (start, None) => self.drop(start)\n (start, Some(end)) => {\n let mut index = 0\n let size_hint = match self.size_hint {\n Some(_) if end <= start => Some(0)\n Some(len) if start >= len => Some(0)\n Some(len) if end < len => Some(end - start)\n Some(len) => Some(len - start)\n None if end <= start => Some(0)\n None => None\n }\n {\n f: fn() {\n if index >= end {\n return None\n }\n while index < start {\n guard self.next() is Some(_) else { return None }\n index += 1\n }\n if index >= end {\n return None\n }\n let result = self.next()\n if result is Some(_) {\n index += 1\n }\n result\n },\n size_hint,\n }\n }\n }\n}\n\n///|\n/// Checks if the iterator contains an element equal to the given value.\n///\n/// Parameters:\n///\n/// * `self` : The iterator to search in.\n/// * `value` : The value to search for.\n///\n/// Returns `true` if the iterator contains an element equal to the given value,\n/// `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let iter = [1, 2, 3, 4, 5].iter()\n/// inspect(iter.contains(3), content=\"true\")\n/// inspect(iter.contains(6), content=\"false\")\n/// let iter = Iter::empty()\n/// inspect(iter.contains(1), content=\"false\")\n/// }\n/// ```\n///\n/// # Note\n/// The old iterator `self` will advance past the searched element.\npub fn[X : Eq] Iter::contains(self : Iter[X], value : X) -> Bool {\n while self.next() is Some(x) {\n if x == value {\n break true\n }\n } nobreak {\n false\n }\n}\n\n///|\n/// Returns the nth element of the iterator, or `None` if the iterator is\n/// shorter than `n` elements.\n/// The iterator `self` will advance past the returned element.\npub fn[X] Iter::nth(self : Iter[X], n : Int) -> X? {\n guard n >= 0 else { None }\n for _ in 0..<n {\n guard self.next() is Some(_) else { break None }\n } nobreak {\n self.next()\n }\n}\n\n///|\n/// Return the maximum element, or `None` if empty.\npub fn[X : Compare] Iter::maximum(self : Iter[X]) -> X? {\n guard self.next() is Some(x) else { return None }\n let mut res = x\n while self.next() is Some(x) {\n if x > res {\n res = x\n }\n }\n Some(res)\n}\n\n///|\n/// Return the minimum element, or `None` if empty.\npub fn[X : Compare] Iter::minimum(self : Iter[X]) -> X? {\n guard self.next() is Some(x) else { return None }\n let mut res = x\n while self.next() is Some(x) {\n if x < res {\n res = x\n }\n }\n Some(res)\n}\n\n///|\n/// This type is used for `for _, _ in ..` loop\n/// (`for .. in` loop with two loop variables),\n/// and should not be used directly in general.\n#alias(Iterator2, deprecated=\"The name `Iterator2` is deprecated, use `Iter2` instead. Note that if you have defined `iterator2()` method to support `for .. in` loop, you should also rename `iterator2()` to `iter2()`. See https://github.com/moonbitlang/core/pull/3127 for more details.\")\npub(all) struct Iter2[X, Y](Iter[(X, Y)])\n\n///|\n/// Construct an `Iter2` from a pair-producing function.\n/// If the number of remaining pairs is known, pass it as `size_hint`.\npub fn[X, Y] Iter2::new(f : () -> (X, Y)?, size_hint? : Int) -> Iter2[X, Y] {\n let size_hint = match size_hint {\n Some(n) if n > 0 => Some(n)\n Some(_) => Some(0)\n None => None\n }\n Iter2({ f, size_hint })\n}\n\n///|\n/// Convert to plain iterator of pairs.\n/// Return an iterator via `iter`.\n#alias(iterator)\npub fn[X, Y] Iter2::iter(self : Iter2[X, Y]) -> Iter[(X, Y)] {\n self.0\n}\n\n///|\n/// Return this two-variable iterator itself.\n/// Return an iterator via `iter2`.\n#alias(iterator2)\npub fn[X, Y] Iter2::iter2(self : Iter2[X, Y]) -> Iter2[X, Y] {\n self\n}\n\n///|\n/// Get the next pair from the iterator.\npub fn[X, Y] Iter2::next(self : Iter2[X, Y]) -> (X, Y)? {\n self.0.next()\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[X : Show, Y : Show] Show for Iter2[X, Y]\n\n///|\n#warnings(\"-deprecated\")\npub impl[X : Show, Y : Show] Show for Iter2[X, Y] with output(self, logger) {\n self.0.output(logger)\n}\n\n///|\n/// Consume pairs while callback returns `IterContinue`.\n#deprecated(\"write a loop instead.\")\npub fn[X, Y] Iter2::run(\n self : Iter2[X, Y],\n f : (X, Y) -> IterResult,\n) -> IterResult {\n while self.0.next() is Some((x, y)) {\n guard f(x, y) is IterContinue else { break IterEnd }\n } nobreak {\n IterContinue\n }\n}\n\n///|\n/// Apply callback to each pair.\npub fn[X, Y] Iter2::each(self : Iter2[X, Y], f : (X, Y) -> Unit) -> Unit {\n self.0.each(pair => f(pair.0, pair.1))\n}\n\n///|\n/// Concatenate two `Iter2` streams.\npub fn[X, Y] Iter2::concat(\n self : Iter2[X, Y],\n other : Iter2[X, Y],\n) -> Iter2[X, Y] {\n Iter2(self.0.concat(other.0))\n}\n\n///|\n/// Collect all pairs into an array.\npub fn[X, Y] Iter2::to_array(self : Iter2[X, Y]) -> Array[(X, Y)] {\n self.0.to_array()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n#cfg(not(target=\"js\"))\nconst ALPHABET : String = \"0123456789abcdefghijklmnopqrstuvwxyz\"\n\n///|\n#cfg(not(target=\"js\"))\nfn unsafe_fixedarray_uint16_to_string(buffer : FixedArray[UInt16]) -> String = \"%string.unsafe_from_uint16_fixedarray\"\n\n//==========================================\n// Int and UInt (Non JS)\n//==========================================\n\n///|\n/// Converts an unsigned 32-bit integer to hexadecimal\n#cfg(not(target=\"js\"))\nfn int_to_string_hex(\n buffer : FixedArray[UInt16],\n num : UInt,\n digit_start : Int,\n total_len : Int,\n) -> Unit {\n // Process 2 hex digits (1 byte) at a time\n let (offset, n) = for offset = total_len - digit_start, n = num; offset >= 2; {\n let byte_val = n.land(0xFFU).reinterpret_as_int()\n let hi = byte_val / 16\n let lo = byte_val % 16\n buffer.unsafe_set(digit_start + offset - 2, ALPHABET.unsafe_get(hi))\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(lo))\n continue offset - 2, n >> 8\n } nobreak {\n (offset, n)\n }\n\n // Handle remaining single hex digit\n if offset == 1 {\n let nibble = n.land(0xFU).reinterpret_as_int()\n buffer.unsafe_set(digit_start, ALPHABET.unsafe_get(nibble))\n }\n}\n\n///|\n/// Generic radix conversion for any base 2-36\n#cfg(not(target=\"js\"))\nfn int_to_string_generic(\n buffer : FixedArray[UInt16],\n num : UInt,\n digit_start : Int,\n total_len : Int,\n radix : Int,\n) -> Unit {\n let base = radix.reinterpret_as_uint()\n if (radix & (radix - 1)) == 0 {\n // Power-of-two radix: use bit shifts\n let shift = radix.ctz()\n let mask = base - 1U\n for offset = total_len - digit_start, n = num; n > 0U; {\n let digit = n.land(mask).reinterpret_as_int()\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(digit))\n continue offset - 1, n >> shift\n }\n } else {\n // General radix: use division\n for offset = total_len - digit_start, n = num; n > 0U; {\n let q = n / base\n let digit = (n - q * base).reinterpret_as_int()\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(digit))\n continue offset - 1, q\n }\n }\n}\n\n///|\n/// Converts an unsigned 32-bit integer to decimal string\n#cfg(not(target=\"js\"))\nfn int_to_string_dec(\n buffer : FixedArray[UInt16],\n num : UInt,\n digit_start : Int,\n total_len : Int,\n) -> Unit {\n // Process digits in groups of 4 (chunks of 10000)\n let (num, offset) = for num = num, offset = total_len - digit_start; num >=\n 10000U; {\n let t = num / 10000U\n let r = (num % 10000U).reinterpret_as_int()\n let d1 = r / 100\n let d2 = r % 100\n let d1_hi = (0x30 + d1 / 10).to_uint16()\n let d1_lo = (0x30 + d1 % 10).to_uint16()\n let d2_hi = (0x30 + d2 / 10).to_uint16()\n let d2_lo = (0x30 + d2 % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 4, d1_hi)\n buffer.unsafe_set(digit_start + offset - 3, d1_lo)\n buffer.unsafe_set(digit_start + offset - 2, d2_hi)\n buffer.unsafe_set(digit_start + offset - 1, d2_lo)\n continue t, offset - 4\n } nobreak {\n (num, offset)\n }\n\n // Handle remaining digits (< 10000)\n // Process pairs of digits\n let (remaining, offset) = for remaining = num.reinterpret_as_int(), offset = offset; remaining >=\n 100; {\n let t = remaining / 100\n let d = remaining % 100\n let d_hi = (0x30 + d / 10).to_uint16()\n let d_lo = (0x30 + d % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 2, d_hi)\n buffer.unsafe_set(digit_start + offset - 1, d_lo)\n continue t, offset - 2\n } nobreak {\n (remaining, offset)\n }\n\n // Handle final 1 or 2 digits\n if remaining >= 10 {\n let d_hi = (0x30 + remaining / 10).to_uint16()\n let d_lo = (0x30 + remaining % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 2, d_hi)\n buffer.unsafe_set(digit_start + offset - 1, d_lo)\n } else {\n buffer.unsafe_set(digit_start + offset - 1, (0x30 + remaining).to_uint16())\n }\n}\n\n///|\n/// Calculates the number of decimal digits in a u32 value\n#cfg(not(target=\"js\"))\nfn dec_count32(value : UInt) -> Int {\n // Binary search: split 1-10 digits into halves\n if value >= 100000U { // >= 10^5 means 6+ digits\n if value >= 10000000U { // >= 10^7 means 8+ digits\n if value >= 1000000000U { // >= 10^9 means 10 digits\n 10\n } else if value >= 100000000U { // >= 10^8 means 9 digits\n 9\n } else {\n 8\n }\n } else if value >= 1000000U { // >= 10^6 means 7 digits\n 7\n } else {\n 6\n }\n } else if value >= 1000U { // >= 10^3 means 4+ digits\n if value >= 10000U { // >= 10^4 means 5 digits\n 5\n } else {\n 4\n }\n } else if value >= 100U { // >= 10^2 means 3 digits\n 3\n } else if value >= 10U { // >= 10^1 means 2 digits\n 2\n } else {\n 1\n }\n}\n\n///|\n/// Calculates the number of hex digits needed for a u32 value\n#cfg(not(target=\"js\"))\nfn hex_count32(value : UInt) -> Int {\n if value == 0U {\n 1\n } else {\n let leading_zeros = value.clz()\n (31 - leading_zeros) / 4 + 1\n }\n}\n\n///|\n/// Calculates the number of digits needed for a u32 value in any radix\n#cfg(not(target=\"js\"))\nfn radix_count32(value : UInt, radix : Int) -> Int {\n if value == 0U {\n return 1\n }\n let base = radix.reinterpret_as_uint()\n for num = value, count = 0; num > 0U; {\n continue num / base, count + 1\n } nobreak {\n count\n }\n}\n\n///|\n/// Converts an integer to its string representation in the specified radix (base).\n/// Example:\n/// ```\n/// inspect((255).to_string(radix=16), content=\"ff\")\n/// inspect((-255).to_string(radix=16), content=\"-ff\")\n/// ```\n#cfg(not(target=\"js\"))\npub fn Int::to_string(self : Int, radix? : Int = 10) -> String {\n // Validate radix\n if radix < 2 || radix > 36 {\n abort(\"radix must be between 2 and 36\")\n }\n\n // Special case for zero\n if self == 0 {\n return \"0\"\n }\n\n // Handle negative numbers\n let is_negative = self < 0\n let num : UInt = if is_negative {\n // Negate and reinterpret as UInt\n // Works correctly for Int::min_value due to two's complement:\n // -Int::min_value wraps to itself, then reinterpreting gives 2147483648U\n (-self).reinterpret_as_uint()\n } else {\n self.reinterpret_as_uint()\n }\n\n // Calculate length, allocate buffer, and write digits\n let buffer = match radix {\n 10 => {\n let digit_len = dec_count32(num)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int_to_string_dec(buffer, num, digit_start, total_len)\n buffer\n }\n 16 => {\n let digit_len = hex_count32(num)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int_to_string_hex(buffer, num, digit_start, total_len)\n buffer\n }\n _ => {\n let digit_len = radix_count32(num, radix)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int_to_string_generic(buffer, num, digit_start, total_len, radix)\n buffer\n }\n }\n\n // Write minus sign if negative\n if is_negative {\n buffer.unsafe_set(0, 0x002D)\n }\n unsafe_fixedarray_uint16_to_string(buffer)\n}\n\n///|\n/// Converts an unsigned integer to its string representation in the specified radix (base).\n#cfg(not(target=\"js\"))\npub fn UInt::to_string(self : UInt, radix? : Int = 10) -> String {\n // Validate radix\n if radix < 2 || radix > 36 {\n abort(\"radix must be between 2 and 36\")\n }\n\n // Special case for zero\n if self == 0U {\n return \"0\"\n }\n\n // Calculate length, allocate buffer, and write digits\n let buffer = match radix {\n 10 => {\n let len = dec_count32(self)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int_to_string_dec(buffer, self, 0, len)\n buffer\n }\n 16 => {\n let len = hex_count32(self)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int_to_string_hex(buffer, self, 0, len)\n buffer\n }\n _ => {\n let len = radix_count32(self, radix)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int_to_string_generic(buffer, self, 0, len, radix)\n buffer\n }\n }\n unsafe_fixedarray_uint16_to_string(buffer)\n}\n\n//==========================================\n// Int and UInt (JS)\n//==========================================\n\n///|\n/// Converts an integer to its string representation in the specified radix (base).\n#cfg(target=\"js\")\npub fn Int::to_string(self : Int, radix? : Int = 10) -> String {\n int_to_string_js(self, radix)\n}\n\n///|\n#cfg(target=\"js\")\nextern \"js\" fn int_to_string_js(i : Int, radix : Int) -> String =\n #|(x, radix) => {\n #| return x.toString(radix);\n #|}\n\n///|\n/// Converts an unsigned integer to its string representation in the specified radix (base).\n#cfg(target=\"js\")\npub fn UInt::to_string(self : UInt, radix? : Int = 10) -> String {\n uint_to_string_js(self, radix)\n}\n\n///|\n#cfg(target=\"js\")\nextern \"js\" fn uint_to_string_js(i : UInt, radix : Int) -> String =\n #|(x, radix) => {\n #| return (x >>> 0).toString(radix);\n #|}\n\n//==========================================\n// Int64 and UInt64\n//==========================================\n\n///|\n/// Calculates the number of decimal digits in a u64 value\n#cfg(not(target=\"js\"))\nfn dec_count64(value : UInt64) -> Int {\n // Binary search: split 1-20 digits into halves\n if value >= 10000000000UL { // >= 10^10 means 11+ digits\n if value >= 100000000000000UL { // >= 10^14 means 15+ digits\n if value >= 10000000000000000UL { // >= 10^16 means 17+ digits\n if value >= 1000000000000000000UL { // >= 10^18 means 19+ digits\n if value >= 10000000000000000000UL { // >= 10^19 means 20 digits\n 20\n } else {\n 19\n }\n } else if value >= 100000000000000000UL { // >= 10^17 means 18 digits\n 18\n } else {\n 17\n }\n } else if value >= 1000000000000000UL { // >= 10^15 means 16 digits\n 16\n } else {\n 15\n }\n } else if value >= 1000000000000UL { // >= 10^12 means 13+ digits\n if value >= 10000000000000UL { // >= 10^13 means 14 digits\n 14\n } else {\n 13\n }\n } else if value >= 100000000000UL { // >= 10^11 means 12 digits\n 12\n } else {\n 11\n }\n } else if value >= 100000UL { // >= 10^5 means 6+ digits\n if value >= 10000000UL { // >= 10^7 means 8+ digits\n if value >= 1000000000UL { // >= 10^9 means 10 digits\n 10\n } else if value >= 100000000UL { // >= 10^8 means 9 digits\n 9\n } else {\n 8\n }\n } else if value >= 1000000UL { // >= 10^6 means 7 digits\n 7\n } else {\n 6\n }\n } else if value >= 1000UL { // >= 10^3 means 4+ digits\n if value >= 10000UL { // >= 10^4 means 5 digits\n 5\n } else {\n 4\n }\n } else if value >= 100UL { // >= 10^2 means 3 digits\n 3\n } else if value >= 10UL { // >= 10^1 means 2 digits\n 2\n } else {\n 1\n }\n}\n\n///|\n/// Calculates the number of hex digits needed for a u64 value\n#cfg(not(target=\"js\"))\nfn hex_count64(value : UInt64) -> Int {\n if value == 0UL {\n 1\n } else {\n let leading_zeros = value.clz()\n (63 - leading_zeros) / 4 + 1\n }\n}\n\n///|\n/// Calculates the number of digits needed for a u64 value in any radix\n#cfg(not(target=\"js\"))\nfn radix_count64(value : UInt64, radix : Int) -> Int {\n if value == 0UL {\n return 1\n }\n let base = radix.to_uint64()\n for num = value, count = 0; num > 0UL; {\n continue num / base, count + 1\n } nobreak {\n count\n }\n}\n\n///|\n/// Converts an unsigned 64-bit integer to hexadecimal\n#cfg(not(target=\"js\"))\nfn int64_to_string_hex(\n buffer : FixedArray[UInt16],\n num : UInt64,\n digit_start : Int,\n total_len : Int,\n) -> Unit {\n // Process 2 hex digits (1 byte) at a time\n let (offset, n) = for offset = total_len - digit_start, n = num; offset >= 2; {\n let byte_val = n.land(0xFFUL).to_int()\n let hi = byte_val / 16\n let lo = byte_val % 16\n buffer.unsafe_set(digit_start + offset - 2, ALPHABET.unsafe_get(hi))\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(lo))\n continue offset - 2, n >> 8\n } nobreak {\n (offset, n)\n }\n\n // Handle remaining single hex digit\n if offset == 1 {\n let nibble = n.land(0xFUL).to_int()\n buffer.unsafe_set(digit_start, ALPHABET.unsafe_get(nibble))\n }\n}\n\n///|\n/// Generic radix conversion for any base 2-36 (64-bit)\n#cfg(not(target=\"js\"))\nfn int64_to_string_generic(\n buffer : FixedArray[UInt16],\n num : UInt64,\n digit_start : Int,\n total_len : Int,\n radix : Int,\n) -> Unit {\n let base = radix.to_uint64()\n if (radix & (radix - 1)) == 0 {\n // Power-of-two radix: use bit shifts\n let shift = radix.ctz()\n let mask = base - 1UL\n for offset = total_len - digit_start, n = num; n > 0UL; {\n let digit = n.land(mask).to_int()\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(digit))\n continue offset - 1, n >> shift\n }\n } else {\n // General radix: use division\n for offset = total_len - digit_start, n = num; n > 0UL; {\n let q = n / base\n let digit = (n - q * base).to_int()\n buffer.unsafe_set(digit_start + offset - 1, ALPHABET.unsafe_get(digit))\n continue offset - 1, q\n }\n }\n}\n\n///|\n/// Converts an unsigned 64-bit integer to decimal string\n#cfg(not(target=\"js\"))\nfn int64_to_string_dec(\n buffer : FixedArray[UInt16],\n num : UInt64,\n digit_start : Int,\n total_len : Int,\n) -> Unit {\n // Process digits in groups of 4 (chunks of 10000)\n let (num, offset) = for num = num, offset = total_len - digit_start; num >=\n 10000UL; {\n let t = num / 10000UL\n let r = (num % 10000UL).to_int()\n let d1 = r / 100\n let d2 = r % 100\n let d1_hi = (0x30 + d1 / 10).to_uint16()\n let d1_lo = (0x30 + d1 % 10).to_uint16()\n let d2_hi = (0x30 + d2 / 10).to_uint16()\n let d2_lo = (0x30 + d2 % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 4, d1_hi)\n buffer.unsafe_set(digit_start + offset - 3, d1_lo)\n buffer.unsafe_set(digit_start + offset - 2, d2_hi)\n buffer.unsafe_set(digit_start + offset - 1, d2_lo)\n continue t, offset - 4\n } nobreak {\n (num, offset)\n }\n\n // Handle remaining digits (< 10000)\n // Process pairs of digits\n let (remaining, offset) = for remaining = num.to_int(), offset = offset; remaining >=\n 100; {\n let t = remaining / 100\n let d = remaining % 100\n let d_hi = (0x30 + d / 10).to_uint16()\n let d_lo = (0x30 + d % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 2, d_hi)\n buffer.unsafe_set(digit_start + offset - 1, d_lo)\n continue t, offset - 2\n } nobreak {\n (remaining, offset)\n }\n\n // Handle final 1 or 2 digits\n if remaining >= 10 {\n let d_hi = (0x30 + remaining / 10).to_uint16()\n let d_lo = (0x30 + remaining % 10).to_uint16()\n buffer.unsafe_set(digit_start + offset - 2, d_hi)\n buffer.unsafe_set(digit_start + offset - 1, d_lo)\n } else {\n buffer.unsafe_set(digit_start + offset - 1, (0x30 + remaining).to_uint16())\n }\n}\n\n///|\n/// Converts a 64-bit integer to its string representation in the specified radix (base).\n#cfg(not(target=\"js\"))\npub fn Int64::to_string(self : Int64, radix? : Int = 10) -> String {\n // Validate radix\n if radix < 2 || radix > 36 {\n abort(\"radix must be between 2 and 36\")\n }\n\n // Special case for zero\n if self == 0L {\n return \"0\"\n }\n\n // Handle negative numbers\n let is_negative = self < 0L\n let num : UInt64 = if is_negative {\n // Negate and reinterpret as UInt64\n // Works correctly for Int64::min_value due to two's complement\n (-self).reinterpret_as_uint64()\n } else {\n self.reinterpret_as_uint64()\n }\n\n // Calculate length, allocate buffer, and write digits\n let buffer = match radix {\n 10 => {\n let digit_len = dec_count64(num)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int64_to_string_dec(buffer, num, digit_start, total_len)\n buffer\n }\n 16 => {\n let digit_len = hex_count64(num)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int64_to_string_hex(buffer, num, digit_start, total_len)\n buffer\n }\n _ => {\n let digit_len = radix_count64(num, radix)\n let total_len = digit_len + (if is_negative { 1 } else { 0 })\n let buffer : FixedArray[UInt16] = FixedArray::make(total_len, 0)\n let digit_start = if is_negative { 1 } else { 0 }\n int64_to_string_generic(buffer, num, digit_start, total_len, radix)\n buffer\n }\n }\n\n // Write minus sign if negative\n if is_negative {\n buffer.unsafe_set(0, 0x002D)\n }\n unsafe_fixedarray_uint16_to_string(buffer)\n}\n\n///|\n/// Converts an unsigned 64-bit integer to its string representation in the specified radix (base).\n#cfg(not(target=\"js\"))\npub fn UInt64::to_string(self : UInt64, radix? : Int = 10) -> String {\n // Validate radix\n if radix < 2 || radix > 36 {\n abort(\"radix must be between 2 and 36\")\n }\n\n // Special case for zero\n if self == 0UL {\n return \"0\"\n }\n\n // Calculate length, allocate buffer, and write digits\n let buffer = match radix {\n 10 => {\n let len = dec_count64(self)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int64_to_string_dec(buffer, self, 0, len)\n buffer\n }\n 16 => {\n let len = hex_count64(self)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int64_to_string_hex(buffer, self, 0, len)\n buffer\n }\n _ => {\n let len = radix_count64(self, radix)\n let buffer : FixedArray[UInt16] = FixedArray::make(len, 0)\n int64_to_string_generic(buffer, self, 0, len, radix)\n buffer\n }\n }\n unsafe_fixedarray_uint16_to_string(buffer)\n}\n\n///|\n/// Converts a 64-bit integer to its string representation in the specified radix (base).\n#cfg(target=\"js\")\npub fn Int64::to_string(self : Int64, radix? : Int = 10) -> String {\n int64_to_string_js(self, radix)\n}\n\n///|\n#cfg(target=\"js\")\nextern \"js\" fn int64_to_string_js(num : Int64, radix : Int) -> String =\n #|(num, radix) => BigInt.asIntN(64, num).toString(radix)\n\n///|\n/// Converts an unsigned 64-bit integer to its string representation in the specified radix (base).\n#cfg(target=\"js\")\npub fn UInt64::to_string(self : UInt64, radix? : Int = 10) -> String {\n uint64_to_string_js(self, radix)\n}\n\n///|\n#cfg(target=\"js\")\nextern \"js\" fn uint64_to_string_js(num : UInt64, radix : Int) -> String =\n #|(num, radix) => num.toString(radix)\n\n//==========================================\n// Int16 and UInt16\n//==========================================\n\n///|\n/// Convert `UInt16` to string with optional radix.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect((255 : UInt16).to_string(), content=\"255\")\n/// inspect((255 : UInt16).to_string(radix=16), content=\"ff\")\n/// }\n/// ```\npub fn UInt16::to_string(self : UInt16, radix? : Int = 10) -> String {\n self.to_int().to_string(radix~)\n}\n\n//==========================================\n// Test cases\n//==========================================\n\n///|\ntest \"UInt::to_string\" {\n inspect(0U, content=\"0\")\n inspect(17U, content=\"17\")\n inspect(4294967295U, content=\"4294967295\")\n}\n\n///|\ntest \"to_string\" {\n assert_eq((0x100).to_string(), \"256\")\n assert_eq(\"\\{0x100}\", \"256\")\n assert_eq(0x200U.to_string(), \"512\")\n assert_eq(\"\\{0x200U}\", \"512\")\n assert_eq(0x300L.to_string(), \"768\")\n assert_eq(\"\\{0x300L}\", \"768\")\n assert_eq(0x400UL.to_string(), \"1024\")\n assert_eq(\"\\{0x400UL}\", \"1024\")\n}\n\n///|\ntest \"panic to_string_by_radix/illegal_radix\" {\n ignore((1).to_string(radix=1))\n ignore((1).to_string(radix=37))\n ignore(1L.to_string(radix=0))\n ignore(1L.to_string(radix=42))\n ignore(1U.to_string(radix=-1))\n ignore(1U.to_string(radix=73))\n ignore(1UL.to_string(radix=-100))\n ignore(1UL.to_string(radix=100))\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Writes the string representation of an object to the StringBuilder.\n#alias(write)\npub fn[T : Show] StringBuilder::write_object(\n self : StringBuilder,\n obj : T,\n) -> Unit {\n obj.output(self)\n}\n\n///|\n/// Writes characters from an iterator to the StringBuilder. \n///\n/// Parameters:\n///\n/// * `self` : The StringBuilder to write to.\n/// * `iter` : An iterator yielding characters to write.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sb = StringBuilder()\n/// let chars = \"Hello🤣\".iter()\n/// sb.write_iter(chars)\n/// assert_eq(sb.to_string(), \"Hello🤣\")\n/// }\n/// ```\npub fn StringBuilder::write_iter(\n self : StringBuilder,\n iter : Iter[Char],\n) -> Unit {\n for ch in iter {\n self.write_char(ch)\n }\n}\n\n///|\n/// Writes a StringView to the StringBuilder.\n/// \n/// This is more efficient than converting the StringView to a String first,\n/// as it directly writes the viewed portion without creating intermediate strings.\n/// \n/// Parameters:\n///\n/// * `self` : The StringBuilder to write to.\n/// * `view` : The StringView to write.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sb = StringBuilder()\n/// let str = \"Hello, world!\"\n/// let view = str[7:12] // \"world\"\n/// sb.write_stringview(view)\n/// assert_eq(sb.to_string(), \"world\")\n/// }\n/// ```\npub fn StringBuilder::write_stringview(\n self : StringBuilder,\n view : StringView,\n) -> Unit {\n let start = view.start()\n let end = view.end()\n self.write_substring(view.str(), start, end - start)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Returns the offset (charcode index) of the first occurrence of the given\n/// substring. If the substring is not found, it returns None.\npub fn StringView::find(self : StringView, str : StringView) -> Int? {\n if str.length() <= 4 {\n brute_force_find(self, str)\n } else {\n boyer_moore_horspool_find(self, str)\n }\n // TODO: When the pattern string is long (>= 256),\n // consider using Two-Way algorithm to ensure linear time complexity.\n}\n\n///|\n/// Simple brute force string search algorithm\n/// Scans the haystack left to right, matching the needle at each position\nfn brute_force_find(haystack : StringView, needle : StringView) -> Int? {\n let haystack_len = haystack.length()\n let needle_len = needle.length()\n guard needle_len > 0 else { return Some(0) }\n guard haystack_len >= needle_len else { return None }\n let needle_first = needle.unsafe_get(0)\n let forward_len = haystack_len - needle_len\n for i = 0; i <= forward_len; {\n if haystack.unsafe_get(i) != needle_first {\n continue i + 1\n }\n // Check remaining charcodes for full match\n for j in 1..<needle_len {\n if haystack.unsafe_get(i + j) != needle.unsafe_get(j) {\n break\n }\n } nobreak {\n return Some(i)\n }\n continue i + 1\n }\n None\n}\n\n///|\n/// Boyer-Moore-Horspool algorithm for string search (left to right)\n/// More efficient than brute force for longer patterns by using bad char heuristic\nfn boyer_moore_horspool_find(\n haystack : StringView,\n needle : StringView,\n) -> Int? {\n let haystack_len = haystack.length()\n let needle_len = needle.length()\n guard needle_len > 0 else { return Some(0) }\n guard haystack_len >= needle_len else { return None }\n // Build skip table\n let skip_table = FixedArray::make(1 << 8, needle_len)\n for i in 0..<(needle_len - 1) {\n skip_table[needle.unsafe_get(i).to_int() & 0xFF] = needle_len - 1 - i\n }\n for i = 0\n i <= haystack_len - needle_len\n i = i +\n skip_table[haystack.unsafe_get(i + needle_len - 1).to_int() & 0xFF] {\n // Check all charcodes for match at current position\n for j in 0..<=(needle_len - 1) {\n if haystack.unsafe_get(i + j) != needle.unsafe_get(j) {\n break\n }\n } nobreak {\n return Some(i)\n }\n }\n None\n}\n\n///|\ntest \"boyer_moore_horspool_find edge cases\" {\n assert_true(boyer_moore_horspool_find(\"abc\", \"\") == Some(0))\n assert_true(boyer_moore_horspool_find(\"ab\", \"abcd\") == None)\n}\n\n///|\ntest \"boyer_moore_horspool_rev_find edge cases\" {\n assert_true(boyer_moore_horspool_rev_find(\"abc\", \"\") == Some(3))\n assert_true(boyer_moore_horspool_rev_find(\"ab\", \"abcd\") == None)\n}\n\n///|\n/// Returns the offset of the first occurrence of the given substring. If the\n/// substring is not found, it returns None.\npub fn String::find(self : String, str : StringView) -> Int? {\n self[:].find(str)\n}\n\n///|\ntest \"find\" {\n assert_true(\"hello\".find(\"o\") == Some(4))\n assert_true(\"hello\".find(\"l\") == Some(2))\n assert_true(\"hello\".find(\"hello\") == Some(0))\n assert_true(\"hello\".find(\"h\") == Some(0))\n assert_true(\"hello\".find(\"\") == Some(0))\n assert_true(\"hello\".find(\"world\") == None)\n assert_true(\"\".find(\"\") == Some(0))\n assert_true(\"\".find(\"a\") == None)\n assert_true(\"hello hello\".find(\"hello\") == Some(0))\n assert_true(\"aaa\".find(\"aa\") == Some(0))\n assert_true(\"😀😀\".find(\"😀\") == Some(0))\n assert_true(\n (\"😀😀aa\".repeat(20) + \"😀😀😀😀\").find(\"😀😀😀😀\") ==\n Some(120),\n )\n assert_true(\n (\"😀😀😀😀\" + \"😀😀aa\".repeat(20)).find(\"😀😀😀😀\") ==\n Some(0),\n )\n}\n\n///|\n/// Returns the offset of the first character that satisfies the given predicate.\n/// If no such character is found, it returns None.\n#locals(pred)\npub fn StringView::find_by(self : StringView, pred : (Char) -> Bool) -> Int? {\n for i, c in self {\n if pred(c) {\n return Some(i)\n }\n }\n None\n}\n\n///|\n/// Returns the offset of the first character that satisfies the given predicate.\n/// If no such character is found, it returns None.\npub fn String::find_by(self : String, pred : (Char) -> Bool) -> Int? {\n self[:].find_by(pred)\n}\n\n///|\ntest \"find_by\" {\n assert_true(\"hello\".find_by(c => c == 'o') == Some(4))\n assert_true(\"hello\".find_by(c => c == 'l') == Some(2))\n assert_true(\"hello\".find_by(c => c == 'z') == None)\n assert_true(\"\".find_by(c => c == 'a') == None)\n assert_true(\"hello\".find_by(c => c is ('0'..='9')) == None)\n assert_true(\"hello123\".find_by(c => c is ('0'..='9')) == Some(5))\n assert_true(\"hello\".find_by(c => c is ('A'..='Z')) == None)\n assert_true(\"Hello\".find_by(c => c is ('A'..='Z')) == Some(0))\n assert_true(\"αβγ\".find_by(c => c == 'β') == Some(1))\n assert_true(\"😀😁😂\".find_by(c => c == '😂') == Some(2))\n}\n\n///|\n/// Returns the offset of the last occurrence of the given substring. If the\n/// substring is not found, it returns None.\npub fn StringView::rev_find(self : StringView, str : StringView) -> Int? {\n if str.length() <= 4 {\n brute_force_rev_find(self, str)\n } else {\n boyer_moore_horspool_rev_find(self, str)\n }\n // TODO: When the pattern string is long (>= 256),\n // consider using Two-Way algorithm to ensure linear time complexity.\n}\n\n///|\n/// Simple brute force string search algorithm\n/// Scans the haystack right to left, matching the needle at each position\nfn brute_force_rev_find(haystack : StringView, needle : StringView) -> Int? {\n let haystack_len = haystack.length()\n let needle_len = needle.length()\n guard needle_len > 0 else { return Some(haystack_len) }\n guard haystack_len >= needle_len else { return None }\n let needle_first = needle.unsafe_get(0)\n for i = haystack_len - needle_len; i >= 0; {\n if haystack.unsafe_get(i) != needle_first {\n continue i - 1\n }\n // Check remaining charcodes for full match\n for j in 1..<needle_len {\n if haystack.unsafe_get(i + j) != needle.unsafe_get(j) {\n break\n }\n } nobreak {\n return Some(i)\n }\n continue i - 1\n }\n None\n}\n\n///|\n/// Boyer-Moore-Horspool algorithm for reverse string search (right to left)\n/// More efficient than brute force for longer patterns by using bad char heuristic\nfn boyer_moore_horspool_rev_find(\n haystack : StringView,\n needle : StringView,\n) -> Int? {\n let haystack_len = haystack.length()\n let needle_len = needle.length()\n guard needle_len > 0 else { return Some(haystack_len) }\n guard haystack_len >= needle_len else { return None }\n let skip_table = FixedArray::make(1 << 8, needle_len)\n for i in needle_len>..1 {\n skip_table[needle.unsafe_get(i).to_int() & 0xFF] = i\n }\n for i = haystack_len - needle_len\n i >= 0\n i = i - skip_table[haystack.unsafe_get(i).to_int() & 0xFF] {\n // Check all charcodes for match at current position\n for j in 0..<needle_len {\n if haystack.unsafe_get(i + j) != needle.unsafe_get(j) {\n break\n }\n } nobreak {\n return Some(i)\n }\n }\n None\n}\n\n///|\n/// Returns the offset (charcode index) of the last occurrence of the given\n/// substring. If the substring is not found, it returns None.\npub fn String::rev_find(self : String, str : StringView) -> Int? {\n self[:].rev_find(str)\n}\n\n///|\ntest \"rev_find\" {\n assert_true(\"hello\".rev_find(\"o\") == Some(4))\n assert_true(\"hello\".rev_find(\"l\") == Some(3))\n assert_true(\"hello\".rev_find(\"hello\") == Some(0))\n assert_true(\"hello\".rev_find(\"h\") == Some(0))\n assert_true(\"hello\".rev_find(\"\") == Some(5))\n assert_true(\"hello\".rev_find(\"world\") == None)\n assert_true(\"\".rev_find(\"\") == Some(0))\n assert_true(\"\".rev_find(\"a\") == None)\n assert_true(\"hello hello\".rev_find(\"hello\") == Some(6))\n assert_true(\"aaa\".rev_find(\"aa\") == Some(1))\n assert_true(\"😀😀\".rev_find(\"😀\") == Some(2))\n assert_true(\n (\"😀😀aa\".repeat(20) + \"😀😀😀😀\").rev_find(\"😀😀😀😀\") ==\n Some(120),\n )\n assert_true(\n (\"😀😀😀😀\" + \"😀😀aa\".repeat(20)).rev_find(\"😀😀😀😀\") ==\n Some(4),\n )\n}\n\n///|\n/// Returns true if the given substring is suffix of this string.\n#alias(ends_with, deprecated)\npub fn StringView::has_suffix(self : StringView, str : StringView) -> Bool {\n self.rev_find(str) is Some(i) && i == self.length() - str.length()\n}\n\n///|\n/// Returns true if the given substring is suffix of this string.\n#alias(ends_with, deprecated)\npub fn String::has_suffix(self : String, str : StringView) -> Bool {\n self[:].has_suffix(str)\n}\n\n///|\ntest \"has_suffix\" {\n inspect(\"hello\".has_suffix(\"lo\"), content=\"true\")\n inspect(\"hello\".has_suffix(\"hello\"), content=\"true\")\n inspect(\"hello\".has_suffix(\"\"), content=\"true\")\n inspect(\"hello\".has_suffix(\"world\"), content=\"false\")\n inspect(\"hello\".has_suffix(\"hel\"), content=\"false\")\n inspect(\"\".has_suffix(\"\"), content=\"true\")\n inspect(\"\".has_suffix(\"a\"), content=\"false\")\n inspect(\"hello world\".has_suffix(\"world\"), content=\"true\")\n inspect(\"😀😀\".has_suffix(\"😀\"), content=\"true\")\n inspect(\"😀😀\".has_suffix(\"😀😀\"), content=\"true\")\n}\n\n///|\n/// Returns true if this string starts with the given substring.\n#alias(starts_with, deprecated)\npub fn StringView::has_prefix(self : StringView, str : StringView) -> Bool {\n self.find(str) is Some(i) && i == 0\n}\n\n///|\n/// Returns true if this string starts with the given substring.\n#alias(starts_with, deprecated)\npub fn String::has_prefix(self : String, str : StringView) -> Bool {\n self[:].has_prefix(str)\n}\n\n///|\ntest \"has_prefix\" {\n inspect(\"hello\".has_prefix(\"h\"), content=\"true\")\n inspect(\"hello\".has_prefix(\"he\"), content=\"true\")\n inspect(\"hello\".has_prefix(\"\"), content=\"true\")\n inspect(\"hello\".has_prefix(\"world\"), content=\"false\")\n inspect(\"hello\".has_prefix(\"lo\"), content=\"false\")\n inspect(\"\".has_prefix(\"\"), content=\"true\")\n inspect(\"\".has_prefix(\"a\"), content=\"false\")\n inspect(\"😀hello\".has_prefix(\"😀\"), content=\"true\")\n inspect(\"😀😃hello\".has_prefix(\"😀😃\"), content=\"true\")\n inspect(\"😀hello\".has_prefix(\"😃\"), content=\"false\")\n inspect(\"hello😀\".has_prefix(\"😀\"), content=\"false\")\n}\n\n///|\n/// Removes the given suffix from the string if it exists.\n///\n/// Returns `Some(prefix)` if the string ends with the given suffix,\n/// where `prefix` is the string without the suffix.\n/// Returns `None` if the string does not end with the suffix.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"hello world\".strip_suffix(\" world\") == Some(\"hello\"[:]))\n/// assert_true(\"hello world\".strip_suffix(\" moon\") == None)\n/// assert_true(\"hello\".strip_suffix(\"hello\") == Some(\"\"[:]))\n/// }\n/// ```\n#alias(chop_suffix)\npub fn String::strip_suffix(self : String, suffix : StringView) -> StringView? {\n self[:].strip_suffix(suffix)\n}\n\n///|\ntest \"strip_prefix\" {\n assert_true(\"hello world\".strip_prefix(\"hello \") == Some(\"world\"[:]))\n assert_true(\"hello world\".strip_prefix(\"hi \") == None)\n assert_true(\"hello\".strip_prefix(\"hello\") == Some(\"\"[:]))\n assert_true(\"\".strip_prefix(\"\") == Some(\"\"[:]))\n assert_true(\"\".strip_prefix(\"a\") == None)\n assert_true(\"abc\".strip_prefix(\"\") == Some(\"abc\"[:]))\n assert_true(\"😀hello\".strip_prefix(\"😀\") == Some(\"hello\"[:]))\n assert_true(\"😀😃hello\".strip_prefix(\"😀😃\") == Some(\"hello\"[:]))\n}\n\n///|\ntest \"strip_suffix\" {\n assert_true(\"hello world\".strip_suffix(\" world\") == Some(\"hello\"[:]))\n assert_true(\"hello world\".strip_suffix(\" moon\") == None)\n assert_true(\"hello\".strip_suffix(\"hello\") == Some(\"\"[:]))\n assert_true(\"\".strip_suffix(\"\") == Some(\"\"[:]))\n assert_true(\"\".strip_suffix(\"a\") == None)\n assert_true(\"abc\".strip_suffix(\"\") == Some(\"abc\"[:]))\n assert_true(\"hello😀\".strip_suffix(\"😀\") == Some(\"hello\"[:]))\n assert_true(\"hello😀😃\".strip_suffix(\"😀😃\") == Some(\"hello\"[:]))\n}\n\n///|\n/// Removes the given prefix from the string if it exists.\n///\n/// Returns `Some(suffix)` if the string starts with the given prefix,\n/// where `suffix` is the string without the prefix.\n/// Returns `None` if the string does not start with the prefix.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"hello world\".strip_prefix(\"hello \") == Some(\"world\"[:]))\n/// assert_true(\"hello world\".strip_prefix(\"hi \") == None)\n/// assert_true(\"hello\".strip_prefix(\"hello\") == Some(\"\"[:]))\n/// }\n/// ```\n#alias(chop_prefix)\npub fn String::strip_prefix(self : String, prefix : StringView) -> StringView? {\n self[:].strip_prefix(prefix)\n}\n\n///|\n/// Removes the given prefix from the view if it exists.\n///\n/// Returns `Some(suffix)` if the view starts with the given prefix,\n/// where `suffix` is the view without the prefix.\n/// Returns `None` if the view does not start with the prefix.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let view = \"hello world\"[:]\n/// assert_true(view.strip_prefix(\"hello \") == Some(\"world\"[:]))\n/// assert_true(view.strip_prefix(\"hi \") == None)\n/// assert_true(view.strip_prefix(\"hello world\") == Some(\"\"[:]))\n/// }\n/// ```\n#alias(chop_prefix)\npub fn StringView::strip_prefix(\n self : StringView,\n prefix : StringView,\n) -> StringView? {\n let prefix_len = prefix.length()\n if self.length() >= prefix_len && self.view(end_offset=prefix_len) == prefix {\n Some(self.view(start_offset=prefix_len))\n } else {\n None\n }\n}\n\n///|\n/// Removes the given suffix from the view if it exists.\n///\n/// Returns `Some(prefix)` if the view ends with the given suffix,\n/// where `prefix` is the view without the suffix.\n/// Returns `None` if the view does not end with the suffix.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let view = \"hello world\"[:]\n/// assert_true(view.strip_suffix(\" world\") == Some(\"hello\"[:]))\n/// assert_true(view.strip_suffix(\" moon\") == None)\n/// assert_true(view.strip_suffix(\"hello world\") == Some(\"\"[:]))\n/// }\n/// ```\n#alias(chop_suffix)\npub fn StringView::strip_suffix(\n self : StringView,\n suffix : StringView,\n) -> StringView? {\n let self_len = self.length()\n let suffix_len = suffix.length()\n if self_len >= suffix_len &&\n self.view(start_offset=self_len - suffix_len) == suffix {\n Some(self.view(end_offset=self_len - suffix_len))\n } else {\n None\n }\n}\n\n///|\n/// Converts the View into an array of Chars.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let view = \"Hello🤣xa\"[1:-1]\n/// let chars = view.to_array()\n/// @debug.debug_inspect(chars, content=\"['e', 'l', 'l', 'o', '🤣', 'x']\")\n/// }\n/// ```\npub fn StringView::to_array(self : StringView) -> Array[Char] {\n self\n .iter()\n .fold(init=Array::new(capacity=self.length()), (rv, c) => {\n rv.push(c)\n rv\n })\n}\n\n///|\n/// Convert to `bytes`.\n#deprecated(\"Check `@encoding/utf8.encode`\")\n#coverage.skip\npub fn StringView::to_bytes(self : StringView) -> Bytes {\n let array = FixedArray::make(self.length() * 2, Byte::default())\n array.blit_from_string(0, self.data(), self.start_offset(), self.length())\n array |> unsafe_to_bytes\n}\n\n///|\ntest \"View::strip_prefix\" {\n let view = \"hello world\"[:]\n assert_true(view.strip_prefix(\"hello \") == Some(\"world\"[:]))\n assert_true(view.strip_prefix(\"hi \") == None)\n assert_true(view.strip_prefix(\"hello world\") == Some(\"\"[:]))\n assert_true(view.strip_prefix(\"\") == Some(\"hello world\"[:]))\n let empty_view = \"\"[:]\n assert_true(empty_view.strip_prefix(\"\") == Some(\"\"[:]))\n assert_true(empty_view.strip_prefix(\"a\") == None)\n let unicode_view = \"😀hello😃\"[:]\n assert_true(unicode_view.strip_prefix(\"😀\") == Some(\"hello😃\"[:]))\n assert_true(unicode_view.strip_prefix(\"😃\") == None)\n}\n\n///|\ntest \"View::strip_suffix\" {\n let view = \"hello world\"[:]\n assert_true(view.strip_suffix(\" world\") == Some(\"hello\"[:]))\n assert_true(view.strip_suffix(\" moon\") == None)\n assert_true(view.strip_suffix(\"hello world\") == Some(\"\"[:]))\n assert_true(view.strip_suffix(\"\") == Some(\"hello world\"[:]))\n let empty_view = \"\"[:]\n assert_true(empty_view.strip_suffix(\"\") == Some(\"\"[:]))\n assert_true(empty_view.strip_suffix(\"a\") == None)\n let unicode_view = \"😀hello😃\"[:]\n assert_true(unicode_view.strip_suffix(\"😃\") == Some(\"😀hello\"[:]))\n assert_true(unicode_view.strip_suffix(\"😀\") == None)\n}\n\n///|\ntest \"View::to_array\" {\n let view = \"Hello🤣\"[:]\n let chars = view.to_array()\n assert_true(chars == ['H', 'e', 'l', 'l', 'o', '🤣'])\n let empty_view = \"\"[:]\n let empty_chars = empty_view.to_array()\n assert_true(empty_chars == [])\n let sub_view = \"Hello World\"[6:11] // \"World\"\n let sub_chars = sub_view.to_array()\n assert_true(sub_chars == ['W', 'o', 'r', 'l', 'd'])\n}\n\n///|\n/// Returns true if this string contains the given substring.\npub fn StringView::contains(self : StringView, str : StringView) -> Bool {\n self.find(str) is Some(_)\n}\n\n///|\n/// Returns true if this string contains the given substring.\npub fn String::contains(self : String, str : StringView) -> Bool {\n self[:].contains(str)\n}\n\n///|\n/// Returns true if this string contains any character from the given set.\npub fn StringView::contains_any(self : StringView, chars~ : StringView) -> Bool {\n match chars {\n [] => false\n [c] => self.contains_char(c) // specialize for single character\n _ =>\n for c in self {\n if chars.contains_char(c) {\n break true\n }\n } nobreak {\n false\n }\n }\n}\n\n///|\n/// Returns true if this string contains any character from the given set.\npub fn String::contains_any(self : String, chars~ : StringView) -> Bool {\n self[:].contains_any(chars~)\n}\n\n///|\ntest \"contains\" {\n inspect(\"hello\".contains(\"o\"), content=\"true\")\n inspect(\"hello\".contains(\"l\"), content=\"true\")\n inspect(\"hello\".contains(\"hello\"), content=\"true\")\n inspect(\"hello\".contains(\"h\"), content=\"true\")\n inspect(\"hello\".contains(\"\"), content=\"true\")\n inspect(\"hello\".contains(\"world\"), content=\"false\")\n inspect(\"\".contains(\"\"), content=\"true\")\n inspect(\"\".contains(\"a\"), content=\"false\")\n inspect(\"hello hello\".contains(\"hello\"), content=\"true\")\n inspect(\"aaa\".contains(\"aa\"), content=\"true\")\n inspect(\"😀😀\".contains(\"😀\"), content=\"true\")\n}\n\n///|\ntest \"contains_any\" {\n inspect(\"hello\".contains_any(chars=\"h\"), content=\"true\")\n inspect(\"hello\".contains_any(chars=\"xyz\"), content=\"false\")\n inspect(\"hello\".contains_any(chars=\"\"), content=\"false\")\n inspect(\"\".contains_any(chars=\"abc\"), content=\"false\")\n inspect(\"😀😃\".contains_any(chars=\"😄😀\"), content=\"true\")\n inspect(\"hello\"[:].contains_any(chars=\"eo\"), content=\"true\")\n}\n\n///|\n/// Returns true if this string contains the given character.\npub fn StringView::contains_char(self : StringView, c : Char) -> Bool {\n let len = self.length()\n // Check empty\n guard len > 0 else { return false }\n let c = c.to_int()\n if c <= 0xFFFF {\n // Search BMP\n for i in 0..<len {\n if self.unsafe_get(i).to_int() == c {\n return true\n }\n }\n } else {\n // Check insufficient\n guard len >= 2 else { return false }\n // Calc surrogate pair\n let adj = c - 0x10000\n let high = 0xD800 + (adj >> 10)\n let low = 0xDC00 + (adj & 0x3FF)\n // Search surrogate pair\n for i = 0; i < len - 1; {\n if self.unsafe_get(i).to_int() == high {\n if self.unsafe_get(i + 1).to_int() == low {\n return true\n }\n continue i + 2\n }\n continue i + 1\n }\n }\n false\n}\n\n///|\n/// Returns true if this string contains the given character.\npub fn String::contains_char(self : String, c : Char) -> Bool {\n self[:].contains_char(c)\n}\n\n///|\ntest \"contains_char\" {\n inspect(\"hello\".contains_char('h'), content=\"true\")\n inspect(\"hello\".contains_char('e'), content=\"true\")\n inspect(\"hello\".contains_char('l'), content=\"true\")\n inspect(\"hello\".contains_char('o'), content=\"true\")\n inspect(\"hello\".contains_char('x'), content=\"false\")\n inspect(\"\".contains_char('a'), content=\"false\")\n inspect(\"hello world\".contains_char(' '), content=\"true\")\n inspect(\"hello world\".contains_char('w'), content=\"true\")\n inspect(\"😀😀\".contains_char('😀'), content=\"true\")\n inspect(\"😀😀\".contains_char('😃'), content=\"false\")\n inspect(\"hello\".contains_char((104).unsafe_to_char()), content=\"true\") // 'h' is 104 in ASCII\n}\n\n///|\n/// Returns the view of the string without the leading characters that are in\n/// the given string.\n#label_migration(chars, alias=char_set)\npub fn StringView::trim_start(\n self : StringView,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n for x = self {\n match x {\n [] as v => break v\n [c, .. rest] as v =>\n if chars.contains_char(c) {\n continue rest\n } else {\n break v\n }\n }\n }\n}\n\n///|\n/// Returns the view of the string without the leading characters that are in\n/// the given string.\n#label_migration(chars, alias=char_set)\npub fn String::trim_start(\n self : String,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n self[:].trim_start(chars~)\n}\n\n///|\ntest \"trim_start\" {\n inspect(\"hello\".trim_start(chars=\"h\"), content=\"ello\")\n inspect(\"hello\".trim_start(chars=\"he\"), content=\"llo\")\n inspect(\"hello\".trim_start(chars=\"eh\"), content=\"llo\")\n inspect(\"hello\".trim_start(chars=\"x\"), content=\"hello\")\n inspect(\"hello\".trim_start(chars=\"\"), content=\"hello\")\n inspect(\"\".trim_start(chars=\"a\"), content=\"\")\n inspect(\" hello\".trim_start(chars=\" \"), content=\"hello\")\n inspect(\"hello world\".trim_start(chars=\"helo\"), content=\" world\")\n inspect(\"😀😀hello\".trim_start(chars=\"😀\"), content=\"hello\")\n inspect(\"😀😃hello\".trim_start(chars=\"😀😃\"), content=\"hello\")\n inspect(\"aaaabc\".trim_start(chars=\"a\"), content=\"bc\")\n inspect(\"aaaa\".trim_start(chars=\"a\"), content=\"\")\n}\n\n///|\n/// Returns the view of the string without the trailing characters that are in\n/// the given string.\n#label_migration(chars, alias=char_set)\npub fn StringView::trim_end(\n self : StringView,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n for x = self {\n match x {\n [] as v => break v\n [.. rest, c] as v =>\n if chars.contains_char(c) {\n continue rest\n } else {\n break v\n }\n }\n }\n}\n\n///|\n/// Returns the view of the string without the trailing characters that are in\n/// the given string.\n// TODO(upstream): label_migration warning does not apply to the current package\n// TODO: make chars optional with default value of whitespace characters\n#label_migration(chars, alias=char_set)\npub fn String::trim_end(\n self : String,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n self[:].trim_end(chars~)\n}\n\n///|\ntest \"trim_end\" {\n inspect(\"hello\".trim_end(chars=\"o\"), content=\"hell\")\n inspect(\"hello\".trim_end(chars=\"lo\"), content=\"he\")\n inspect(\"hello\".trim_end(chars=\"x\"), content=\"hello\")\n inspect(\"hello\".trim_end(chars=\"\"), content=\"hello\")\n inspect(\"\".trim_end(chars=\"a\"), content=\"\")\n inspect(\"hello \".trim_end(chars=\" \"), content=\"hello\")\n inspect(\"hello world\".trim_end(chars=\"dlrow \"), content=\"he\")\n inspect(\"hello😀😀\".trim_end(chars=\"😀\"), content=\"hello\")\n inspect(\"hello😀😃\".trim_end(chars=\"😀😃\"), content=\"hello\")\n inspect(\"abcccc\".trim_end(chars=\"c\"), content=\"ab\")\n inspect(\"cccc\".trim_end(chars=\"c\"), content=\"\")\n}\n\n///|\n/// Returns the view of the string without the leading and trailing characters\n/// that are in the given string.\n#label_migration(chars, alias=char_set)\npub fn StringView::trim(\n self : StringView,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n self.trim_start(chars~).trim_end(chars~)\n}\n\n///|\n/// Returns the view of the string without the leading and trailing characters\n/// that are in the given string.\n#label_migration(chars, alias=char_set)\npub fn String::trim(\n self : String,\n chars? : StringView = \"\\t\\n\\r \",\n) -> StringView {\n self[:].trim(chars~)\n}\n\n///|\ntest \"trim\" {\n inspect(\"hello\".trim(chars=\"h\"), content=\"ello\")\n inspect(\"hello\".trim(chars=\"o\"), content=\"hell\")\n inspect(\"hello\".trim(chars=\"ho\"), content=\"ell\")\n inspect(\"hello\".trim(chars=\"oh\"), content=\"ell\")\n inspect(\"hello\".trim(chars=\"x\"), content=\"hello\")\n inspect(\"hello\".trim(chars=\"\"), content=\"hello\")\n inspect(\"\".trim(chars=\"a\"), content=\"\")\n inspect(\" hello \".trim(chars=\" \"), content=\"hello\")\n inspect(\"hello world\".trim(chars=\"hd\"), content=\"ello worl\")\n inspect(\"😀hello😀\".trim(chars=\"😀\"), content=\"hello\")\n inspect(\"😀😃hello😀😃\".trim(chars=\"😀😃\"), content=\"hello\")\n inspect(\"aaaabcaaa\".trim(chars=\"a\"), content=\"bc\")\n inspect(\"aaaa\".trim(chars=\"a\"), content=\"\")\n inspect(\" hello world \".trim(chars=\" \"), content=\"hello world\")\n inspect(\"abcabc\".trim(chars=\"abc\"), content=\"\")\n}\n\n///|\n/// Returns the view of the string without the leading and trailing spaces.\n#deprecated(\"Use `trim` with default whitespace characters instead\")\npub fn StringView::trim_space(self : StringView) -> StringView {\n self.trim()\n}\n\n///|\n/// Returns the view of the string without the leading and trailing spaces.\n#deprecated(\"Use `trim` with default whitespace characters instead\")\npub fn String::trim_space(self : String) -> StringView {\n self.trim()\n}\n\n///|\ntest \"trim whitespace for string\" {\n inspect(\"hello\".trim(), content=\"hello\")\n inspect(\" hello \".trim(), content=\"hello\")\n inspect(\"hello \".trim(), content=\"hello\")\n inspect(\" hello\".trim(), content=\"hello\")\n inspect(\"\\t\\nhello\\r\\n\".trim(), content=\"hello\")\n inspect(\" hello world \".trim(), content=\"hello world\")\n inspect(\" \".trim(), content=\"\")\n inspect(\"\\n\\r\\t\".trim(), content=\"\")\n inspect(\"\".trim(), content=\"\")\n inspect(\" hello\\nworld\\t\".trim(), content=\"hello\\nworld\")\n}\n\n///|\n/// Returns true if this string is empty.\npub fn StringView::is_empty(self : StringView) -> Bool {\n self.length() == 0\n}\n\n///|\n/// Returns true if this string is empty.\npub fn String::is_empty(self : String) -> Bool {\n self == \"\"\n}\n\n///|\ntest \"is_empty\" {\n inspect(\"\".is_empty(), content=\"true\")\n inspect(\"hello\".is_empty(), content=\"false\")\n inspect(\" \".is_empty(), content=\"false\")\n inspect(\"\\n\".is_empty(), content=\"false\")\n inspect(\"\\t\".is_empty(), content=\"false\")\n inspect(\" \".is_empty(), content=\"false\")\n\n // Test with string views\n let s = \"hello\"\n let empty_view = s[0:0]\n let non_empty_view = s[0:3]\n inspect(empty_view.is_empty(), content=\"true\")\n inspect(non_empty_view.is_empty(), content=\"false\")\n}\n\n///|\n/// Returns true if this string is blank.\npub fn StringView::is_blank(self : StringView) -> Bool {\n self.trim().is_empty()\n}\n\n///|\n/// Returns true if this string is blank.\npub fn String::is_blank(self : String) -> Bool {\n self[:].is_blank()\n}\n\n///|\ntest \"is_blank\" {\n inspect(\"\".is_blank(), content=\"true\")\n inspect(\"hello\".is_blank(), content=\"false\")\n inspect(\" \".is_blank(), content=\"true\")\n inspect(\"\\n\".is_blank(), content=\"true\")\n inspect(\"\\t\".is_blank(), content=\"true\")\n inspect(\" \".is_blank(), content=\"true\")\n inspect(\" \\n\\t\\r \".is_blank(), content=\"true\")\n inspect(\"hello world\".is_blank(), content=\"false\")\n inspect(\" hello \".is_blank(), content=\"false\")\n\n // Test with string views\n let s = \" hello \"\n let blank_view = s[0:3] // \" \"\n let non_blank_view = s[3:8] // \"hello\"\n inspect(blank_view.is_blank(), content=\"true\")\n inspect(non_blank_view.is_blank(), content=\"false\")\n}\n\n///|\n/// Returns a new string with `padding_char`s prefixed to `self` if\n/// `self.char_length() < total_width`. The number of unicode characters in\n/// the returned string is `total_width` if padding is added.\npub fn StringView::pad_start(\n self : StringView,\n total_width : Int,\n padding_char : Char,\n) -> String {\n let len = self.length()\n guard len < total_width else { return self.to_owned() }\n let padding = String::make(total_width - len, padding_char)\n [..padding, ..self]\n}\n\n///|\n/// Returns a new string with `padding_char`s prefixed to `self` if\n/// `self.char_length() < total_width`. The number of unicode characters in\n/// the returned string is `total_width` if padding is added.\npub fn String::pad_start(\n self : String,\n total_width : Int,\n padding_char : Char,\n) -> String {\n let len = self.length()\n guard len < total_width else { return self }\n let padding = String::make(total_width - len, padding_char)\n [..padding, ..self]\n}\n\n///|\ntest \"pad_start\" {\n // Test with regular strings\n inspect(\"2\".pad_start(3, '0'), content=\"002\")\n inspect(\"abc\".pad_start(5, 'x'), content=\"xxabc\")\n inspect(\"hello\".pad_start(4, ' '), content=\"hello\") // No padding needed\n inspect(\"\".pad_start(3, '-'), content=\"---\")\n\n // Test with different padding characters\n inspect(\"test\".pad_start(8, '*'), content=\"****test\")\n inspect(\"123\".pad_start(6, '0'), content=\"000123\")\n\n // Test with string views\n let s = \"hello\"\n let view = s[2:5] // \"llo\"\n inspect(view.pad_start(5, 'x'), content=\"xxllo\")\n\n // Test with Unicode characters\n inspect(\"🌟\".pad_start(3, '✨'), content=\"✨🌟\")\n\n // Edge cases\n inspect(\"abc\".pad_start(0, 'x'), content=\"abc\") // width less than string length\n inspect(\"abc\".pad_start(3, 'x'), content=\"abc\") // width equal to string length\n}\n\n///|\n/// Returns a new string with `padding_char`s appended to `self` if\n/// `self.length() < total_width`. The number of unicode characters in\n/// the returned string is `total_width` if padding is added.\npub fn StringView::pad_end(\n self : StringView,\n total_width : Int,\n padding_char : Char,\n) -> String {\n let len = self.length()\n guard len < total_width else { return self.to_owned() }\n let padding = String::make(total_width - len, padding_char)\n [..self, ..padding]\n}\n\n///|\n/// Returns a new string with `padding_char`s appended to `self` if\n/// `self.length() < total_width`. The number of unicode characters in\n/// the returned string is `total_width` if padding is added.\npub fn String::pad_end(\n self : String,\n total_width : Int,\n padding_char : Char,\n) -> String {\n let len = self.length()\n guard len < total_width else { return self }\n let padding = String::make(total_width - len, padding_char)\n [..self, ..padding]\n}\n\n///|\ntest \"pad_end\" {\n // Test with regular strings\n inspect(\"2\".pad_end(3, '0'), content=\"200\")\n inspect(\"abc\".pad_end(5, 'x'), content=\"abcxx\")\n inspect(\"hello\".pad_end(4, ' '), content=\"hello\") // No padding needed\n inspect(\"\".pad_end(3, '-'), content=\"---\")\n\n // Test with different padding characters\n inspect(\"test\".pad_end(8, '*'), content=\"test****\")\n inspect(\"123\".pad_end(6, '0'), content=\"123000\")\n\n // Test with string views\n let s = \"hello\"\n let view = s[2:5] // \"llo\"\n inspect(view.pad_end(5, 'x'), content=\"lloxx\")\n\n // Test with Unicode characters\n inspect(\"🌟\".pad_end(3, '✨'), content=\"🌟✨\")\n\n // Edge cases\n inspect(\"abc\".pad_end(0, 'x'), content=\"abc\") // width less than string length\n inspect(\"abc\".pad_end(3, 'x'), content=\"abc\") // width equal to string length\n}\n\n///|\n/// Returns a new string with `self` repeated `n` times.\n///\n/// Aborts if `n` is negative. When `n` is `0`, returns the empty string.\npub fn StringView::repeat(self : StringView, n : Int) -> StringView {\n match n {\n _..<0 => abort(\"negative repeat count\")\n 0 => \"\"\n 1 => self\n _ => {\n let len = self.length()\n let total = len * n\n guard len == 0 || total / n == len else {\n abort(\"repeat result too large\")\n }\n let buf = StringBuilder(size_hint=total)\n let str = self.to_owned()\n for _ in 0..<n {\n buf.write_string(str)\n }\n buf.to_string()\n }\n }\n}\n\n///|\n/// Returns a new string with `self` repeated `n` times.\n///\n/// Aborts if `n` is negative. When `n` is `0`, returns the empty string.\npub fn String::repeat(self : String, n : Int) -> String {\n match n {\n _..<0 => abort(\"negative repeat count\")\n 0 => \"\"\n 1 => self\n _ => {\n let len = self.length()\n let total = len * n\n guard len == 0 || total / n == len else {\n abort(\"repeat result too large\")\n }\n let buf = StringBuilder(size_hint=total)\n let str = self.to_string()\n for _ in 0..<n {\n buf.write_string(str)\n }\n buf.to_string()\n }\n }\n}\n\n///|\ntest \"repeat\" {\n // Test with regular strings\n inspect(\"abc\".repeat(3), content=\"abcabcabc\")\n inspect(\"x\".repeat(5), content=\"xxxxx\")\n inspect(\"hello \".repeat(2), content=\"hello hello \")\n\n // Test with empty string\n inspect(\"\".repeat(10), content=\"\")\n\n // Test with string views\n let s = \"hello world\"\n let view = s[6:11] // \"world\"\n inspect(view.repeat(2), content=\"worldworld\")\n\n // Test with Unicode characters\n inspect(\"🌟\".repeat(3), content=\"🌟🌟🌟\")\n inspect(\"✨🌟\".repeat(2), content=\"✨🌟✨🌟\")\n\n // Edge cases\n inspect(\"abc\".repeat(0), content=\"\")\n inspect(\"abc\".repeat(1), content=\"abc\")\n}\n\n///|\ntest \"panic string repeat negative\" {\n let _ = \"abc\".repeat(-5)\n}\n\n///|\ntest \"panic string view repeat negative\" {\n let _ = \"hello\"[1:].repeat(-1)\n}\n\n///|\n/// Returns a new string with the characters in reverse order. It respects\n/// Unicode characters and surrogate pairs but not grapheme clusters.\npub fn StringView::rev(self : StringView) -> String {\n let buf = StringBuilder(size_hint=self.length())\n for c in self.rev_iter() {\n buf.write_char(c)\n }\n buf.to_string()\n}\n\n///|\n/// Returns a new string with the characters in reverse order. It respects\n/// Unicode characters and surrogate pairs but not grapheme clusters.\npub fn String::rev(self : String) -> String {\n self[:].rev()\n}\n\n///|\ntest \"rev\" {\n inspect(\"hello\".rev(), content=\"olleh\")\n inspect(\"\".rev(), content=\"\")\n inspect(\"abc\".rev(), content=\"cba\")\n inspect(\"😀😃\".rev(), content=\"😃😀\")\n}\n\n///|\n/// Splits the string into all substrings separated by the given separator.\n/// \n/// If the string does not contain the separator and the separator is not empty,\n/// the returned iterator will contain only one element, which is the original\n/// string.\n/// \n/// If the separator is empty, the returned iterator will contain all the\n/// characters in the string as single elements.\npub fn StringView::split(\n self : StringView,\n sep : StringView,\n) -> Iter[StringView] {\n let sep_len = sep.length()\n if sep_len == 0 {\n return self.iter().map(c => c.to_string().view())\n }\n let mut remaining = Some(self)\n Iter::new(() => {\n guard remaining is Some(view) else { None }\n guard view.find(sep) is Some(end) else {\n remaining = None\n Some(view)\n }\n remaining = Some(view.view(start_offset=end + sep_len))\n Some(view.view(end_offset=end))\n })\n}\n\n///|\n/// Splits the string into all substrings separated by the given separator.\n/// \n/// If the string does not contain the separator and the separator is not empty,\n/// the returned iterator will contain only one element, which is the original\n/// string.\n/// \n/// If the separator is empty, the returned iterator will contain all the\n/// characters in the string as single elements.\npub fn String::split(self : String, sep : StringView) -> Iter[StringView] {\n self[:].split(sep)\n}\n\n///|\n/// Splits the string into a pair at the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it splits at the start of the string, returning\n/// an empty prefix and the full string as the suffix.\npub fn StringView::split_once(\n self : StringView,\n needle : StringView,\n) -> (StringView, StringView)? {\n match self.find(needle) {\n Some(index) =>\n Some(\n (\n self.view(end_offset=index),\n self.view(start_offset=index + needle.length()),\n ),\n )\n None => None\n }\n}\n\n///|\n/// Splits the string into a pair at the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it splits at the start of the string, returning\n/// an empty prefix and the full string as the suffix.\npub fn String::split_once(\n self : String,\n needle : StringView,\n) -> (StringView, StringView)? {\n self[:].split_once(needle)\n}\n\n///|\n/// Returns the substring before the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it returns an empty string.\npub fn StringView::before(\n self : StringView,\n needle : StringView,\n) -> StringView? {\n match self.find(needle) {\n Some(index) => Some(self.view(end_offset=index))\n None => None\n }\n}\n\n///|\n/// Returns the substring before the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it returns an empty string.\npub fn String::before(self : String, needle : StringView) -> StringView? {\n self[:].before(needle)\n}\n\n///|\n/// Returns the substring after the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it returns the full string.\npub fn StringView::after(self : StringView, needle : StringView) -> StringView? {\n match self.find(needle) {\n Some(index) => Some(self.view(start_offset=index + needle.length()))\n None => None\n }\n}\n\n///|\n/// Returns the substring after the first occurrence of the separator.\n/// \n/// Returns None if the separator is not found.\n/// \n/// If the separator is empty, it returns the full string.\npub fn String::after(self : String, needle : StringView) -> StringView? {\n self[:].after(needle)\n}\n\n///|\n/// Splits the string into a pair at the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a::b::c\".rev_split_once(\"::\") == Some((\"a::b\"[:], \"c\"[:])))\n/// assert_true(\"nope\".rev_split_once(\"::\") == None)\n/// }\n/// ```\npub fn StringView::rev_split_once(\n self : StringView,\n needle : StringView,\n) -> (StringView, StringView)? {\n match self.rev_find(needle) {\n Some(index) =>\n Some(\n (\n self.view(end_offset=index),\n self.view(start_offset=index + needle.length()),\n ),\n )\n None => None\n }\n}\n\n///|\n/// Splits the string into a pair at the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a::b::c\".rev_split_once(\"::\") == Some((\"a::b\"[:], \"c\"[:])))\n/// }\n/// ```\npub fn String::rev_split_once(\n self : String,\n needle : StringView,\n) -> (StringView, StringView)? {\n self[:].rev_split_once(needle)\n}\n\n///|\n/// Returns the substring before the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a/b/c.txt\".rev_before(\"/\") == Some(\"a/b\"[:]))\n/// }\n/// ```\npub fn StringView::rev_before(\n self : StringView,\n needle : StringView,\n) -> StringView? {\n match self.rev_find(needle) {\n Some(index) => Some(self.view(end_offset=index))\n None => None\n }\n}\n\n///|\n/// Returns the substring before the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a/b/c.txt\".rev_before(\"/\") == Some(\"a/b\"[:]))\n/// }\n/// ```\npub fn String::rev_before(self : String, needle : StringView) -> StringView? {\n self[:].rev_before(needle)\n}\n\n///|\n/// Returns the substring after the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a/b/c.txt\".rev_after(\"/\") == Some(\"c.txt\"[:]))\n/// }\n/// ```\npub fn StringView::rev_after(\n self : StringView,\n needle : StringView,\n) -> StringView? {\n match self.rev_find(needle) {\n Some(index) => Some(self.view(start_offset=index + needle.length()))\n None => None\n }\n}\n\n///|\n/// Returns the substring after the last occurrence of the separator.\n///\n/// Returns None if the separator is not found.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// assert_true(\"a/b/c.txt\".rev_after(\"/\") == Some(\"c.txt\"[:]))\n/// }\n/// ```\npub fn String::rev_after(self : String, needle : StringView) -> StringView? {\n self[:].rev_after(needle)\n}\n\n///|\ntest \"split\" {\n assert_true(\n \"a,b,c\".split(\",\").map(x => x.to_owned()).collect() == [\"a\", \"b\", \"c\"],\n )\n assert_true(\n \"a,b,c\".split(\"\").map(x => x.to_owned()).collect() ==\n [\"a\", \",\", \"b\", \",\", \"c\"],\n )\n assert_true(\n \"apple::orange::banana\".split(\"::\").map(x => x.to_owned()).collect() ==\n [\"apple\", \"orange\", \"banana\"],\n )\n assert_true(\n \"abc\".split(\"\").map(x => x.to_owned()).collect() == [\"a\", \"b\", \"c\"],\n )\n assert_true(\"hello\".split(\",\").map(x => x.to_owned()).collect() == [\"hello\"])\n assert_true(\n \",a,b,c\".split(\",\").map(x => x.to_owned()).collect() == [\"\", \"a\", \"b\", \"c\"],\n )\n assert_true(\n \"a,b,c,\".split(\",\").map(x => x.to_owned()).collect() == [\"a\", \"b\", \"c\", \"\"],\n )\n assert_true(\n \"a,b,c\".split(\"\").map(x => x.to_owned()).collect() ==\n [\"a\", \",\", \"b\", \",\", \"c\"],\n )\n assert_true(\"\".split(\"\").map(x => x.to_owned()).collect() == [])\n assert_true(\"\".split(\",\").map(x => x.to_owned()).collect() == [\"\"])\n assert_true(\n \"😀,😃,😄\".split(\",\").map(x => x.to_owned()).collect() ==\n [\"😀\", \"😃\", \"😄\"],\n )\n assert_true(\n \"a😀b😀c\".split(\"😀\").map(x => x.to_owned()).collect() ==\n [\"a\", \"b\", \"c\"],\n )\n}\n\n///|\ntest \"split_once before after\" {\n assert_true(\"a=b=c\".split_once(\"=\") == Some((\"a\"[:], \"b=c\"[:])))\n assert_true(\"a=b=c\".before(\"=\") == Some(\"a\"[:]))\n assert_true(\"a=b=c\".after(\"=\") == Some(\"b=c\"[:]))\n assert_true(\"nope\".split_once(\"=\") == None)\n assert_true(\"nope\".before(\"=\") == None)\n assert_true(\"nope\".after(\"=\") == None)\n assert_true(\"\".split_once(\"\") == Some((\"\"[:], \"\"[:])))\n assert_true(\"\".before(\"\") == Some(\"\"[:]))\n assert_true(\"\".after(\"\") == Some(\"\"[:]))\n assert_true(\"hello\".split_once(\"\") == Some((\"\"[:], \"hello\"[:])))\n assert_true(\"hello\".before(\"\") == Some(\"\"[:]))\n assert_true(\"hello\".after(\"\") == Some(\"hello\"[:]))\n assert_true(\"😊::🚀\".split_once(\"::\") == Some((\"😊\"[:], \"🚀\"[:])))\n}\n\n///|\ntest \"rev_split_once rev_before rev_after\" {\n assert_true(\"a=b=c\".rev_split_once(\"=\") == Some((\"a=b\"[:], \"c\"[:])))\n assert_true(\"a=b=c\".rev_before(\"=\") == Some(\"a=b\"[:]))\n assert_true(\"a=b=c\".rev_after(\"=\") == Some(\"c\"[:]))\n assert_true(\"nope\".rev_split_once(\"=\") == None)\n assert_true(\"nope\".rev_before(\"=\") == None)\n assert_true(\"nope\".rev_after(\"=\") == None)\n assert_true(\"a/b/c.txt\".rev_before(\"/\") == Some(\"a/b\"[:]))\n assert_true(\"a/b/c.txt\".rev_after(\"/\") == Some(\"c.txt\"[:]))\n assert_true(\"one=two\".rev_split_once(\"=\") == Some((\"one\"[:], \"two\"[:])))\n assert_true(\n \"😊::🚀::⭐\".rev_split_once(\"::\") == Some((\"😊::🚀\"[:], \"⭐\"[:])),\n )\n}\n\n///|\n/// Replaces the first occurrence of `old` with `new` in `self`.\n/// \n/// If `old` is empty, it matches the beginning of the string, and `new` is\n/// prepended to the string.\npub fn StringView::replace(\n self : StringView,\n old~ : StringView,\n new~ : StringView,\n) -> StringView {\n match self.find(old) {\n Some(end) =>\n [\n ..self.view(end_offset=end),\n ..new,\n ..self.view(start_offset=end + old.length()),\n ]\n None => self\n }\n}\n\n///|\n/// Replaces the first occurrence of `old` with `new` in `self`.\n/// \n/// If `old` is empty, it matches the beginning of the string, and `new` is\n/// prepended to the string.\npub fn String::replace(\n self : String,\n old~ : StringView,\n new~ : StringView,\n) -> String {\n match self.find(old) {\n Some(end) =>\n [\n ..self.view(end_offset=end),\n ..new,\n ..self.view(start_offset=end + old.length()),\n ]\n None => self\n }\n}\n\n///|\ntest \"replace\" {\n inspect(\"hello\".replace(old=\"o\", new=\"a\"), content=\"hella\")\n inspect(\"hello\".replace(old=\"l\", new=\"a\"), content=\"healo\")\n inspect(\"hello\".replace(old=\"hello\", new=\"a\"), content=\"a\")\n inspect(\"hello\".replace(old=\"h\", new=\"a\"), content=\"aello\")\n inspect(\"hello\".replace(old=\"\", new=\"a\"), content=\"ahello\")\n inspect(\"hello\".replace(old=\"world\", new=\"a\"), content=\"hello\")\n inspect(\"\".replace(old=\"\", new=\"a\"), content=\"a\")\n}\n\n///|\n/// Replaces all non-overlapping occurrences of `old` with `new` in `self`.\n/// \n/// If `old` is empty, it matches at the beginning of the string and after each\n/// character in the string, so `new` is inserted at the beginning of the string\n/// and after each character.\npub fn StringView::replace_all(\n self : StringView,\n old~ : StringView,\n new~ : StringView,\n) -> StringView {\n let len = self.length()\n let buf = StringBuilder(size_hint=len)\n let old_len = old.length()\n let new = new.to_owned()\n // use write_substring to avoid intermediate allocations\n if old_len == 0 {\n buf.write_string(new)\n for c in self {\n buf.write_char(c)\n buf.write_string(new)\n }\n buf.to_string()\n } else {\n let first_end = self.find(old)\n if first_end is Some(end) {\n for view = self, end = end {\n let seg = view.view(end_offset=end)\n buf.write_substring(seg.data(), seg.start_offset(), seg.length())\n buf.write_string(new)\n // check if there is no more characters after the last occurrence of `old`\n guard end + old_len <= len else { break }\n let next_view = view.view(start_offset=end + old_len)\n guard next_view.find(old) is Some(next_end) else {\n buf.write_substring(\n next_view.data(),\n next_view.start_offset(),\n next_view.length(),\n )\n break\n }\n continue next_view, next_end\n }\n buf.to_string()\n } else {\n self\n }\n }\n}\n\n///|\n/// Replaces all non-overlapping occurrences of `old` with `new` in `self`.\n/// \n/// If `old` is empty, it matches at the beginning of the string and after each\n/// character in the string, so `new` is inserted at the beginning of the string\n/// and after each character.\npub fn String::replace_all(\n self : String,\n old~ : StringView,\n new~ : StringView,\n) -> String {\n let len = self.length()\n let buf = StringBuilder(size_hint=len)\n let old_len = old.length()\n let new = new.to_owned()\n // use write_substring to avoid intermediate allocations\n if old_len == 0 {\n buf.write_string(new)\n for c in self {\n buf.write_char(c)\n buf.write_string(new)\n }\n buf.to_string()\n } else {\n let first_end = self.find(old)\n if first_end is Some(end) {\n for view = self[:], end = end {\n let seg = view.view(end_offset=end)\n buf.write_substring(seg.data(), seg.start_offset(), seg.length())\n buf.write_string(new)\n // check if there is no more characters after the last occurrence of `old`\n guard end + old_len <= len else { break }\n let next_view = view.view(start_offset=end + old_len)\n guard next_view.find(old) is Some(next_end) else {\n buf.write_substring(\n next_view.data(),\n next_view.start_offset(),\n next_view.length(),\n )\n break\n }\n continue next_view, next_end\n }\n buf.to_string()\n } else {\n self\n }\n }\n}\n\n///|\ntest \"replace_all\" {\n assert_eq(\"hello\".replace_all(old=\"o\", new=\"a\"), \"hella\")\n assert_eq(\"hello\".replace_all(old=\"l\", new=\"a\"), \"heaao\")\n assert_eq(\"hello\".replace_all(old=\"ll\", new=\"rr\"), \"herro\")\n assert_eq(\"hello\".replace_all(old=\"hello\", new=\"world\"), \"world\")\n assert_eq(\"hello hello hello\".replace_all(old=\"hello\", new=\"hi\"), \"hi hi hi\")\n assert_eq(\n \"hello hello helloi\".replace_all(old=\"hello\", new=\"hi\"),\n \"hi hi hii\",\n )\n assert_eq(\n \"hi hi hii\".replace_all(old=\"hi\", new=\"hello\"),\n \"hello hello helloi\",\n )\n assert_eq(\"hello\".replace_all(old=\"\", new=\"a\"), \"ahaealalaoa\")\n assert_eq(\"hello\".replace_all(old=\"world\", new=\"a\"), \"hello\")\n assert_eq(\"\".replace_all(old=\"\", new=\"a\"), \"a\")\n assert_eq(\"aaa\".replace_all(old=\"a\", new=\"b\"), \"bbb\")\n assert_eq(\"aaa\".replace_all(old=\"a\", new=\"bb\"), \"bbbbbb\")\n assert_eq(\"aaa\".replace_all(old=\"aa\", new=\"b\"), \"ba\")\n assert_eq(\"🤣🤣🤣\".replace_all(old=\"🤣\", new=\"😊\"), \"😊😊😊\")\n assert_eq(\"abc123abc\".replace_all(old=\"abc\", new=\"xyz\"), \"xyz123xyz\")\n assert_eq(\"abcabcabc\".replace_all(old=\"abc\", new=\"\"), \"\")\n assert_eq(\"abc\".replace_all(old=\"abc\", new=\"\"), \"\")\n assert_eq(\"abc\".replace_all(old=\"\", new=\"x\"), \"xaxbxcx\")\n}\n\n///|\ntest \"String::replace_all boundary cases\" {\n // These tests should trigger the uncovered line 1187: guard end + old_len <= len else { break }\n // This happens when the pattern is found at the very end of the string\n\n // Pattern at the end of string - should trigger the guard condition\n assert_eq(\"helloworld\".replace_all(old=\"world\", new=\"X\"), \"helloX\")\n assert_eq(\"abcdef\".replace_all(old=\"def\", new=\"XYZ\"), \"abcXYZ\")\n\n // Multiple patterns where the last one is at the end\n assert_eq(\"abcabc\".replace_all(old=\"abc\", new=\"X\"), \"XX\")\n\n // Pattern that exactly matches the string length\n assert_eq(\"test\".replace_all(old=\"test\", new=\"done\"), \"done\")\n\n // Empty replacement at the end\n assert_eq(\"remove_me\".replace_all(old=\"_me\", new=\"\"), \"remove\")\n}\n\n///|\ntest \"View::replace_all\" {\n assert_eq(\"hello\"[:].replace_all(old=\"o\", new=\"a\"), \"hella\")\n assert_eq(\"hello\"[:].replace_all(old=\"l\", new=\"a\"), \"heaao\")\n assert_eq(\"hello\"[:].replace_all(old=\"ll\", new=\"rr\"), \"herro\")\n assert_eq(\"hello\"[:].replace_all(old=\"hello\", new=\"world\"), \"world\")\n assert_eq(\n \"hello hello hello\"[:].replace_all(old=\"hello\", new=\"hi\"),\n \"hi hi hi\",\n )\n assert_eq(\n \"hello hello helloi\"[:].replace_all(old=\"hello\", new=\"hi\"),\n \"hi hi hii\",\n )\n assert_eq(\n \"hi hi hii\"[:].replace_all(old=\"hi\", new=\"hello\"),\n \"hello hello helloi\",\n )\n assert_eq(\"hello\"[:].replace_all(old=\"\", new=\"a\"), \"ahaealalaoa\")\n assert_eq(\"hello\"[:].replace_all(old=\"world\", new=\"a\"), \"hello\")\n assert_eq(\"\"[:].replace_all(old=\"\", new=\"a\"), \"a\")\n assert_eq(\"aaa\"[:].replace_all(old=\"a\", new=\"b\"), \"bbb\")\n assert_eq(\"aaa\"[:].replace_all(old=\"a\", new=\"bb\"), \"bbbbbb\")\n assert_eq(\"aaa\"[:].replace_all(old=\"aa\", new=\"b\"), \"ba\")\n assert_eq(\n \"🤣🤣🤣\"[:].replace_all(old=\"🤣\", new=\"😊\"),\n \"😊😊😊\",\n )\n assert_eq(\"abc123abc\"[:].replace_all(old=\"abc\", new=\"xyz\"), \"xyz123xyz\")\n assert_eq(\"abcabcabc\"[:].replace_all(old=\"abc\", new=\"\"), \"\")\n assert_eq(\"abc\"[:].replace_all(old=\"abc\", new=\"\"), \"\")\n assert_eq(\"abc\"[:].replace_all(old=\"\", new=\"x\"), \"xaxbxcx\")\n}\n\n///|\ntest \"View::replace_all boundary cases\" {\n // These tests should trigger the uncovered line 1141: guard end + old_len <= len else { break }\n // This condition triggers when end + old_len > len, meaning we're at the boundary\n\n // Let me trace through the algorithm more carefully...\n // Actually, let me try a different approach - create a scenario where the view length changes\n\n // Try with overlapping patterns or edge cases\n assert_eq(\"abcabc\"[:].replace_all(old=\"abc\", new=\"X\"), \"XX\")\n assert_eq(\"aaaa\"[:].replace_all(old=\"aa\", new=\"b\"), \"bb\")\n\n // Pattern at exact end\n assert_eq(\"hello\"[:].replace_all(old=\"lo\", new=\"X\"), \"helX\")\n\n // Test with empty string edge case\n assert_eq(\"a\"[:].replace_all(old=\"a\", new=\"\"), \"\")\n\n // Let me try to understand when end + old_len > len could happen...\n // Maybe when we have a complex replacement scenario\n inspect(\"Testing boundary condition\", content=\"Testing boundary condition\")\n}\n\n///|\n/// Converts this string to lowercase.\npub fn StringView::to_lower(self : StringView) -> StringView {\n // TODO: deal with non-ascii characters\n guard self.find_by(x => x.is_ascii_uppercase()) is Some(idx) else {\n return self\n }\n let buf = StringBuilder(size_hint=self.length())\n let head = self.view(end_offset=idx)\n buf.write_substring(head.data(), head.start_offset(), head.length())\n for c in self.view(start_offset=idx) {\n if c.is_ascii_uppercase() {\n // 'A' is 65 in ASCII, 'a' is 97, the difference is 32\n buf.write_char((c.to_int() + 32).unsafe_to_char())\n } else {\n buf.write_char(c)\n }\n }\n buf.to_string()\n}\n\n///|\n/// Converts this string to lowercase.\npub fn String::to_lower(self : String) -> String {\n // TODO: deal with non-ascii characters\n guard self.find_by(x => x.is_ascii_uppercase()) is Some(idx) else {\n return self\n }\n let buf = StringBuilder(size_hint=self.length())\n let head = self.view(end_offset=idx)\n buf.write_substring(head.data(), head.start_offset(), head.length())\n for c in self.view(start_offset=idx) {\n if c.is_ascii_uppercase() {\n // 'A' is 65 in ASCII, 'a' is 97, the difference is 32\n buf.write_char((c.to_int() + 32).unsafe_to_char())\n } else {\n buf.write_char(c)\n }\n }\n buf.to_string()\n}\n\n///|\ntest \"to_lower\" {\n assert_eq(\"Hello\".to_lower(), \"hello\")\n assert_eq(\"HELLO\".to_lower(), \"hello\")\n assert_eq(\"Hello, World!\".to_lower(), \"hello, world!\")\n}\n\n///|\ntest \"View::to_lower\" {\n assert_eq(\"Hello\"[:].to_lower(), \"hello\")\n assert_eq(\"HELLO\"[:].to_lower(), \"hello\")\n assert_eq(\"Hello, World!\"[:].to_lower(), \"hello, world!\")\n}\n\n///|\n/// Converts this string to uppercase.\npub fn StringView::to_upper(self : StringView) -> StringView {\n // TODO: deal with non-ascii characters\n guard self.find_by(c => c.is_ascii_lowercase()) is Some(idx) else {\n return self\n }\n let buf = StringBuilder(size_hint=self.length())\n let head = self.view(end_offset=idx)\n buf.write_substring(head.data(), head.start_offset(), head.length())\n for c in self.view(start_offset=idx) {\n if c.is_ascii_lowercase() {\n buf.write_char((c.to_int() - 32).unsafe_to_char())\n } else {\n buf.write_char(c)\n }\n }\n buf.to_string()\n}\n\n///|\n/// Converts this string to uppercase.\npub fn String::to_upper(self : String) -> String {\n // TODO: deal with non-ascii characters\n guard self.find_by(c => c.is_ascii_lowercase()) is Some(idx) else {\n return self\n }\n let buf = StringBuilder(size_hint=self.length())\n let head = self.view(end_offset=idx)\n buf.write_substring(head.data(), head.start_offset(), head.length())\n for c in self.view(start_offset=idx) {\n if c.is_ascii_lowercase() {\n buf.write_char((c.to_int() - 32).unsafe_to_char())\n } else {\n buf.write_char(c)\n }\n }\n buf.to_string()\n}\n\n///|\ntest \"to_upper\" {\n assert_eq(\"hello\".to_upper(), \"HELLO\")\n assert_eq(\"HELLO\".to_upper(), \"HELLO\")\n assert_eq(\"Hello, World!\".to_upper(), \"HELLO, WORLD!\")\n}\n\n///|\ntest \"View::to_upper\" {\n assert_eq(\"hello\"[:].to_upper(), \"HELLO\")\n assert_eq(\"HELLO\"[:].to_upper(), \"HELLO\")\n assert_eq(\"Hello, World!\"[:].to_upper(), \"HELLO, WORLD!\")\n}\n\n///|\n/// Folds the characters of the string into a single value.\n#locals(f)\npub fn[A] StringView::fold(\n self : StringView,\n init~ : A,\n f : (A, Char) -> A raise?,\n) -> A raise? {\n for c in self; rv = (init : A) {\n continue f(rv, c)\n } nobreak {\n rv\n }\n}\n\n///|\n/// Folds the characters of the string into a single value.\npub fn[A] String::fold(\n self : String,\n init~ : A,\n f : (A, Char) -> A raise?,\n) -> A raise? {\n self[:].fold(init~, f)\n}\n\n///|\ntest \"fold\" {\n assert_true(\n \"hello\".fold(init=[], (acc, c) => {\n acc.push(c)\n acc\n }) ==\n ['h', 'e', 'l', 'l', 'o'],\n )\n assert_eq(\n \"hello\".fold(init=0, (acc, c) => acc + c.to_int()),\n 104 + 101 + 108 + 108 + 111,\n )\n}\n\n///|\ntest \"fold with raise\" {\n let result = try? \"hello\".fold(init=0, (acc, c) => {\n if c == 'l' {\n raise Failure(\"found l\")\n }\n acc + 1\n })\n assert_true(result is Err(Failure(\"found l\")))\n}\n\n///|\n/// Function `rev_fold`.\n#locals(f)\npub fn[A] StringView::rev_fold(\n self : StringView,\n init~ : A,\n f : (A, Char) -> A raise?,\n) -> A raise? {\n for c in self.rev_iter(); rv = (init : A) {\n continue f(rv, c)\n } nobreak {\n rv\n }\n}\n\n///|\n/// Function `rev_fold`.\npub fn[A] String::rev_fold(\n self : String,\n init~ : A,\n f : (A, Char) -> A raise?,\n) -> A raise? {\n self[:].rev_fold(init~, f)\n}\n\n///|\ntest \"rev_fold\" {\n assert_true(\n \"hello\".rev_fold(init=[], (acc, c) => {\n acc.push(c)\n acc\n }) ==\n ['o', 'l', 'l', 'e', 'h'],\n )\n assert_eq(\n \"hello\".rev_fold(init=0, (acc, c) => acc + c.to_int()),\n 111 + 108 + 108 + 101 + 104,\n )\n}\n\n///|\ntest \"rev_fold with raise\" {\n let result = try? \"hello\".rev_fold(init=0, (acc, c) => {\n if c == 'l' {\n raise Failure(\"found l\")\n }\n acc + 1\n })\n assert_true(result is Err(Failure(\"found l\")))\n}\n\n///|\n/// Returns the UTF-16 code unit at the given index. Returns `None` if the index\n/// is out of bounds.\n#deprecated(\"The return type is about to change to `UInt16?` in a future release. Please check boundaries manually and use `String::code_unit_at` instead.\", skip_current_package=true)\npub fn String::get(self : String, idx : Int) -> Int? {\n guard idx >= 0 && idx < self.length() else { return None }\n Some(self.unsafe_get(idx).to_int())\n}\n\n///|\n/// Returns the UTF-16 code unit at the given index. Returns `None` if the index\n/// is out of bounds.\n#deprecated(\"The return type is about to change to `UInt16?` in a future release. Please check boundaries manually and use `StringView::code_unit_at` instead.\", skip_current_package=true)\npub fn StringView::get(self : StringView, idx : Int) -> Int? {\n guard idx >= 0 && idx < self.length() else { return None }\n Some(self.unsafe_get(idx).to_int())\n}\n\n///|\ntest \"String::get supports emoji (surrogate pair)\" {\n let s = \"hello\"\n assert_true(s.get(0) == Some(104))\n assert_true(s.get(4) == Some(111))\n assert_true(s.get(5) == None)\n assert_true(s.get(-1) == None)\n let s = \"a🤣b\"\n assert_true(s.get(0) == Some(97))\n assert_true(s.get(1) == Some(55358))\n assert_true(s.get(2) == Some(56611))\n assert_true(s.get(3) == Some(98))\n assert_true(s.get(4) == None)\n}\n\n///|\ntest \"View::get basic cases\" {\n let v = \"hello\"[1:-1]\n assert_true(v.get(0) == Some(101))\n assert_true(v.get(2) == Some(108))\n assert_true(v.get(3) == None)\n assert_true(v.get(-1) == None)\n let v = \"ab🤣cd\"[1:-1]\n assert_true(v.get(0) == Some(98))\n assert_true(v.get(1) == Some(55358))\n assert_true(v.get(2) == Some(56611))\n}\n\n///|\n/// Returns the character at the given index. Returns `None` if the index is out\n/// of bounds or the index splits a surrogate pair.\npub fn String::get_char(self : String, idx : Int) -> Char? {\n guard idx >= 0 && idx < self.length() else { return None }\n let c = self.unsafe_get(idx)\n if c.is_leading_surrogate() {\n guard idx + 1 < self.length() else { return None }\n let next = self.unsafe_get(idx + 1)\n if next.is_trailing_surrogate() {\n Some(code_point_of_surrogate_pair(c.to_int(), next.to_int()))\n } else {\n None\n }\n } else if c.is_trailing_surrogate() {\n None\n } else {\n Some(c.unsafe_to_char())\n }\n}\n\n///|\n/// Returns the character at the given index. Returns `None` if the index is out\n/// of bounds or the index splits a surrogate pair.\npub fn StringView::get_char(self : StringView, idx : Int) -> Char? {\n guard idx >= 0 && idx < self.length() else { return None }\n let c = self.unsafe_get(idx)\n if c.is_leading_surrogate() {\n guard idx + 1 < self.length() else { return None }\n let next = self.unsafe_get(idx + 1)\n if next.is_trailing_surrogate() {\n Some(code_point_of_surrogate_pair(c.to_int(), next.to_int()))\n } else {\n None\n }\n } else if c.is_trailing_surrogate() {\n None\n } else {\n Some(c.unsafe_to_char())\n }\n}\n\n///|\ntest \"String::get_char basic cases\" {\n // Basic ASCII characters\n let s = \"hello\"\n assert_true(s.get_char(0) == Some('h'))\n assert_true(s.get_char(1) == Some('e'))\n assert_true(s.get_char(4) == Some('o'))\n assert_true(s.get_char(5) == None)\n assert_true(s.get_char(-1) == None)\n\n // Contains emoji (surrogate pair)\n let s = \"a🤣b\"\n assert_true(s.get_char(0) == Some('a'))\n assert_true(s.get_char(1) == Some('🤣'))\n assert_true(s.get_char(2) == None) // Second half of surrogate pair is not a valid char\n assert_true(s.get_char(3) == Some('b'))\n assert_true(s.get_char(4) == None)\n}\n\n///|\ntest \"View::get_char basic cases\" {\n let s = \"a🤣b\"\n let v = s[0:-1]\n assert_true(v.get_char(0) == Some('a'))\n assert_true(v.get_char(1) == Some('🤣'))\n assert_true(v.get_char(2) == None)\n assert_true(v.get_char(3) == None)\n assert_true(v.get_char(4) == None)\n\n // Test substring view\n let v2 = s[1:3] // Only contains the emoji surrogate pair\n assert_true(v2.get_char(0) == Some('🤣'))\n assert_true(v2.get_char(1) == None)\n assert_true(v2.get_char(2) == None)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n//#region\n// These types are of workaround for the restriction that MoonBit do not support\n// generic type parameters of extern ffi\n\n///|\n#external\npriv type JSValue\n\n///|\nfn[T] JSValue::ofAny(array : T) -> JSValue = \"%identity\"\n\n///|\nfn[T] JSValue::toAny(self : JSValue) -> T = \"%identity\"\n\n///|\n#external\npriv type JSArray\n\n///|\nfn[T] JSArray::ofAnyArray(array : Array[T]) -> JSArray = \"%identity\"\n\n///|\nfn[T] JSArray::toAnyArray(self : JSArray) -> Array[T] = \"%identity\"\n\n///|\nfn[T] JSArray::ofAnyFixedArray(array : FixedArray[T]) -> JSArray = \"%identity\"\n\n///|\nfn[T] JSArray::toAnyFixedArray(self : JSArray) -> FixedArray[T] = \"%identity\"\n\n///|\nextern \"js\" fn JSArray::set_length(self : JSArray, new_len : Int) -> Unit =\n #| (arr, len) => { arr.length = len; }\n\n///|\nextern \"js\" fn JSArray::push(self : JSArray, value : JSValue) -> Unit =\n #| (arr, val) => { arr.push(val); }\n\n///|\nextern \"js\" fn JSArray::pop(self : JSArray) -> JSValue =\n #| (arr) => arr.pop()\n\n///|\nextern \"js\" fn JSArray::splice(\n self : JSArray,\n index : Int,\n count : Int,\n) -> JSArray =\n #| (arr, idx, cnt) => arr.splice(idx, cnt)\n\n///|\nextern \"js\" fn JSArray::splice1(\n self : JSArray,\n index : Int,\n count : Int,\n value : JSValue,\n) -> JSArray =\n #| (arr, idx, cnt, val) => arr.splice(idx, cnt, val)\n\n///|\nextern \"js\" fn JSArray::fill(\n self : JSArray,\n value : JSValue,\n start : Int,\n end : Int,\n) -> Unit =\n #| (arr, val, start, end) => arr.fill(val, start, end)\n\n///|\nextern \"js\" fn JSArray::copy(self : JSArray) -> JSArray =\n #|(arr) => arr.slice(0)\n\n//#endregion\n\n///|\n/// An `Array` is a collection of values that supports random access and can\n/// grow in size.\n#external\ntype Array[T]\n\n///|\nfn[T] Array::make_uninit(len : Int) -> Array[T] = \"%fixedarray.make_uninit\"\n\n///|\n/// Creates a new array.\npub fn[T] Array::new(capacity? : Int = 0) -> Array[T] {\n ignore(capacity)\n []\n}\n\n///|\n/// Returns the number of elements in the array.\npub fn[T] Array::length(self : Array[T]) -> Int = \"%fixedarray.length\"\n\n///|\nfn[T] Array::unsafe_truncate_to_length(self : Array[T], new_len : Int) -> Unit {\n JSArray::ofAnyArray(self).set_length(new_len)\n}\n\n///|\nfn[T] Array::buffer(self : Array[T]) -> UninitializedArray[T] = \"%identity\"\n\n///|\ntest \"array_unsafe_blit_fixed\" {\n let src = FixedArray::make(5, 0)\n let dst = UninitializedArray::make(5)\n for i in 0..<5 {\n src[i] = i + 1\n }\n UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5)\n for i in 0..<5 {\n assert_eq(dst[i], src[i])\n }\n}\n\n///|\ntest \"UninitializedArray::unsafe_blit_fixed\" {\n let src = FixedArray::make(5, 0)\n let dst = UninitializedArray::make(5)\n for i in 0..<5 {\n src[i] = i + 1\n }\n UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5)\n for i in 0..<5 {\n assert_eq(dst[i], src[i])\n }\n}\n\n///|\n/// Reserves capacity to ensure that it can hold at least the number of elements\n/// specified by the `capacity` argument.\n///\n/// **NOTE**: This method does nothing on js platform.\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let v = [1]\n/// v.reserve_capacity(10)\n/// assert_eq(v.capacity(), 1)\n/// }\n/// ```\npub fn[T] Array::reserve_capacity(self : Array[T], capacity : Int) -> Unit {\n ignore(self)\n ignore(capacity)\n}\n\n///|\n/// Shrinks the capacity of the array as much as possible.\n///\n/// **NOTE**: This method does nothing on js platform.\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let v = Array::new(capacity=10)\n/// v.push(1)\n/// v.push(2)\n/// v.push(3)\n/// assert_eq(v.capacity(), 3)\n/// v.shrink_to_fit()\n/// assert_eq(v.capacity(), 3)\n/// }\n/// ```\npub fn[T] Array::shrink_to_fit(self : Array[T]) -> Unit {\n ignore(self)\n}\n\n///|\n/// Adds an element to the end of the array.\n///\n/// If the array is at capacity, it will be reallocated.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = []\n/// v.push(3)\n/// }\n/// ```\npub fn[T] Array::push(self : Array[T], value : T) -> Unit {\n JSArray::ofAnyArray(self).push(JSValue::ofAny(value))\n}\n\n///|\n/// Removes the last element from an array and returns it, or `None` if it is empty.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [1, 2, 3]\n/// let vv = v.pop()\n/// assert_eq(vv, Some(3))\n/// assert_eq(v, [1, 2])\n/// }\n/// ```\npub fn[T] Array::pop(self : Array[T]) -> T? {\n if self.is_empty() {\n None\n } else {\n let v = self.unsafe_pop()\n Some(v)\n }\n}\n\n///|\n/// Removes the last element from an array and returns it.\n///\n/// **NOTE** This method will not cause a panic, but it may result in undefined\n/// behavior on the JavaScript platform. Use with caution.\n///\n#internal(unsafe, \"Panic if the array is empty.\")\n#doc(hidden)\n#alias(pop_exn, deprecated)\npub fn[T] Array::unsafe_pop(self : Array[T]) -> T {\n JSArray::ofAnyArray(self).pop().toAny()\n}\n\n///|\n/// Remove an element from the array at a given index.\n///\n/// Removes and returns the element at position index within the array, shifting all elements after it to the left.\n/// \n/// This function will panic if the index is out of bounds.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let vv = v.remove(1)\n/// assert_eq(vv, 4)\n/// assert_eq(v, [3, 5])\n/// }\n/// ```\npub fn[T] Array::remove(self : Array[T], index : Int) -> T {\n guard index >= 0 && index < self.length() else {\n abort(\n \"index out of bounds: the len is from 0 to \\{self.length()} but the index is \\{index}\",\n )\n }\n let value = self.buffer()[index]\n let _ = JSArray::ofAnyArray(self).splice(index, 1)\n value\n}\n\n///|\n/// Removes the specified range from the array and returns it.\n///\n/// This functions returns an array range from `begin` to `end` `[begin, end)`\n/// \n/// This function will panic if the index is out of bounds.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let vv = v.drain(1, 2) // vv = [4], v = [3, 5]\n/// assert_eq(vv, [4])\n/// assert_eq(v, [3, 5])\n/// }\n/// ```\npub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] {\n guard begin >= 0 && end <= self.length() && begin <= end else {\n abort(\n \"index out of bounds: the len is \\{self.length()} but the index is (\\{begin}, \\{end})\",\n )\n }\n JSArray::ofAnyArray(self).splice(begin, end - begin).toAnyArray()\n}\n\n///|\n/// Inserts an element at a given index within the array.\n/// \n/// This function will panic if the index is out of bounds.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// [3, 4, 5].insert(1, 6)\n/// }\n/// ```\npub fn[T] Array::insert(self : Array[T], index : Int, value : T) -> Unit {\n guard index >= 0 && index <= self.length() else {\n abort(\n \"index out of bounds: the len is from 0 to \\{self.length()} but the index is \\{index}\",\n )\n }\n let _ = JSArray::ofAnyArray(self).splice1(index, 0, JSValue::ofAny(value))\n}\n\n///|\n/// Resize the array in-place so that `len` is equal to `new_len`.\n///\n/// If `new_len` is greater than `len`, the array will be extended by the\n/// difference, and the values in the new slots are left uninitilized.\n/// If `new_len` is less than `len`, it will panic\n///\nfn[T] Array::unsafe_grow_to_length(self : Array[T], new_len : Int) -> Unit {\n guard new_len >= self.length()\n JSArray::ofAnyArray(self).set_length(new_len)\n}\n\n///|\n/// Fills an Array with a specified value.\n/// \n/// This method fills all or part of an Array with the given value.\n/// \n/// # Parameters\n/// - `value`: The value to fill the array with\n/// - `start`: The starting index (inclusive, default: 0)\n/// - `end`: The ending index (exclusive, optional)\n/// \n/// If `end` is not provided, fills from `start` to the end of the array.\n/// If `start` equals `end`, no elements are modified.\n/// \n/// # Panics\n/// - Panics if `start` is negative or greater than or equal to the array length\n/// - Panics if `end` is provided and is less than `start` or greater than array length\n/// - Does nothing if the array is empty\n/// \n/// # Example\n/// ```mbt check\n/// test {\n/// // Fill entire array\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.fill(0)\n/// @debug.debug_inspect(arr, content=\"[0, 0, 0, 0, 0]\")\n///\n/// // Fill from index 1 to 3 (exclusive)\n/// let arr2 = [1, 2, 3, 4, 5]\n/// arr2.fill(99, start=1, end=3)\n/// @debug.debug_inspect(arr2, content=\"[1, 99, 99, 4, 5]\")\n///\n/// // Fill from index 2 to end\n/// let arr3 = [\"a\", \"b\", \"c\", \"d\"]\n/// arr3.fill(\"x\", start=2)\n/// @debug.debug_inspect(\n/// arr3,\n/// content=(\n/// #|[\"a\", \"b\", \"x\", \"x\"]\n/// ),\n/// )\n/// }\n/// ```\npub fn[A] Array::fill(\n self : Array[A],\n value : A,\n start? : Int = 0,\n end? : Int,\n) -> Unit {\n let array_length = self.length()\n guard array_length > 0 else { return }\n guard start >= 0 && start < array_length\n let end = match end {\n None => array_length\n Some(e) => {\n guard e >= 0 && e <= array_length\n e\n }\n }\n JSArray::ofAnyArray(self).fill(JSValue::ofAny(value), start, end)\n}\n\n///|\n/// Creates and returns a new array with a copy of all elements from the input\n/// array.\n///\n/// Parameters:\n///\n/// * `array` : The array to be copied.\n///\n/// Returns a new array containing all elements from the original array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let original = [1, 2, 3]\n/// let copied = original.copy()\n/// @debug.debug_inspect(copied, content=\"[1, 2, 3]\")\n/// inspect(physical_equal(original, copied), content=\"false\")\n/// }\n/// ```\n#alias(clone, deprecated)\npub fn[T] Array::copy(self : Array[T]) -> Array[T] {\n JSArray::ofAnyArray(self).copy().toAnyArray()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn Char::to_hex(char : Char) -> String {\n let code = char.to_int()\n match code {\n 0..=0xFF => code.to_byte().to_hex()\n _..=0xFFFF => (code >> 8).to_byte().to_hex() + code.to_byte().to_hex()\n _ =>\n (code >> 16).to_byte().to_hex() +\n (code >> 8).to_byte().to_hex() +\n code.to_byte().to_hex()\n }\n}\n\n///|\ntest \"Char::to_hex\" {\n // Test various characters\n inspect(Char::to_hex('A'), content=\"41\")\n inspect(Char::to_hex('a'), content=\"61\")\n inspect(Char::to_hex('0'), content=\"30\")\n inspect(Char::to_hex('\\n'), content=\"0a\")\n inspect(Char::to_hex('\\u{0}'), content=\"00\")\n inspect(Char::to_hex('\\u{FF}'), content=\"ff\")\n inspect(Char::to_hex('\\u{100}'), content=\"0100\")\n inspect(Char::to_hex('\\u{1000}'), content=\"1000\")\n inspect(Char::to_hex('😀'), content=\"01f600\")\n}\n\n///|\npub impl Hash for Char with hash_combine(self, hasher) -> Unit {\n hasher.combine_char(self)\n}\n\n///|\n/// Checks if the value is within the ASCII range.\npub fn Char::is_ascii(self : Self) -> Bool {\n self is ('\\u{00}'..='\\u{7F}')\n}\n\n///|\n/// Checks if the value is an ASCII alphabetic character:\n/// - U+0041 'A' ..= U+005A 'Z'\n/// - U+0061 'a' ..= U+007A 'z'\npub fn Char::is_ascii_alphabetic(self : Self) -> Bool {\n self is ('A'..='Z' | 'a'..='z')\n}\n\n///|\n/// Checks if the value is an ASCII control character:\n/// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.\n/// Note that most ASCII whitespace characters are control characters, but SPACE is not.\npub fn Char::is_ascii_control(self : Self) -> Bool {\n self is ('\\u{00}'..='\\u{1F}' | '\\u{7F}')\n}\n\n///|\n/// Checks if the value is an ASCII decimal digit:\n/// U+0030 '0' ..= U+0039 '9'\npub fn Char::is_ascii_digit(self : Self) -> Bool {\n self is ('0'..='9')\n}\n\n///|\n/// Checks if the value is an ASCII graphic character:\n/// U+0021 '!' ..= U+007E '~'\npub fn Char::is_ascii_graphic(self : Self) -> Bool {\n self is ('\\u{21}'..='\\u{7E}')\n}\n\n///|\n/// Checks if the value is an ASCII hexadecimal digit:\n/// - U+0030 '0' ..= U+0039 '9'\n/// - U+0041 'A' ..= U+0046 'F'\n/// - U+0061 'a' ..= U+0066 'f'\npub fn Char::is_ascii_hexdigit(self : Self) -> Bool {\n self is ('0'..='9' | 'A'..='F' | 'a'..='f')\n}\n\n///|\n/// Checks if the value is an ASCII lowercase character:\n/// U+0061 'a' ..= U+007A 'z'.\npub fn Char::is_ascii_lowercase(self : Self) -> Bool {\n self is ('a'..='z')\n}\n\n///|\n/// Checks if the value is an ASCII octal digit:\n/// U+0030 '0' ..= U+0037 '7'\npub fn Char::is_ascii_octdigit(self : Self) -> Bool {\n self is ('0'..='7')\n}\n\n///|\n/// Checks if the value is an ASCII punctuation character:\n/// - U+0021 ..= U+002F ! \" # $ % & ' ( ) * + , - . /\n/// - U+003A ..= U+0040 : ; < = > ? @\n/// - U+005B ..= U+0060 [ \\ ] ^ _ `\n/// - U+007B ..= U+007E { | } ~\npub fn Char::is_ascii_punctuation(self : Self) -> Bool {\n self\n is ('\\u{21}'..='\\u{2F}'\n | '\\u{3A}'..='\\u{40}'\n | '\\u{5B}'..='\\u{60}'\n | '\\u{7B}'..='\\u{7E}')\n}\n\n///|\n/// Checks if the value is an ASCII uppercase character:\n/// U+0041 'A' ..= U+005A 'Z'\npub fn Char::is_ascii_uppercase(self : Self) -> Bool {\n self is ('A'..='Z')\n}\n\n///|\n/// Checks if the value is an ASCII whitespace character:\n/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED, U+000B VERTICAL TAB, U+000C FORM FEED, or U+000D CARRIAGE RETURN.\npub fn Char::is_ascii_whitespace(self : Self) -> Bool {\n self is ('\\u{20}' | '\\u{09}' | '\\u{0A}' | '\\u{0B}' | '\\u{0C}' | '\\u{0D}')\n}\n\n///|\n/// Returns true if this char has the general category for control codes.\npub fn Char::is_control(self : Self) -> Bool {\n self is ('\\u0000'..='\\u001F' | '\\u007F'..='\\u009F')\n}\n\n///|\n/// Checks if a char is a digit in the given radix (range from 2 to 36).\n/// \n/// panic if the radix is invalid.\npub fn Char::is_digit(self : Self, radix : UInt) -> Bool {\n let v = self.to_uint()\n match radix {\n 2..=10 => v >= 48 && v <= radix + 47\n 11..=36 =>\n (v >= 48 && v <= 57) ||\n (v >= 65 && v <= radix + 54) ||\n (v >= 97 && v <= radix + 86)\n _ => panic()\n }\n}\n\n///|\n/// Returns true if this char has the White_Space property.\npub fn Char::is_whitespace(self : Self) -> Bool {\n self\n is ('\\u0009'..='\\u000D'\n | '\\u0020'\n | '\\u0085'\n | '\\u00A0'\n | '\\u1680'\n | '\\u2000'..='\\u200A'\n | '\\u2028'\n | '\\u2029'\n | '\\u202F'\n | '\\u205F'\n | '\\u3000')\n}\n\n///|\n/// Returns true if this char has one of the general categories for numbers.\npub fn Char::is_numeric(self : Self) -> Bool {\n self\n is ('\\u0030'..='\\u0039'\n | '\\u00B2'\n | '\\u00B3'\n | '\\u00B9'\n | '\\u00BC'\n | '\\u00BD'\n | '\\u00BE'\n | '\\u0660'..='\\u0669'\n | '\\u06F0'..='\\u06F9'\n | '\\u07C0'..='\\u07F9'\n | '\\u0966'..='\\u096F'\n | '\\u09E6'..='\\u09EF'\n | '\\u09F4'..='\\u09F9'\n | '\\u0A66'..='\\u0A6F'\n | '\\u0AE6'..='\\u0AEF'\n | '\\u0B66'..='\\u0B6F'\n | '\\u0B72'..='\\u0B77'\n | '\\u0BE6'..='\\u0BEF'\n | '\\u0BF0'..='\\u0BF2'\n | '\\u0C66'..='\\u0C6F'\n | '\\u0C78'..='\\u0C7E'\n | '\\u0CE6'..='\\u0CEF'\n | '\\u0D58'..='\\u0D5E'\n | '\\u0D66'..='\\u0D6F'\n | '\\u0D70'..='\\u0D78'\n | '\\u0DE6'..='\\u0DEF'\n | '\\u0E50'..='\\u0E59'\n | '\\u0ED0'..='\\u0ED9'\n | '\\u0F20'..='\\u0F33'\n | '\\u1040'..='\\u1049'\n | '\\u1090'..='\\u1099'\n | '\\u1369'..='\\u137C'\n | '\\u16EE'..='\\u16F0'\n | '\\u17E0'..='\\u17E9'\n | '\\u17F0'..='\\u17F9'\n | '\\u1810'..='\\u1819'\n | '\\u1946'..='\\u194F'\n | '\\u19D0'..='\\u19DA'\n | '\\u1A80'..='\\u1A89'\n | '\\u1A90'..='\\u1A99'\n | '\\u1B50'..='\\u1B59'\n | '\\u1BB0'..='\\u1BB9'\n | '\\u1C40'..='\\u1C49'\n | '\\u1C50'..='\\u1C59'\n | '\\u2070'\n | '\\u2074'..='\\u2079'\n | '\\u2080'..='\\u2089'\n | '\\u2150'..='\\u2189'\n | '\\u2460'..='\\u249B'\n | '\\u24EA'..='\\u24FF'\n | '\\u2776'..='\\u2793'\n | '\\u2CFD'\n | '\\u3007'\n | '\\u3021'..='\\u3029'\n | '\\u3038'..='\\u303A'\n | '\\u3192'..='\\u3195'\n | '\\u3220'..='\\u3229'\n | '\\u3248'..='\\u324F'\n | '\\u3251'..='\\u325F'\n | '\\u3280'..='\\u3289'\n | '\\u32B1'..='\\u32BF'\n | '\\uA620'..='\\uA629'\n | '\\uA6E6'..='\\uA6EF'\n | '\\uA830'..='\\uA835'\n | '\\uA8D0'..='\\uA8D9'\n | '\\uA900'..='\\uA909'\n | '\\uA9D0'..='\\uA9D9'\n | '\\uA9F0'..='\\uA9F9'\n | '\\uAA50'..='\\uAA59'\n | '\\uABF0'..='\\uABF9'\n | '\\uFF10'..='\\uFF19'\n | '\\u{10107}'..='\\u{10133}'\n | '\\u{10140}'..='\\u{10178}'\n | '\\u{1018A}'..='\\u{1018B}'\n | '\\u{102E1}'..='\\u{102FB}'\n | '\\u{10320}'..='\\u{10323}'\n | '\\u{10341}'\n | '\\u{1034A}'\n | '\\u{103D1}'..='\\u{103D5}'\n | '\\u{104A0}'..='\\u{104A9}'\n | '\\u{10858}'..='\\u{1085F}'\n | '\\u{10879}'..='\\u{1087F}'\n | '\\u{108A7}'..='\\u{108AF}'\n | '\\u{108FB}'..='\\u{108FF}'\n | '\\u{10916}'..='\\u{1091B}'\n | '\\u{109BC}'..='\\u{109BD}'\n | '\\u{109C0}'..='\\u{109CF}'\n | '\\u{10A40}'..='\\u{10A48}'\n | '\\u{10A7D}'..='\\u{10A7E}'\n | '\\u{10A9D}'..='\\u{10A9F}'\n | '\\u{10AEB}'..='\\u{10AEF}'\n | '\\u{10B58}'..='\\u{10B5F}'\n | '\\u{10B78}'..='\\u{10B7F}'\n | '\\u{10BA9}'..='\\u{10BAF}'\n | '\\u{10CFA}'..='\\u{10CFF}'\n | '\\u{10D30}'..='\\u{10D39}'\n | '\\u{10D40}'..='\\u{10D49}'\n | '\\u{10E60}'..='\\u{10E7E}'\n | '\\u{10F1D}'..='\\u{10F26}'\n | '\\u{10F51}'..='\\u{10F54}'\n | '\\u{10FC5}'..='\\u{10FCB}'\n | '\\u{11052}'..='\\u{1106F}'\n | '\\u{110F0}'..='\\u{110F9}'\n | '\\u{11136}'..='\\u{1113F}'\n | '\\u{111D0}'..='\\u{111D9}'\n | '\\u{111E1}'..='\\u{111F4}'\n | '\\u{112F0}'..='\\u{112F9}'\n | '\\u{11450}'..='\\u{11459}'\n | '\\u{114D0}'..='\\u{114D9}'\n | '\\u{11650}'..='\\u{11659}'\n | '\\u{116C0}'..='\\u{116C9}'\n | '\\u{116D0}'..='\\u{116E3}'\n | '\\u{11730}'..='\\u{1173B}'\n | '\\u{118E0}'..='\\u{118F2}'\n | '\\u{11950}'..='\\u{11959}'\n | '\\u{11BF0}'..='\\u{11BF9}'\n | '\\u{11C50}'..='\\u{11C6C}'\n | '\\u{11D50}'..='\\u{11D59}'\n | '\\u{11DA0}'..='\\u{11DA9}'\n | '\\u{11F50}'..='\\u{11F59}'\n | '\\u{11FC0}'..='\\u{11FD4}'\n | '\\u{12400}'..='\\u{1246E}'\n | '\\u{16130}'..='\\u{16139}'\n | '\\u{16A60}'..='\\u{16A69}'\n | '\\u{16AC0}'..='\\u{16AC9}'\n | '\\u{16B50}'..='\\u{16B59}'\n | '\\u{16B5B}'..='\\u{16B61}'\n | '\\u{16D70}'..='\\u{16D79}'\n | '\\u{16D80}'..='\\u{16E96}'\n | '\\u{1CCF0}'..='\\u{1CCF9}'\n | '\\u{1D2C0}'..='\\u{1D2F3}'\n | '\\u{1D360}'..='\\u{1D378}'\n | '\\u{1D7CE}'..='\\u{1D7FF}'\n | '\\u{1E140}'..='\\u{1E149}'\n | '\\u{1E2F0}'..='\\u{1E2F9}'\n | '\\u{1E4F0}'..='\\u{1E4F9}'\n | '\\u{1E5F1}'..='\\u{1E5FA}'\n | '\\u{1E8C7}'..='\\u{1E8CF}'\n | '\\u{1E950}'..='\\u{1E959}'\n | '\\u{1EC71}'..='\\u{1ECB4}'\n | '\\u{1ED01}'..='\\u{1ED3D}'\n | '\\u{1F100}'..='\\u{1F10C}'\n | '\\u{1FBF0}'..='\\u{1FBF9}')\n}\n\n///|\n/// Returns true if this character is printable (visible when displayed).\n/// Aligns with Unicode standard categories for printable characters.\n/// Characters are considered printable if they are:\n/// - Letters (L*)\n/// - Marks (M*)\n/// - Numbers (N*)\n/// - Punctuation (P*)\n/// - Symbols (S*)\n/// - Spaces (Zs), with some exceptions\n/// Characters are considered non-printable if they are:\n/// - Control characters (Cc)\n/// - Format characters (Cf)\n/// - Line/paragraph separators (Zl, Zp)\n/// - Private use (Co)\n/// - Unassigned (Cn)\n/// - Surrogates (Cs)\npub fn Char::is_printable(self : Self) -> Bool {\n // Check for control characters (Cc)\n if self.is_control() {\n return false\n }\n let self = self.to_int()\n\n // Private use areas (Co)\n if self is (0xE000..=0xF8FF | 0xF0000..=0xFFFFD | 0x100000..=0x10FFFD) {\n return false\n }\n\n // Format characters (Cf)\n if self\n is ('\\u{00AD}'\n | '\\u{0600}'..='\\u{0605}'\n | '\\u{061C}'\n | '\\u{06DD}'\n | '\\u{070F}'\n | '\\u{0890}'..='\\u{0891}'\n | '\\u{08E2}'\n | '\\u{180E}'\n | '\\u{200B}'..='\\u{200F}'\n | '\\u{202A}'..='\\u{202E}'\n | '\\u{2060}'..='\\u{2064}'\n | '\\u{2066}'..='\\u{206F}'\n | '\\u{feff}'\n | '\\u{FFF9}'..='\\u{FFFB}'\n | '\\u{110BD}'\n | '\\u{110CD}'\n | '\\u{13430}'..='\\u{1343F}'\n | '\\u{1BCA0}'..='\\u{1BCA3}'\n | '\\u{1D173}'..='\\u{1D17A}'\n | '\\u{E0001}'\n | '\\u{E0020}'..='\\u{E007F}') {\n return false\n }\n // Surrogate (Cs)\n if self.is_surrogate() {\n return false\n }\n\n // Line and paragraph separators (Zl, Zp)\n if self == '\\u{2028}' || self == '\\u{2029}' {\n return false\n }\n\n // Noncharacter\n if self\n is (0xFDD0..=0xFDEF\n | 0xFFFE..=0xFFFF\n | 0x1FFFE..=0x1FFFF\n | 0x2FFFE..=0x2FFFF\n | 0x3FFFE..=0x3FFFF\n | 0x4FFFE..=0x4FFFF\n | 0x5FFFE..=0x5FFFF\n | 0x6FFFE..=0x6FFFF\n | 0x7FFFE..=0x7FFFF\n | 0x8FFFE..=0x8FFFF\n | 0x9FFFE..=0x9FFFF\n | 0xAFFFE..=0xAFFFF\n | 0xBFFFE..=0xBFFFF\n | 0xCFFFE..=0xCFFFF\n | 0xDFFFE..=0xDFFFF\n | 0xEFFFE..=0xEFFFF\n | 0xFFFFE..=0xFFFFF\n | 0x10FFFE..=0x10FFFF) {\n return false\n }\n true\n}\n\n///|\n/// Makes a copy of the value in its ASCII lower case equivalent.\n/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',\n/// but non-ASCII letters are unchanged.\npub fn Char::to_ascii_lowercase(self : Self) -> Char {\n if self.is_ascii_uppercase() {\n return (self.to_int() + 32).unsafe_to_char()\n }\n self\n}\n\n///|\n/// Makes a copy of the value in its ASCII upper case equivalent.\n/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',\n/// but non-ASCII letters are unchanged.\npub fn Char::to_ascii_uppercase(self : Self) -> Char {\n if self.is_ascii_lowercase() {\n return (self.to_int() - 32).unsafe_to_char()\n }\n self\n}\n\n///|\n/// Returns the original character as a string without escaping.\n/// `Show::output` for `Char` also writes the raw character through this\n/// `Show::to_string` implementation.\n/// Use `Char::escape` when a quoted and escaped representation is needed.\npub impl Show for Char with to_string(self : Char) -> String {\n char_to_string(self)\n}\n\n///|\n/// TODO: support attributes for impl\n#intrinsic(\"%char.to_string\")\nfn char_to_string(char : Char) -> String {\n [char]\n}\n\n///|\n/// Returns the escaped representation of a character.\n///\n/// When `quote` is true (default), the result is wrapped in single quotes\n/// like a MoonBit character literal.\n///\n/// Escape rules:\n/// - Single quote and backslash are backslash-escaped: `\\'`, `\\\\`\n/// - Common control characters use named escapes: `\\n`, `\\r`, `\\b`, `\\t`\n/// - ASCII printable characters (U+0020 to U+007E) are displayed as-is\n/// - Printable Unicode characters outside ASCII are displayed as-is\n/// - Non-printable characters use `\\u{hex}` format\n///\n/// ```mbt check\n/// test {\n/// inspect('a'.escape(), content=\"'a'\")\n/// inspect('a'.escape(quote=false), content=\"a\")\n/// inspect('\\n'.escape(), content=\"'\\\\n'\")\n/// inspect('\\n'.escape(quote=false), content=\"\\\\n\")\n/// }\n/// ```\npub fn Char::escape(self : Char, quote? : Bool = true) -> String {\n let buf = StringBuilder()\n self.escape_to(buf, quote~)\n buf.to_string()\n}\n\n///|\nfn Char::escape_to(self : Char, logger : &Logger, quote? : Bool = true) -> Unit {\n if quote {\n logger.write_char('\\'')\n }\n match self {\n '\\'' | '\\\\' => {\n logger.write_char('\\\\')\n logger.write_char(self)\n }\n '\\n' => logger.write_string(\"\\\\n\")\n '\\r' => logger.write_string(\"\\\\r\")\n '\\b' => logger.write_string(\"\\\\b\")\n '\\t' => logger.write_string(\"\\\\t\")\n ' '..='~' => logger.write_char(self)\n _ =>\n if !self.is_printable() {\n logger.write_string(\"\\\\u{\")\n logger.write_string(self.to_hex())\n logger.write_char('}')\n } else {\n logger.write_char(self)\n }\n }\n if quote {\n logger.write_char('\\'')\n }\n}\n\n///|\npub impl ToJson for Char with to_json(self : Char) -> Json {\n Json::string(self.to_string())\n}\n\n///|\n/// Returns the number of UTF-16 code units required to encode this character.\n///\n/// Parameters:\n///\n/// * `self` : The character to analyze.\n///\n/// Returns the number of UTF-16 code units (1 or 2) needed to represent this\n/// character.\n/// Note surrogate pairs are counted as 2, it should not happen in general since \n/// surrogate pair is Int instead of Char.\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect('A'.utf16_len(), content=\"1\")\n/// inspect('🌟'.utf16_len(), content=\"2\")\n/// }\n/// ```\n///\npub fn Char::utf16_len(self : Self) -> Int {\n let code = self.to_int()\n if code <= 0xFFFF {\n 1\n } else {\n 2\n }\n}\n\n///|\n/// Returns true if this character is in the Basic Multilingual Plane (BMP).\n/// \n/// The BMP (Basic Multilingual Plane) contains 65,536 code points (U+0000 to U+FFFF)\n/// distributed as follows:\n/// \n/// - **~57,022 actual Unicode character positions** (87% of BMP)\n/// - **2,048 surrogate code points** (U+D800-U+DFFF) - reserved for UTF-16 encoding\n/// - High surrogates: U+D800-U+DBFF (1,024 code points)\n/// - Low surrogates: U+DC00-U+DFFF (1,024 code points)\n/// - **6,400 private use area** (U+E000-U+F8FF) - for custom characters\n/// - **66 permanent noncharacters** (including U+FFFE, U+FFFF, U+FDD0-U+FDEF)\n/// \n/// Note: Surrogate code points are not actual characters but encoding mechanisms\n/// for representing characters outside the BMP in UTF-16.\n/// \n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect('A'.is_bmp(), content=\"true\")\n/// inspect('🌟'.is_bmp(), content=\"false\")\n/// }\n/// ```\n/// \npub fn Char::is_bmp(self : Self) -> Bool {\n self.to_int() <= 0xFFFF\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn[T] ReadOnlyArray::unsafe_reinterpret_to_fixed_array(\n self : ReadOnlyArray[T],\n) -> FixedArray[T] = \"%identity\"\n\n///|\nfn[T] unsafe_reinterpret_from_fixed_array(\n arr : FixedArray[T],\n) -> ReadOnlyArray[T] = \"%identity\"\n\n///|\n/// Access element at `index` in a read-only array.\n///\n/// Panics if index is out of bounds.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a : ReadOnlyArray[Int] = [10, 20, 30]\n/// inspect(a.at(1), content=\"20\")\n/// }\n/// ```\n#alias(\"_[_]\")\npub fn[T] ReadOnlyArray::at(self : ReadOnlyArray[T], index : Int) -> T {\n self.unsafe_reinterpret_to_fixed_array()[index]\n}\n\n///|\n/// Creates an ReadOnlyArray from a dynamic Array.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let dynamic_array = [1, 2, 3, 4, 5]\n/// let immut_array = ReadOnlyArray::from_array(dynamic_array)\n/// inspect(immut_array[0], content=\"1\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::from_array(array : ArrayView[T]) -> ReadOnlyArray[T] {\n unsafe_reinterpret_from_fixed_array(FixedArray::from_array(array))\n}\n\n///|\n/// Creates an ReadOnlyArray from an iterator.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let iter = [1, 2, 3].iter()\n/// let immut_array = ReadOnlyArray::from_iter(iter)\n/// inspect(immut_array[0], content=\"1\")\n/// }\n/// ```\n#alias(from_iterator, deprecated)\npub fn[T] ReadOnlyArray::from_iter(iter : Iter[T]) -> ReadOnlyArray[T] {\n unsafe_reinterpret_from_fixed_array(FixedArray::from_iter(iter))\n}\n\n///|\n/// Creates an ReadOnlyArray by applying a function to each index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let immut_array = ReadOnlyArray::makei(3, fn(i) { i * 2 })\n/// inspect(immut_array[1], content=\"2\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::makei(\n length : Int,\n value : (Int) -> T raise?,\n) -> ReadOnlyArray[T] raise? {\n unsafe_reinterpret_from_fixed_array(FixedArray::makei(length, value))\n}\n\n///|\n/// Safely retrieves an element at the specified index.\n/// Returns Some(element) if the index is valid, None otherwise.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// debug_inspect(arr.get(1), content=\"Some(2)\")\n/// debug_inspect(arr.get(5), content=\"None\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::get(self : ReadOnlyArray[T], index : Int) -> T? {\n self.unsafe_reinterpret_to_fixed_array().get(index)\n}\n\n///|\n/// Returns the length of the ReadOnlyArray.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr.length(), content=\"3\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::length(self : ReadOnlyArray[T]) -> Int {\n self.unsafe_reinterpret_to_fixed_array().length()\n}\n\n///|\n/// Checks if the ReadOnlyArray is empty.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let empty_arr : ReadOnlyArray[Int] = []\n/// inspect(empty_arr.is_empty(), content=\"true\")\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr.is_empty(), content=\"false\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::is_empty(self : ReadOnlyArray[T]) -> Bool {\n self.unsafe_reinterpret_to_fixed_array().is_empty()\n}\n\n///|\n/// Returns the last element of the ReadOnlyArray, if any.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// debug_inspect(arr.last(), content=\"Some(3)\")\n/// let empty_arr : ReadOnlyArray[Int] = []\n/// debug_inspect(empty_arr.last(), content=\"None\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::last(self : ReadOnlyArray[T]) -> T? {\n self.unsafe_reinterpret_to_fixed_array().last()\n}\n\n///|\n/// Creates an iterator over the elements of the ReadOnlyArray.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let mut sum = 0\n/// arr.iter().each(fn(x) { sum = sum + x })\n/// inspect(sum, content=\"6\")\n/// }\n/// ```\n#alias(iterator, deprecated)\npub fn[T] ReadOnlyArray::iter(self : ReadOnlyArray[T]) -> Iter[T] {\n self.unsafe_reinterpret_to_fixed_array().iter()\n}\n\n///|\n/// Creates an iterator that yields both indices and values.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [10, 20, 30]\n/// let mut sum = 0\n/// arr.iter2().each(fn(i, x) { sum = sum + i + x })\n/// inspect(sum, content=\"63\") // (0+10) + (1+20) + (2+30) = 63\n/// }\n/// ```\npub fn[T] ReadOnlyArray::iter2(self : ReadOnlyArray[T]) -> Iter2[Int, T] {\n self.unsafe_reinterpret_to_fixed_array().iter2()\n}\n\n///|\n/// Returns an iterator that yields each element from the last to the first.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let result = []\n/// arr.rev_iter().each(x => result.push(x))\n/// debug_inspect(result, content=\"[3, 2, 1]\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::rev_iter(self : ReadOnlyArray[T]) -> Iter[T] {\n self[:].rev_iter()\n}\n\n///|\n/// Iterates over each element in the ReadOnlyArray.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let result = []\n/// arr.each(fn(x) { result.push(x * 2) })\n/// debug_inspect(result, content=\"[2, 4, 6]\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::each(\n self : ReadOnlyArray[T],\n f : (T) -> Unit raise?,\n) -> Unit raise? {\n self.unsafe_reinterpret_to_fixed_array().each(f)\n}\n\n///|\n/// Iterates over each element with its index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [10, 20, 30]\n/// let result = []\n/// arr.eachi(fn(i, x) { result.push((i, x)) })\n/// debug_inspect(result, content=\"[(0, 10), (1, 20), (2, 30)]\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::eachi(\n self : ReadOnlyArray[T],\n f : (Int, T) -> Unit raise?,\n) -> Unit raise? {\n self.unsafe_reinterpret_to_fixed_array().eachi(f)\n}\n\n///|\n/// Iterates over each element in reverse order.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let result = []\n/// arr.rev_each(fn(x) { result.push(x) })\n/// debug_inspect(result, content=\"[3, 2, 1]\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::rev_each(\n self : ReadOnlyArray[T],\n f : (T) -> Unit raise?,\n) -> Unit raise? {\n self.unsafe_reinterpret_to_fixed_array().rev_each(f)\n}\n\n///|\n/// Iterates over each element in reverse order with its index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [10, 20, 30]\n/// let result = []\n/// arr.rev_eachi(fn(i, x) { result.push((i, x)) })\n/// debug_inspect(result, content=\"[(0, 30), (1, 20), (2, 10)]\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::rev_eachi(\n self : ReadOnlyArray[T],\n f : (Int, T) -> Unit raise?,\n) -> Unit raise? {\n self.unsafe_reinterpret_to_fixed_array().rev_eachi(f)\n}\n\n///|\n/// Creates a new ReadOnlyArray by applying a function to each element.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let doubled = arr.map(fn(x) { x * 2 })\n/// inspect(doubled[0], content=\"2\")\n/// inspect(doubled[2], content=\"6\")\n/// }\n/// ```\npub fn[T, U] ReadOnlyArray::map(\n self : ReadOnlyArray[T],\n f : (T) -> U raise?,\n) -> ReadOnlyArray[U] raise? {\n unsafe_reinterpret_from_fixed_array(\n self.unsafe_reinterpret_to_fixed_array().map(f),\n )\n}\n\n///|\n/// Creates a new ReadOnlyArray by applying a function to each element with its index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [10, 20, 30]\n/// let result = arr.mapi(fn(i, x) { i + x })\n/// inspect(result[1], content=\"21\") // index 1 + value 20 = 21\n/// }\n/// ```\npub fn[T, U] ReadOnlyArray::mapi(\n self : ReadOnlyArray[T],\n f : (Int, T) -> U raise?,\n) -> ReadOnlyArray[U] raise? {\n unsafe_reinterpret_from_fixed_array(\n self.unsafe_reinterpret_to_fixed_array().mapi(f),\n )\n}\n\n///|\n/// Returns a new ReadOnlyArray containing the elements for which `f` returns\n/// `true`, in original order.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// debug_inspect(\n/// arr.filter(x => x % 2 == 0),\n/// content=(\n/// #|<ReadOnlyArray: [2, 4]>\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] ReadOnlyArray::filter(\n self : ReadOnlyArray[T],\n f : (T) -> Bool raise?,\n) -> ReadOnlyArray[T] raise? {\n ReadOnlyArray::from_array(self[:].filter(f)[:])\n}\n\n///|\n/// Returns a new ReadOnlyArray that maps and filters in one pass: for each\n/// element, `Some(new_value)` includes the mapped value and `None` drops it.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// let out = arr.filter_map(x => if x % 2 == 0 { Some(x * 10) } else { None })\n/// debug_inspect(\n/// out,\n/// content=(\n/// #|<ReadOnlyArray: [20, 40]>\n/// ),\n/// )\n/// }\n/// ```\npub fn[A, B] ReadOnlyArray::filter_map(\n self : ReadOnlyArray[A],\n f : (A) -> B? raise?,\n) -> ReadOnlyArray[B] raise? {\n ReadOnlyArray::from_array(self[:].filter_map(f)[:])\n}\n\n///|\n/// Folds the ReadOnlyArray from left to right.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// let sum = arr.fold(init=0, fn(acc, x) { acc + x })\n/// inspect(sum, content=\"15\")\n/// }\n/// ```\npub fn[A, B] ReadOnlyArray::fold(\n self : ReadOnlyArray[A],\n init~ : B,\n f : (B, A) -> B raise?,\n) -> B raise? {\n self.unsafe_reinterpret_to_fixed_array().fold(init~, f)\n}\n\n///|\n/// Folds the ReadOnlyArray from right to left.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// let result = arr.rev_fold(init=\"\", fn(acc, x) { acc + x.to_string() })\n/// inspect(result, content=\"321\") // Processed in reverse order\n/// }\n/// ```\npub fn[A, B] ReadOnlyArray::rev_fold(\n self : ReadOnlyArray[A],\n init~ : B,\n f : (B, A) -> B raise?,\n) -> B raise? {\n self.unsafe_reinterpret_to_fixed_array().rev_fold(init~, f)\n}\n\n///|\n/// Folds the ReadOnlyArray from left to right with index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [2, 3]\n/// let sum = arr.foldi(init=0, fn(i, acc, x) { acc + i * x })\n/// inspect(sum, content=\"3\") // 0 + (0*2) + (1*3) = 3\n/// }\n/// ```\npub fn[A, B] ReadOnlyArray::foldi(\n self : ReadOnlyArray[A],\n init~ : B,\n f : (Int, B, A) -> B raise?,\n) -> B raise? {\n self.unsafe_reinterpret_to_fixed_array().foldi(init~, f)\n}\n\n///|\n/// Folds the ReadOnlyArray from right to left with index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [2, 3]\n/// let sum = arr.rev_foldi(init=0, fn(i, acc, x) { acc + i * x })\n/// inspect(sum, content=\"2\") // 0 + (1*3) + (0*2) = 3\n/// }\n/// ```\npub fn[A, B] ReadOnlyArray::rev_foldi(\n self : ReadOnlyArray[A],\n init~ : B,\n f : (Int, B, A) -> B raise?,\n) -> B raise? {\n self.unsafe_reinterpret_to_fixed_array().rev_foldi(init~, f)\n}\n\n///|\n/// Returns a new ReadOnlyArray with elements in reverse order.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// let reversed = arr.rev()\n/// inspect(reversed[0], content=\"5\")\n/// inspect(reversed[4], content=\"1\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::rev(self : ReadOnlyArray[T]) -> ReadOnlyArray[T] {\n unsafe_reinterpret_from_fixed_array(\n self.unsafe_reinterpret_to_fixed_array().rev(),\n )\n}\n\n///|\n/// Searches for an element and returns its index if found.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 2, 4]\n/// debug_inspect(arr.search(2), content=\"Some(1)\") // Returns first occurrence\n/// debug_inspect(arr.search(5), content=\"None\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::search(\n self : ReadOnlyArray[T],\n value : T,\n) -> Int? {\n self.unsafe_reinterpret_to_fixed_array().search(value)\n}\n\n///|\n/// Returns the index of the first element satisfying `f`, or `None`.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// debug_inspect(arr.search_by(x => x > 3), content=\"Some(3)\")\n/// debug_inspect(arr.search_by(x => x > 99), content=\"None\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::search_by(\n self : ReadOnlyArray[T],\n f : (T) -> Bool raise?,\n) -> Int? raise? {\n self[:].search_by(f)\n}\n\n///|\n/// Checks if the ReadOnlyArray contains a specific value.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr.contains(2), content=\"true\")\n/// inspect(arr.contains(4), content=\"false\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::contains(\n self : ReadOnlyArray[T],\n value : T,\n) -> Bool {\n self.unsafe_reinterpret_to_fixed_array().contains(value)\n}\n\n///|\n/// Checks if the ReadOnlyArray is sorted in non-decreasing order.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr.is_sorted(), content=\"true\")\n/// let arr2 : ReadOnlyArray[Int] = [2, 1]\n/// inspect(arr2.is_sorted(), content=\"false\")\n/// }\n/// ```\npub fn[T : Compare] ReadOnlyArray::is_sorted(self : ReadOnlyArray[T]) -> Bool {\n self.unsafe_reinterpret_to_fixed_array().is_sorted()\n}\n\n///|\n/// Checks if the ReadOnlyArray starts with the given prefix.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// inspect(arr.starts_with([1, 2][:]), content=\"true\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::starts_with(\n self : ReadOnlyArray[T],\n prefix : ArrayView[T],\n) -> Bool {\n self[:].starts_with(prefix)\n}\n\n///|\n/// Checks if the ReadOnlyArray ends with the given suffix.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// inspect(arr.ends_with([4, 5][:]), content=\"true\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::ends_with(\n self : ReadOnlyArray[T],\n suffix : ArrayView[T],\n) -> Bool {\n self[:].ends_with(suffix)\n}\n\n///|\n/// If the array starts with `prefix`, returns a view of the remainder.\n/// Otherwise returns `None`. The returned view shares the backing storage —\n/// no allocation.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// debug_inspect(\n/// arr.strip_prefix([1, 2][:]),\n/// content=(\n/// #|Some(<ArrayView: [3, 4, 5]>)\n/// ),\n/// )\n/// debug_inspect(arr.strip_prefix([2, 3][:]), content=\"None\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::strip_prefix(\n self : ReadOnlyArray[T],\n prefix : ArrayView[T],\n) -> ArrayView[T]? {\n self[:].strip_prefix(prefix)\n}\n\n///|\n/// If the array ends with `suffix`, returns a view of the leading portion.\n/// Otherwise returns `None`. The returned view shares the backing storage —\n/// no allocation.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// debug_inspect(\n/// arr.strip_suffix([4, 5][:]),\n/// content=(\n/// #|Some(<ArrayView: [1, 2, 3]>)\n/// ),\n/// )\n/// debug_inspect(arr.strip_suffix([3, 4][:]), content=\"None\")\n/// }\n/// ```\npub fn[T : Eq] ReadOnlyArray::strip_suffix(\n self : ReadOnlyArray[T],\n suffix : ArrayView[T],\n) -> ArrayView[T]? {\n self[:].strip_suffix(suffix)\n}\n\n///|\n/// Checks if all elements satisfy the given predicate.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [2, 4, 6]\n/// inspect(arr.all(fn(x) { x % 2 == 0 }), content=\"true\")\n/// let arr2 : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr2.all(fn(x) { x % 2 == 0 }), content=\"false\")\n/// }\n/// ```\n#alias(every)\npub fn[T] ReadOnlyArray::all(\n self : ReadOnlyArray[T],\n f : (T) -> Bool raise?,\n) -> Bool raise? {\n self.unsafe_reinterpret_to_fixed_array().all(f)\n}\n\n///|\n/// Checks if any element satisfies the given predicate.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 3, 5]\n/// inspect(arr.any(fn(x) { x % 2 == 0 }), content=\"false\")\n/// let arr2 : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(arr2.any(fn(x) { x % 2 == 0 }), content=\"true\")\n/// }\n/// ```\n#alias(exists)\npub fn[T] ReadOnlyArray::any(\n self : ReadOnlyArray[T],\n f : (T) -> Bool raise?,\n) -> Bool raise? {\n self.unsafe_reinterpret_to_fixed_array().any(f)\n}\n\n///|\n/// Performs binary search on a sorted ReadOnlyArray.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 3, 5, 7, 9]\n/// debug_inspect(arr.binary_search(5), content=\"Ok(2)\")\n/// debug_inspect(arr.binary_search(6), content=\"Err(3)\")\n/// }\n/// ```\npub fn[T : Compare] ReadOnlyArray::binary_search(\n self : ReadOnlyArray[T],\n value : T,\n) -> Result[Int, Int] {\n self.unsafe_reinterpret_to_fixed_array().binary_search(value)\n}\n\n///|\n/// Performs binary search using a custom comparison function.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 3, 5, 7, 9]\n/// let result = arr.binary_search_by(fn(x) { x.compare(5) })\n/// debug_inspect(result, content=\"Ok(2)\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::binary_search_by(\n self : ReadOnlyArray[T],\n cmp : (T) -> Int raise?,\n) -> Result[Int, Int] raise? {\n self.unsafe_reinterpret_to_fixed_array().binary_search_by(cmp)\n}\n\n///|\n/// Splits the array into consecutive non-overlapping chunks of length `size`,\n/// from left to right. The final chunk is shorter when `length` is not a\n/// multiple of `size`. Each returned sub-view shares the original backing\n/// storage — no allocation per chunk.\n///\n/// Panics if `size <= 0`.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5, 6, 7]\n/// debug_inspect(\n/// arr.chunks(3),\n/// content=(\n/// #|[<ArrayView: [1, 2, 3]>, <ArrayView: [4, 5, 6]>, <ArrayView: [7]>]\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] ReadOnlyArray::chunks(\n self : ReadOnlyArray[T],\n size : Int,\n) -> Array[ArrayView[T]] {\n self[:].chunks(size)\n}\n\n///|\n/// Returns all contiguous sub-views of length `size`, from left to right. The\n/// result has `length - size + 1` entries when `size <= length`, and is empty\n/// otherwise. Each sub-view shares the original backing storage.\n///\n/// Panics if `size <= 0`.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4]\n/// debug_inspect(\n/// arr.windows(2),\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [2, 3]>, <ArrayView: [3, 4]>]\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] ReadOnlyArray::windows(\n self : ReadOnlyArray[T],\n size : Int,\n) -> Array[ArrayView[T]] {\n self[:].windows(size)\n}\n\n///|\n/// Groups consecutive elements into chunks where each adjacent pair satisfies\n/// `pred`. A new chunk starts as soon as `pred(prev, cur)` is `false`. Each\n/// returned sub-view shares the original backing storage.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 1, 2, 2, 2, 3, 1]\n/// debug_inspect(\n/// arr.chunk_by((a, b) => a == b),\n/// content=(\n/// #|[\n/// #| <ArrayView: [1, 1]>,\n/// #| <ArrayView: [2, 2, 2]>,\n/// #| <ArrayView: [3]>,\n/// #| <ArrayView: [1]>,\n/// #|]\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] ReadOnlyArray::chunk_by(\n self : ReadOnlyArray[T],\n pred : (T, T) -> Bool raise?,\n) -> Array[ArrayView[T]] raise? {\n self[:].chunk_by(pred)\n}\n\n///|\n/// Yields all suffix views from the longest down to length 1 (and the empty\n/// view if `include_empty=true`). Each suffix shares the original backing\n/// storage.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2]\n/// debug_inspect(\n/// arr.suffixes().collect(),\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [2]>]\n/// ),\n/// )\n/// debug_inspect(\n/// arr.suffixes(include_empty=true).collect(),\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [2]>, <ArrayView: []>]\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] ReadOnlyArray::suffixes(\n self : ReadOnlyArray[T],\n include_empty? : Bool = false,\n) -> Iter[ArrayView[T]] {\n self[:].suffixes(include_empty~)\n}\n\n///|\n/// Performs a lexicographical comparison of two arrays.\n///\n/// Unlike the `Compare` trait implementation (shortlex — shorter arrays come\n/// first), this method compares purely by element values; length only breaks\n/// ties when one array is a prefix of the other.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let a : ReadOnlyArray[Int] = [1, 2]\n/// let b : ReadOnlyArray[Int] = [1, 2, 3]\n/// inspect(a.lexical_compare(b), content=\"-1\")\n/// inspect(b.lexical_compare(a), content=\"1\")\n/// inspect(b.lexical_compare(b), content=\"0\")\n/// let c : ReadOnlyArray[Int] = [1, 2, 4]\n/// inspect(b.lexical_compare(c), content=\"-1\")\n/// }\n/// ```\npub fn[T : Compare] ReadOnlyArray::lexical_compare(\n self : ReadOnlyArray[T],\n other : ReadOnlyArray[T],\n) -> Int {\n self[:].lexical_compare(other[:])\n}\n\n///|\n/// Creates a view of a subarray.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// let view = arr[1:4]\n/// inspect(view[0], content=\"2\")\n/// inspect(view[2], content=\"4\")\n/// }\n/// ```\n#alias(\"_[_:_]\")\n#alias(sub, deprecated=\"Use _[_:_] instead\")\npub fn[T] ReadOnlyArray::view(\n self : ReadOnlyArray[T],\n start? : Int = 0,\n end? : Int,\n) -> ArrayView[T] {\n match end {\n None => self.unsafe_reinterpret_to_fixed_array()[start:]\n Some(e) => self.unsafe_reinterpret_to_fixed_array()[start:e]\n }\n}\n\n///|\n/// Creates a view of a subarray, returning `None` when indices are invalid.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]\n/// let start = 1\n/// let end = 4\n/// debug_inspect(\n/// arr.get_view(start~, end~),\n/// content=(\n/// #|Some(<ArrayView: [2, 3, 4]>)\n/// ),\n/// )\n/// let start = 4\n/// let end = 10\n/// debug_inspect(arr.get_view(start~, end~), content=\"None\")\n/// }\n/// ```\npub fn[T] ReadOnlyArray::get_view(\n self : ReadOnlyArray[T],\n start? : Int = 0,\n end? : Int,\n) -> ArrayView[T]? {\n let fixed = self.unsafe_reinterpret_to_fixed_array()\n match end {\n None => fixed.get_view(start~)\n Some(end) => fixed.get_view(start~, end~)\n }\n}\n\n///|\n/// Joins the string-renderable elements with a separator.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr : ReadOnlyArray[String] = [\"hello\", \"world\", \"moon\"]\n/// inspect(arr.join(\",\"), content=\"hello,world,moon\")\n/// inspect(arr.join(\" \"), content=\"hello world moon\")\n/// }\n/// ```\npub fn[A : ToStringView] ReadOnlyArray::join(\n self : ReadOnlyArray[A],\n separator : StringView,\n) -> String {\n self[:].join(separator)\n}\n\n///|\n/// Default implementation for ReadOnlyArray - returns empty array.\npub impl[T] Default for ReadOnlyArray[T] with default() {\n unsafe_reinterpret_from_fixed_array(FixedArray::default())\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[T : Show] Show for ReadOnlyArray[T]\n\n///|\n/// Show implementation for ReadOnlyArray.\n#warnings(\"-deprecated\")\npub impl[T : Show] Show for ReadOnlyArray[T] with output(self, logger) {\n self.unsafe_reinterpret_to_fixed_array().output(logger)\n}\n\n///|\n/// ToJson implementation for ReadOnlyArray.\npub impl[T : ToJson] ToJson for ReadOnlyArray[T] with to_json(self) {\n self.unsafe_reinterpret_to_fixed_array().to_json()\n}\n\n///|\npub impl[T : Eq] Eq for ReadOnlyArray[T] with equal(self, other) {\n self\n .unsafe_reinterpret_to_fixed_array()\n .equal(other.unsafe_reinterpret_to_fixed_array())\n}\n\n///|\npub impl[T : Hash] Hash for ReadOnlyArray[T] with hash_combine(self, hasher) {\n self.unsafe_reinterpret_to_fixed_array().hash_combine(hasher)\n}\n\n///|\npub impl[T : Compare] Compare for ReadOnlyArray[T] with compare(self, other) {\n self\n .unsafe_reinterpret_to_fixed_array()\n .compare(other.unsafe_reinterpret_to_fixed_array())\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\npub impl[X : Eq] Eq for X? with equal(self, other) {\n match (self, other) {\n (None, None) => true\n (Some(x), Some(y)) => x == y\n _ => false\n }\n}\n\n///|\n/// Convert to `string`.\n#deprecated(\"Option does not have a meaningful string representation\")\npub fn[X : Show] Option::to_string(self : X?) -> String {\n match self {\n None => \"None\"\n Some(x) => \"Some(\" + x.to_string() + \")\"\n }\n}\n\n///|\n/// Extract the value in `Some`.\n/// \n/// If the value is `None`, it throws a panic.\npub fn[X] Option::unwrap(self : X?) -> X {\n match self {\n None => panic()\n Some(x) => x\n }\n}\n\n///|\n/// Return the contained `Some` value or the provided default.\n#alias(or, deprecated)\npub fn[T] Option::unwrap_or(self : T?, default : T) -> T {\n match self {\n None => default\n Some(t) => t\n }\n}\n\n///|\n/// Return the contained `Some` value or the provided default.\n///\n/// Default is lazily evaluated\n#alias(or_else, deprecated)\npub fn[T] Option::unwrap_or_else(\n self : T?,\n default : () -> T raise?,\n) -> T raise? {\n match self {\n None => default()\n Some(t) => t\n }\n}\n\n///|\n/// Return the contained `Some` value or the result of the `T::default()`.\n#alias(or_default, deprecated)\npub fn[T : Default] Option::unwrap_or_default(self : T?) -> T {\n match self {\n None => T::default()\n Some(t) => t\n }\n}\n\n///|\npub impl[X : Compare] Compare for X? with compare(self, other) {\n match (self, other) {\n (Some(x), Some(y)) => x.compare(y)\n (Some(_), None) => 1\n (None, Some(_)) => -1\n (None, None) => 0\n }\n}\n\n///|\n/// Extract the wrapped value with `unwrap_or_error` semantics.\n#alias(or_error, deprecated)\npub fn[T, Err : Error] Option::unwrap_or_error(\n self : T?,\n err : Err,\n) -> T raise Err {\n match self {\n Some(v) => v\n None => raise err\n }\n}\n\n///|\n/// `None`\npub impl[X] Default for X? with default() {\n None\n}\n\n///|\n/// Return an iterator via `iter`.\n#alias(iterator, deprecated)\npub fn[T] Option::iter(self : T?) -> Iter[T] {\n match self {\n Some(v) => Iter::singleton(v)\n None => Iter::empty()\n }\n}\n\n///|\n/// Maps the value of an `Option` using a provided function.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let a = Some(5)\n/// assert_eq(a.map(x => x * 2), Some(10))\n/// let b = None\n/// assert_eq(b.map(x => x * 2), None)\n/// }\n/// ```\npub fn[T, U] Option::map(self : T?, f : (T) -> U raise?) -> U? raise? {\n match self {\n Some(t) => Some(f(t))\n None => None\n }\n}\n\n///|\n/// Returns the provided default result (if none), or applies a function to the contained value (if any).\n/// Arguments passed to map_or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use `map_or_else`, which is lazily evaluated.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let a = Some(5)\n/// assert_eq(a.map_or(3, x => x * 2), 10)\n/// }\n/// ```\npub fn[T, U] Option::map_or(\n self : T?,\n default : U,\n f : (T) -> U raise?,\n) -> U raise? {\n match self {\n None => default\n Some(x) => f(x)\n }\n}\n\n///|\n/// Computes a default function result (if none), or applies a different function to the contained value (if any).\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let a = Some(5)\n/// assert_eq(a.map_or_else(() => 3, x => x * 2), 10)\n/// }\n/// ```\npub fn[T, U] Option::map_or_else(\n self : T?,\n default : () -> U raise?,\n f : (T) -> U raise?,\n) -> U raise? {\n match self {\n None => default()\n Some(x) => f(x)\n }\n}\n\n///|\n/// Binds an option to a function that returns another option.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let a = Option::Some(5)\n/// let r1 = a.bind(x => Some(x * 2))\n/// assert_eq(r1, Some(10))\n/// let b : Int? = None\n/// let r2 = b.bind(x => Some(x * 2))\n/// assert_eq(r2, None)\n/// }\n/// ```\npub fn[T, U] Option::bind(self : T?, f : (T) -> U? raise?) -> U? raise? {\n match self {\n Some(t) => f(t)\n None => None\n }\n}\n\n///|\n/// Flatten nested option/result value.\n#deprecated(\"use `option.bind(x => x)` instead\")\npub fn[T] Option::flatten(self : T??) -> T? {\n match self {\n Some(inner) => inner\n None => None\n }\n}\n\n///|\n/// Checks if the option is empty.\n#deprecated(\"use `x is None` instead\")\npub fn[T] Option::is_empty(self : T?) -> Bool {\n self is None\n}\n\n///|\n/// Filters the option by applying the given predicate function `f`.\n///\n/// If the predicate function `f` returns `true` for the value contained in the option,\n/// the same option is returned. Otherwise, `None` is returned.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let x = Some(3)\n/// assert_eq(x.filter(x => x > 5), None)\n/// assert_eq(x.filter(x => x < 5), Some(3))\n/// }\n/// ```\npub fn[T] Option::filter(self : T?, f : (T) -> Bool raise?) -> T? raise? {\n match self {\n Some(t) => if f(t) { self } else { None }\n None => None\n }\n}\n\n///|\n/// Checks if the option contains a value.\n#deprecated(\"use `x is Some(_)` instead\")\npub fn[T] Option::is_some(self : T?) -> Bool {\n self is Some(_)\n}\n\n///|\n/// Checks if the option is None.\n#deprecated(\"use `x is None` instead\")\npub fn[T] Option::is_none(self : T?) -> Bool {\n self is None\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Types\n\n///|\npriv struct Entry[K, V] {\n mut prev : Int\n mut next : Entry[K, V]?\n mut psl : Int\n hash : Int\n key : K\n mut value : V\n}\n\n///|\n/// Mutable linked hash map that maintains the order of insertion, not thread safe.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let map = { 3: \"three\", 8: \"eight\", 1: \"one\" }\n/// assert_eq(map.get(2), None)\n/// assert_eq(map.get(3), Some(\"three\"))\n/// map.set(3, \"updated\")\n/// assert_eq(map.get(3), Some(\"updated\"))\n/// }\n/// ```\nstruct Map[K, V] {\n mut entries : FixedArray[Entry[K, V]?]\n mut size : Int // active key-value pairs count\n mut capacity : Int // current capacity\n mut capacity_mask : Int // capacity_mask = capacity - 1, used to find idx\n mut grow_at : Int // threshold that triggers grow\n mut head : Entry[K, V]? // head of linked list\n mut tail : Int // tail of linked list\n}\n\n// Implementations\n\n///|\nlet default_init_capacity = 8\n\n///|\nfn[K, V] new_map(capacity : Int) -> Map[K, V] {\n let capacity = capacity.next_power_of_two()\n {\n size: 0,\n capacity,\n capacity_mask: capacity - 1,\n grow_at: calc_grow_threshold(capacity),\n entries: FixedArray::make(capacity, None),\n head: None,\n tail: -1,\n }\n}\n\n///|\nfn capacity_for_length(length : Int) -> Int {\n let mut capacity = length.next_power_of_two()\n if length > calc_grow_threshold(capacity) {\n capacity *= 2\n }\n capacity\n}\n\n///|\n/// Create a hash map from an array.\n/// The optional `capacity` is treated as a minimum initial capacity and will be\n/// rounded up to the smallest power of 2 that can hold the requested capacity.\n#alias(from_array)\npub fn[K : Hash + Eq, V] Map::Map(\n arr : ArrayView[(K, V)],\n capacity? : Int,\n) -> Map[K, V] {\n let length = arr.length()\n let capacity = match capacity {\n Some(capacity) => capacity.max(capacity_for_length(length))\n None =>\n if length == 0 {\n default_init_capacity\n } else {\n capacity_for_length(length)\n }\n }\n let m = new_map(capacity)\n for e in arr {\n m.set(e.0, e.1)\n }\n m\n}\n\n///|\n/// Sets a key-value pair into the hash map. If the key already exists, updates\n/// its value. If the hash map is near full capacity, automatically\n/// grows the internal storage to accommodate more entries.\n///\n/// Parameters:\n///\n/// * `map` : The hash map to modify.\n/// * `key` : The key to insert or update. Must implement `Hash` and `Eq` traits.\n/// * `value` : The value to associate with the key.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map : Map[String, Int] = Map([])\n/// map.set(\"key\", 42)\n/// debug_inspect(map.get(\"key\"), content=\"Some(42)\")\n/// map.set(\"key\", 24) // update existing key\n/// debug_inspect(map.get(\"key\"), content=\"Some(24)\")\n/// }\n/// ```\n#alias(\"_[_]=_\")\npub fn[K : Hash + Eq, V] Map::set(self : Map[K, V], key : K, value : V) -> Unit {\n self.set_with_hash(key, value, key.hash())\n}\n\n///|\nfn[K : Eq, V] Map::set_with_hash(\n self : Map[K, V],\n key : K,\n value : V,\n hash : Int,\n) -> Unit {\n // Only grow when actually inserting a new entry, not when updating existing\n for psl = 0, idx = hash & self.capacity_mask {\n match self.entries[idx] {\n None => {\n // Need to insert new entry - check if grow is needed first\n if self.size >= self.grow_at {\n self.grow()\n // Restart search with new capacity_mask\n continue 0, hash & self.capacity_mask\n }\n let entry = { prev: self.tail, next: None, psl, key, value, hash }\n self.add_entry_to_tail(idx, entry)\n return\n }\n Some(curr_entry) => {\n if curr_entry.hash == hash && curr_entry.key == key {\n // Key exists - just update value, no grow needed\n curr_entry.value = value\n return\n }\n if psl > curr_entry.psl {\n // Need to insert and push away - check if grow is needed first\n if self.size >= self.grow_at {\n self.grow()\n // Restart search with new capacity_mask\n continue 0, hash & self.capacity_mask\n }\n self.push_away(idx, curr_entry)\n let entry = { prev: self.tail, next: None, psl, key, value, hash }\n self.add_entry_to_tail(idx, entry)\n return\n }\n continue psl + 1, (idx + 1) & self.capacity_mask\n }\n }\n }\n}\n\n///|\nfn[K, V] Map::push_away(\n self : Map[K, V],\n idx : Int,\n entry : Entry[K, V],\n) -> Unit {\n for psl = entry.psl + 1, idx = (idx + 1) & self.capacity_mask, entry = entry {\n match self.entries[idx] {\n None => {\n entry.psl = psl\n self.set_entry(entry, idx)\n break\n }\n Some(curr_entry) =>\n if psl > curr_entry.psl {\n entry.psl = psl\n self.set_entry(entry, idx)\n continue curr_entry.psl + 1,\n (idx + 1) & self.capacity_mask,\n curr_entry\n } else {\n continue psl + 1, (idx + 1) & self.capacity_mask, entry\n }\n }\n }\n}\n\n///|\nfn[K, V] Map::set_entry(\n self : Map[K, V],\n entry : Entry[K, V],\n new_idx : Int,\n) -> Unit {\n self.entries[new_idx] = Some(entry)\n match entry.next {\n None => self.tail = new_idx\n Some(next) => next.prev = new_idx\n }\n}\n\n///|\n/// Retrieves the value associated with a given key in the hash map.\n///\n/// Parameters:\n///\n/// * `self` : The hash map to search in.\n/// * `key` : The key to look up in the map.\n///\n/// Returns `Some(value)` if the key exists in the map, `None` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"key\": 42 }\n/// debug_inspect(map.get(\"key\"), content=\"Some(42)\")\n/// debug_inspect(map.get(\"nonexistent\"), content=\"None\")\n/// }\n/// ```\npub fn[K : Hash + Eq, V] Map::get(self : Map[K, V], key : K) -> V? {\n let hash = key.hash()\n for i = 0, idx = hash & self.capacity_mask {\n guard self.entries[idx] is Some(entry) else { break None }\n if entry.hash == hash && entry.key == key {\n break Some(entry.value)\n }\n if i > entry.psl {\n break None\n }\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n}\n\n///|\n/// Get value with `at` access semantics.\n#alias(\"_[_]\")\npub fn[K : Hash + Eq, V] Map::at(self : Map[K, V], key : K) -> V {\n let hash = key.hash()\n for i = 0, idx = hash & self.capacity_mask {\n guard self.entries[idx] is Some(entry)\n if entry.hash == hash && entry.key == key {\n return entry.value\n }\n guard i <= entry.psl\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n}\n\n///|\n/// Returns the value associated with the key in the map, or computes and returns\n/// a default value if the key does not exist.\n///\n/// Parameters:\n///\n/// * `map` : The map to search in.\n/// * `key` : The key to look up in the map.\n/// * `default` : A function that returns a default value when the key is not\n/// found.\n///\n/// Returns either the value associated with the key if it exists, or the result\n/// of calling the default function.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"a\": 1, \"b\": 2 }\n/// inspect(map.get_or_default(\"a\", 0), content=\"1\")\n/// inspect(map.get_or_default(\"c\", 42), content=\"42\")\n/// }\n/// ```\npub fn[K : Hash + Eq, V] Map::get_or_default(\n self : Map[K, V],\n key : K,\n default : V,\n) -> V {\n let hash = key.hash()\n for i = 0, idx = hash & self.capacity_mask {\n match self.entries[idx] {\n Some(entry) => {\n if entry.hash == hash && entry.key == key {\n break entry.value\n }\n if i > entry.psl {\n break default\n }\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n None => break default\n }\n }\n}\n\n///|\n/// Returns the value for the given key, or sets and returns a default value if the key does not exist.\npub fn[K : Hash + Eq, V] Map::get_or_init(\n self : Map[K, V],\n key : K,\n default : () -> V,\n) -> V {\n let hash = key.hash()\n let (idx, psl, new_value, push_away) = for psl = 0, idx = hash &\n self.capacity_mask {\n match self.entries[idx] {\n Some(entry) => {\n if entry.hash == hash && entry.key == key {\n return entry.value\n }\n if psl > entry.psl {\n let new_value = default()\n break (idx, psl, new_value, Some(entry))\n }\n continue psl + 1, (idx + 1) & self.capacity_mask\n }\n None => {\n let new_value = default()\n break (idx, psl, new_value, None)\n }\n }\n }\n if self.size >= self.grow_at {\n // Slow path, we need to resize\n self.grow()\n self.set_with_hash(key, new_value, hash)\n } else {\n if push_away is Some(entry) {\n self.push_away(idx, entry)\n }\n let entry = {\n prev: self.tail,\n next: None,\n psl,\n hash,\n key,\n value: new_value,\n }\n self.add_entry_to_tail(idx, entry)\n }\n new_value\n}\n\n///|\n/// Inserts `default` for `key` if it is absent, otherwise replaces the existing\n/// value with `f(existing)`. The pairing of an eager `default` value with a\n/// modifier function lets the canonical counter pattern read literally:\n///\n/// ```mbt check\n/// test {\n/// let counts : Map[String, Int] = Map([])\n/// counts.update_or_default(\"a\", 1, x => x + 1)\n/// counts.update_or_default(\"a\", 1, x => x + 1)\n/// counts.update_or_default(\"b\", 1, x => x + 1)\n/// debug_inspect(counts.get(\"a\"), content=\"Some(2)\")\n/// debug_inspect(counts.get(\"b\"), content=\"Some(1)\")\n/// }\n/// ```\n///\n/// Note: `f` is *not* applied to `default` on first insertion — `default` is\n/// the value stored when the key is absent. This mirrors Java's `Map.merge`\n/// and Rust's `Entry::and_modify(f).or_insert(default)`.\npub fn[K : Hash + Eq, V] Map::update_or_default(\n self : Map[K, V],\n key : K,\n default : V,\n f : (V) -> V,\n) -> Unit {\n let hash = key.hash()\n let (idx, psl, push_away) = for psl = 0, idx = hash & self.capacity_mask {\n match self.entries[idx] {\n Some(entry) => {\n if entry.hash == hash && entry.key == key {\n entry.value = f(entry.value)\n return\n }\n if psl > entry.psl {\n break (idx, psl, Some(entry))\n }\n continue psl + 1, (idx + 1) & self.capacity_mask\n }\n None => break (idx, psl, None)\n }\n }\n if self.size >= self.grow_at {\n self.grow()\n self.set_with_hash(key, default, hash)\n } else {\n if push_away is Some(entry) {\n self.push_away(idx, entry)\n }\n let entry = { prev: self.tail, next: None, psl, hash, key, value: default }\n self.add_entry_to_tail(idx, entry)\n }\n}\n\n///|\n/// Check if the hash map contains a key.\npub fn[K : Hash + Eq, V] Map::contains(self : Map[K, V], key : K) -> Bool {\n // inline Map::get to avoid boxing\n let hash = key.hash()\n for i = 0, idx = hash & self.capacity_mask {\n guard self.entries[idx] is Some(entry) else { break false }\n if entry.hash == hash && entry.key == key {\n break true\n }\n if i > entry.psl {\n break false\n }\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n}\n\n///|\n/// Checks if a map contains a specific key-value pair.\n///\n/// Parameters:\n///\n/// * `map` : A map of type `Map[K, V]` to search in.\n/// * `key` : The key to look up in the map.\n/// * `value` : The value to be compared with the value associated with the key.\n///\n/// Returns `true` if the map contains the specified key and its associated value\n/// equals the given value, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"a\": 1, \"b\": 2 }\n/// inspect(map.contains_kv(\"a\", 1), content=\"true\")\n/// inspect(map.contains_kv(\"a\", 2), content=\"false\")\n/// inspect(map.contains_kv(\"c\", 3), content=\"false\")\n/// }\n/// ```\npub fn[K : Hash + Eq, V : Eq] Map::contains_kv(\n self : Map[K, V],\n key : K,\n value : V,\n) -> Bool {\n // inline Map::get to avoid boxing\n let hash = key.hash()\n for i = 0, idx = hash & self.capacity_mask {\n guard self.entries[idx] is Some(entry) else { break false }\n if entry.hash == hash && entry.key == key && entry.value == value {\n break true\n }\n if i > entry.psl {\n break false\n }\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n}\n\n///|\n/// Removes the entry for the specified key from the hash map. If the key exists\n/// in the map, removes its entry and adjusts the probe sequence length (PSL) of\n/// subsequent entries to maintain the Robin Hood hashing invariant. If the key\n/// does not exist, the map remains unchanged.\n///\n/// Parameters:\n///\n/// * `self` : The hash map to remove the entry from.\n/// * `key` : The key to remove from the map.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"a\": 1, \"b\": 2 }\n/// map.remove(\"a\")\n/// debug_inspect(map.get(\"a\"), content=\"None\")\n/// inspect(map.length(), content=\"1\")\n/// }\n/// ```\npub fn[K : Hash + Eq, V] Map::remove(self : Map[K, V], key : K) -> Unit {\n self.remove_with_hash(key, key.hash())\n}\n\n///|\nfn[K : Eq, V] Map::remove_with_hash(\n self : Map[K, V],\n key : K,\n hash : Int,\n) -> Unit {\n for i = 0, idx = hash & self.capacity_mask {\n guard self.entries[idx] is Some(entry) else { break }\n if entry.hash == hash && entry.key == key {\n self.remove_entry(entry)\n self.shift_back(idx)\n self.size -= 1\n break\n }\n if i > entry.psl {\n break\n }\n continue i + 1, (idx + 1) & self.capacity_mask\n }\n}\n\n///|\nfn[K, V] Map::add_entry_to_tail(\n self : Map[K, V],\n idx : Int,\n entry : Entry[K, V],\n) -> Unit {\n match self.tail {\n -1 => self.head = Some(entry)\n tail => self.entries[tail].unwrap().next = Some(entry)\n }\n self.tail = idx\n self.entries[idx] = Some(entry)\n self.size += 1\n}\n\n///|\nfn[K, V] Map::remove_entry(self : Map[K, V], entry : Entry[K, V]) -> Unit {\n match entry.prev {\n -1 => self.head = entry.next\n idx => self.entries[idx].unwrap().next = entry.next\n }\n match entry.next {\n None => self.tail = entry.prev\n Some(next) => next.prev = entry.prev\n }\n}\n\n///|\nfn[K, V] Map::shift_back(self : Map[K, V], idx : Int) -> Unit {\n for cur = idx {\n let next = (cur + 1) & self.capacity_mask\n match self.entries[next] {\n None | Some({ psl: 0, .. }) => {\n self.entries[cur] = None\n break\n }\n Some(entry) => {\n entry.psl -= 1\n self.set_entry(entry, cur)\n continue next\n }\n }\n }\n}\n\n///|\nfn[K : Eq, V] Map::grow(self : Map[K, V]) -> Unit {\n let old_head = self.head\n let new_capacity = self.capacity << 1\n self.entries = FixedArray::make(new_capacity, None)\n self.capacity = new_capacity\n self.capacity_mask = new_capacity - 1\n self.grow_at = calc_grow_threshold(self.capacity)\n self.size = 0\n self.head = None\n self.tail = -1\n for x = old_head {\n match x {\n Some({ next, key, value, hash, .. }) => {\n self.set_with_hash(key, value, hash)\n continue next\n }\n None => break\n }\n }\n}\n\n///|\nfn calc_grow_threshold(capacity : Int) -> Int {\n capacity * 13 / 16\n}\n\n// Utils\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl[K : Show, V : Show] Show for Map[K, V]\n\n///|\npub impl[K : Show, V : Show] Show for Map[K, V] with output(self, logger) {\n logger.write_string(\"{\")\n for x = 0, y = self.head {\n match (x, y) {\n (_, None) => break logger.write_string(\"}\")\n (i, Some({ key, value, next, .. })) => {\n if i > 0 {\n logger.write_string(\", \")\n }\n logger.write_object(key)\n logger.write_string(\": \")\n logger.write_object(value)\n continue i + 1, next\n }\n }\n }\n}\n\n///|\n/// Get the number of key-value pairs in the map.\n#alias(size, deprecated)\npub fn[K, V] Map::length(self : Map[K, V]) -> Int {\n self.size\n}\n\n///|\n/// Get the capacity of the map.\npub fn[K, V] Map::capacity(self : Map[K, V]) -> Int {\n self.capacity\n}\n\n///|\n/// Check if the hash map is empty.\npub fn[K, V] Map::is_empty(self : Map[K, V]) -> Bool {\n self.size == 0\n}\n\n///|\n/// Iterate over all key-value pairs of the map in the order of insertion.\n#locals(f)\npub fn[K, V] Map::each(\n self : Map[K, V],\n f : (K, V) -> Unit raise?,\n) -> Unit raise? {\n for x = self.head {\n match x {\n Some({ key, value, next, .. }) => {\n f(key, value)\n continue next\n }\n None => break\n }\n }\n}\n\n///|\n/// Iterate over all key-value pairs of the map in the order of insertion, with index.\n#locals(f)\npub fn[K, V] Map::eachi(\n self : Map[K, V],\n f : (Int, K, V) -> Unit raise?,\n) -> Unit raise? {\n for x = 0, y = self.head {\n match (x, y) {\n (i, Some({ key, value, next, .. })) => {\n f(i, key, value)\n continue i + 1, next\n }\n (_, None) => break\n }\n }\n}\n\n///|\n/// Clears the map, removing all key-value pairs. Keeps the allocated space.\npub fn[K, V] Map::clear(self : Map[K, V]) -> Unit {\n self.entries.fill(None)\n self.size = 0\n self.head = None\n self.tail = -1\n}\n\n///|\n/// Returns the iterator of the hash map, provide elements in the order of insertion.\n#alias(iterator, deprecated)\npub fn[K, V] Map::iter(self : Map[K, V]) -> Iter[(K, V)] {\n let mut curr_entry = self.head\n let len = self.size\n let mut remaining = len\n Iter::new(\n fn() {\n guard remaining > 0 && curr_entry is Some({ key, value, next, .. }) else {\n None\n }\n curr_entry = next\n remaining -= 1\n Some((key, value))\n },\n size_hint=len,\n )\n}\n\n///|\n/// Return an iterator via `iter2`.\n#alias(iterator2, deprecated)\npub fn[K, V] Map::iter2(self : Map[K, V]) -> Iter2[K, V] {\n self.iter()\n}\n\n///|\n/// Return an iterator of keys.\npub fn[K, V] Map::keys(self : Map[K, V]) -> Iter[K] {\n let mut curr_entry = self.head\n let len = self.size\n let mut remaining = len\n Iter::new(\n fn() {\n guard remaining > 0 && curr_entry is Some({ key, next, .. }) else { None }\n curr_entry = next\n remaining -= 1\n Some(key)\n },\n size_hint=len,\n )\n}\n\n///|\n/// Return an iterator of values.\npub fn[K, V] Map::values(self : Map[K, V]) -> Iter[V] {\n let mut curr_entry = self.head\n let len = self.size\n let mut remaining = len\n Iter::new(\n fn() {\n guard remaining > 0 && curr_entry is Some({ value, next, .. }) else {\n None\n }\n curr_entry = next\n remaining -= 1\n Some(value)\n },\n size_hint=len,\n )\n}\n\n///|\n/// Converts the hash map to an array.\npub fn[K, V] Map::to_array(self : Map[K, V]) -> Array[(K, V)] {\n let arr = Array::make_uninit(self.size)\n let mut i = 0\n for x = self.head {\n match x {\n Some({ key, value, next, .. }) => {\n arr.unsafe_set(i, (key, value))\n i += 1\n continue next\n }\n None => break\n }\n }\n arr\n}\n\n///|\npub impl[K : Hash + Eq, V : Eq] Eq for Map[K, V] with equal(\n self : Map[K, V],\n that : Map[K, V],\n) -> Bool {\n guard self.size == that.size else { return false }\n for k, v in self {\n guard that.contains_kv(k, v) else { return false }\n } nobreak {\n true\n }\n}\n\n///|\n/// Function `of`.\n#deprecated(\"Use `Map([(k, v), ...])` or `Map::from_array` instead\")\npub fn[K : Hash + Eq, V] Map::of(arr : FixedArray[(K, V)]) -> Map[K, V] {\n let length = arr.length()\n let m = new_map(capacity_for_length(length))\n // arr.iter((e) => { m.set(e.0, e.1) })\n for e in arr {\n m.set(e.0, e.1)\n }\n m\n}\n\n///|\n/// Create from `iter`.\n#alias(from_iterator, deprecated)\npub fn[K : Hash + Eq, V] Map::from_iter(iter : Iter[(K, V)]) -> Map[K, V] {\n let m = {}\n while iter.next() is Some((k, v)) {\n m.set(k, v)\n }\n m\n}\n\n///|\npub impl[K, V] Default for Map[K, V] with default() {\n new_map(default_init_capacity)\n}\n\n///|\n/// Applies a function to each key-value pair in the map and returns a new map with the results, using the original keys.\npub fn[K, V, V2] Map::map(self : Map[K, V], f : (K, V) -> V2) -> Map[K, V2] {\n // copy structure\n let other = {\n capacity: self.capacity,\n entries: FixedArray::make(self.capacity, None),\n size: self.size,\n capacity_mask: self.capacity_mask,\n grow_at: self.grow_at,\n head: None,\n tail: self.tail,\n }\n if self.size == 0 {\n return other\n }\n guard self.entries[self.tail] is Some(last)\n for entry = last, idx = self.tail, next = (None : Entry[K, V2]?) {\n let { prev, psl, hash, key, value, .. } = entry\n let new_value = f(key, value)\n let new_entry = { prev, next, psl, hash, key, value: new_value }\n other.entries[idx] = Some(new_entry)\n if prev != -1 {\n continue self.entries[prev].unwrap(), prev, Some(new_entry)\n } else {\n other.head = Some(new_entry)\n break\n }\n }\n other\n}\n\n///|\n/// Copy the map, creating a new map with the same key-value pairs and order of insertion.\n#alias(clone, deprecated)\npub fn[K, V] Map::copy(self : Map[K, V]) -> Map[K, V] {\n // copy structure\n let other = {\n capacity: self.capacity,\n entries: FixedArray::make(self.capacity, None),\n size: self.size,\n capacity_mask: self.capacity_mask,\n grow_at: self.grow_at,\n head: None,\n tail: self.tail,\n }\n if self.size == 0 {\n return other\n }\n guard self.entries[self.tail] is Some(last)\n for entry = last, idx = self.tail, next = (None : Entry[K, V]?) {\n let { prev, psl, hash, key, value, .. } = entry\n let new_entry = { prev, next, psl, hash, key, value }\n other.entries[idx] = Some(new_entry)\n if prev != -1 {\n continue self.entries[prev].unwrap(), prev, Some(new_entry)\n } else {\n other.head = Some(new_entry)\n break\n }\n }\n other\n}\n\n///|\n/// Merges two maps into a new map. Returns a new map containing all key-value\n/// pairs from both maps. When both maps contain the same key, the value from\n/// `other` takes precedence. The iteration order follows the order of `self`\n/// followed by new entries from `other`.\n///\n/// This is a pure operation - it does not modify either of the input maps.\n///\n/// Parameters:\n///\n/// * `self` : The first map.\n/// * `other` : The second map whose values take precedence in case of key\n/// conflicts.\n///\n/// Returns a new linked hash map containing all entries from both maps.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map1 : Map[String, Int] = { \"a\": 1, \"b\": 2 }\n/// let map2 : Map[String, Int] = { \"b\": 3, \"c\": 4 }\n/// let merged = map1.merge(map2)\n/// @json.json_inspect(merged, content={ \"a\": 1, \"b\": 3, \"c\": 4 })\n/// }\n/// ```\npub fn[K : Eq, V] Map::merge(self : Map[K, V], other : Map[K, V]) -> Map[K, V] {\n let result = self.copy()\n result.merge_in_place(other)\n result\n}\n\n///|\n/// Merges another map into this map in-place. Updates the current map by adding\n/// all key-value pairs from `other`. When both maps contain the same key, the\n/// value from `other` overwrites the value in this map. New entries from `other`\n/// are added at the end, preserving the original order of `self` and appending\n/// new keys from `other`.\n///\n/// This is a mutating operation - it modifies the receiver map.\n///\n/// Parameters:\n///\n/// * `self` : The map to be modified.\n/// * `other` : The map whose entries will be added to `self`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map1 : Map[String, Int] = { \"a\": 1, \"b\": 2 }\n/// let map2 : Map[String, Int] = { \"b\": 3, \"c\": 4 }\n/// map1.merge_in_place(map2)\n/// @json.json_inspect(map1, content={ \"a\": 1, \"b\": 3, \"c\": 4 })\n/// }\n/// ```\npub fn[K : Eq, V] Map::merge_in_place(\n self : Map[K, V],\n other : Map[K, V],\n) -> Unit {\n if physical_equal(self, other) {\n return\n }\n for x = other.head {\n match x {\n Some({ key, value, next, hash, .. }) => {\n self.set_with_hash(key, value, hash)\n continue next\n }\n None => break\n }\n }\n}\n\n///|\n/// Retains only the key-value pairs that satisfy the given predicate function.\n/// This method modifies the map in-place, removing all entries for which\n/// the predicate returns `false`. The order of remaining elements is preserved.\n///\n/// Parameters:\n///\n/// * `self` : The map to be filtered.\n/// * `predicate` : A function that takes a key and value as arguments and returns\n/// `true` if the key-value pair should be kept, `false` if it should be removed.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4 }\n/// map.retain((_k, v) => v % 2 == 0) // Keep only even values\n/// inspect(map.length(), content=\"2\")\n/// debug_inspect(map.get(\"a\"), content=\"None\")\n/// debug_inspect(map.get(\"b\"), content=\"Some(2)\")\n/// debug_inspect(map.get(\"c\"), content=\"None\")\n/// debug_inspect(map.get(\"d\"), content=\"Some(4)\")\n/// }\n/// ```\n#locals(f)\npub fn[K, V] Map::retain(self : Map[K, V], f : (K, V) -> Bool) -> Unit {\n for x = self.head, y = false {\n match (x, y) {\n (Some({ key, value, next, prev: idx, .. }), remove_prev) => {\n if remove_prev {\n guard self.entries[idx] is Some(entry)\n self.remove_entry(entry)\n self.shift_back(idx)\n self.size -= 1\n }\n continue next, !f(key, value)\n }\n (None, remove_prev) => {\n if remove_prev {\n let idx = self.tail\n guard self.entries[idx] is Some(entry)\n self.remove_entry(entry)\n self.shift_back(idx)\n self.size -= 1\n }\n break\n }\n }\n }\n}\n\n///|\n/// Updates a value in the map based on the existing value.\n///\n/// This method allows you to conditionally update, insert, or remove a key-value pair\n/// based on whether the key already exists in the map. The provided function `f` is\n/// called with `Some(current_value)` if the key exists, or `None` if it doesn't.\n///\n/// Parameters:\n///\n/// * `self` : The map to update.\n/// * `key` : The key to update.\n/// * `f` : A function that takes the current value (wrapped in `Option`) and returns\n/// the new value (wrapped in `Option`). Returning `None` will remove the key-value\n/// pair from the map.\n///\n/// Behavior:\n///\n/// * If the key exists and `f` returns `Some(new_value)`, the value is updated.\n/// * If the key exists and `f` returns `None`, the key-value pair is removed.\n/// * If the key doesn't exist and `f` returns `Some(new_value)`, a new pair is inserted.\n/// * If the key doesn't exist and `f` returns `None`, no operation is performed.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"a\": 1, \"b\": 2 }\n///\n/// // Update existing value\n/// map.update(\"a\", fn(v) {\n/// match v {\n/// Some(x) => Some(x + 10)\n/// None => Some(0)\n/// }\n/// })\n/// debug_inspect(\n/// map,\n/// content=(\n/// #|{ \"a\": 11, \"b\": 2 }\n/// ),\n/// )\n///\n/// // Insert new value\n/// map.update(\"c\", fn(v) {\n/// match v {\n/// Some(x) => Some(x)\n/// None => Some(3)\n/// }\n/// })\n/// debug_inspect(\n/// map,\n/// content=(\n/// #|{ \"a\": 11, \"b\": 2, \"c\": 3 }\n/// ),\n/// )\n///\n/// // Remove existing value\n/// map.update(\"b\", fn(_) { None })\n/// debug_inspect(\n/// map,\n/// content=(\n/// #|{ \"a\": 11, \"c\": 3 }\n/// ),\n/// )\n/// }\n/// ```\npub fn[K : Hash + Eq, V] Map::update(\n self : Map[K, V],\n key : K,\n f : (V?) -> V?,\n) -> Unit {\n let hash = key.hash()\n let (idx, psl, new_value, push_away) = for psl = 0, idx = hash &\n self.capacity_mask {\n match self.entries[idx] {\n Some(entry) => {\n if entry.hash == hash && entry.key == key {\n // Found the entry, update its value\n if f(Some(entry.value)) is Some(new_value) {\n entry.value = new_value\n } else {\n // Remove the entry since the new value is None\n self.remove_entry(entry)\n self.shift_back(idx)\n self.size -= 1\n }\n return\n }\n if psl > entry.psl {\n guard f(None) is Some(new_value) else { return }\n break (idx, psl, new_value, Some(entry))\n }\n continue psl + 1, (idx + 1) & self.capacity_mask\n }\n None => {\n guard f(None) is Some(new_value) else { return }\n break (idx, psl, new_value, None)\n }\n }\n }\n if self.size >= self.grow_at {\n // Slow path, we need to resize\n self.grow()\n self.set(key, new_value)\n } else {\n if push_away is Some(entry) {\n self.push_away(idx, entry)\n }\n let entry = {\n prev: self.tail,\n next: None,\n psl,\n hash,\n key,\n value: new_value,\n }\n self.add_entry_to_tail(idx, entry)\n }\n}\n\n// Special handling for Views as accessors\n\n///|\n/// Retrieves the value associated with a `BytesView` key in a map with `Bytes` keys.\n///\n/// This function allows efficient lookups using `BytesView` without creating a new `Bytes` object.\n/// It's particularly useful when working with byte slices or subranges of existing byte arrays.\n///\n/// Parameters:\n///\n/// * `map` : The hash map with `Bytes` keys to search in.\n/// * `key` : A `BytesView` representing the key to look up.\n///\n/// Returns `Some(value)` if a matching key exists in the map, `None` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { b\"hello\": 1, b\"world\": 2 }\n/// let bytes = b\"prefix_hello_suffix\"\n/// let view = bytes[7:12] // view of \"hello\"\n/// debug_inspect(map.get_from_bytes(view), content=\"Some(1)\")\n/// }\n/// ```\npub fn[V] Map::get_from_bytes(map : Self[Bytes, V], key : BytesView) -> V? {\n let hash = key.hash()\n for i = 0, idx = hash & map.capacity_mask {\n guard map.entries[idx] is Some(entry) else { break None }\n if entry.hash == hash && key.equal_to_bytes(entry.key) {\n break Some(entry.value)\n }\n if i > entry.psl {\n break None\n }\n continue i + 1, (idx + 1) & map.capacity_mask\n }\n}\n\n///|\n/// Retrieves the value associated with a `StringView` key in a map with `String` keys.\n///\n/// This function allows efficient lookups using `StringView` without creating a new `String` object.\n/// It's particularly useful when working with substrings or string slices.\n///\n/// Parameters:\n///\n/// * `map` : The hash map with `String` keys to search in.\n/// * `key` : A `StringView` representing the key to look up.\n///\n/// Returns `Some(value)` if a matching key exists in the map, `None` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let map = { \"hello\": 1, \"world\": 2 }\n/// let str = \"say hello to everyone\"\n/// let view = str.view(start_offset=4, end_offset=9) // view of \"hello\"\n/// debug_inspect(map.get_from_string(view), content=\"Some(1)\")\n/// }\n/// ```\npub fn[V] Map::get_from_string(map : Self[String, V], key : StringView) -> V? {\n let hash = key.hash()\n for i = 0, idx = hash & map.capacity_mask {\n guard map.entries[idx] is Some(entry) else { break None }\n if entry.hash == hash && key.equal_to_string(entry.key) {\n break Some(entry.value)\n }\n if i > entry.psl {\n break None\n }\n continue i + 1, (idx + 1) & map.capacity_mask\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Returns the smallest power of two greater than or equal to `self`.\n/// This function will panic if `self` is negative. For values greater than\n/// the largest representable power of two (2^30 = 1073741824), it returns\n/// the largest representable power of two.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0).next_power_of_two(), content=\"1\")\n/// inspect((1).next_power_of_two(), content=\"1\")\n/// inspect((2).next_power_of_two(), content=\"2\")\n/// inspect((3).next_power_of_two(), content=\"4\")\n/// inspect((8).next_power_of_two(), content=\"8\")\n/// inspect((1073741824).next_power_of_two(), content=\"1073741824\")\n/// inspect((2000000000).next_power_of_two(), content=\"1073741824\")\n/// }\n/// ```\npub fn Int::next_power_of_two(self : Int) -> Int {\n guard self >= 0\n if self <= 1 {\n return 1\n }\n // The largest power of 2 that fits in a 32-bit signed integer is 2^30\n let max_power_of_two = 1073741824 // 2^30\n if self > max_power_of_two {\n return max_power_of_two\n }\n // 2147483647 is the largest value of an integer\n (2147483647 >> ((self - 1).clz() - 1)) + 1\n}\n\n///|\n/// Returns the minimum of two integers.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((1).min(2), content=\"1\")\n/// inspect((2).min(1), content=\"1\")\n/// }\n/// ```\npub fn Int::min(self : Int, other : Int) -> Int {\n if self < other {\n self\n } else {\n other\n }\n}\n\n///|\n/// Returns the maximum of two integers.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((1).max(2), content=\"2\")\n/// inspect((2).max(1), content=\"2\")\n/// }\n/// ```\npub fn Int::max(self : Int, other : Int) -> Int {\n if self > other {\n self\n } else {\n other\n }\n}\n\n///|\n/// Clamps the value `self` between `min` and `max`.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((1).clamp(min=0, max=2), content=\"1\")\n/// inspect((-1).clamp(min=0, max=2), content=\"0\")\n/// inspect((3).clamp(min=0, max=2), content=\"2\")\n/// inspect((-1).clamp(min=0, max=2), content=\"0\")\n/// }\n/// ```\npub fn Int::clamp(self : Int, min~ : Int, max~ : Int) -> Int {\n guard min <= max\n if self < min {\n min\n } else if self > max {\n max\n } else {\n self\n }\n}\n\n///|\n/// Checks if the integer value represents a UTF-16 leading surrogate.\n/// Leading surrogates are in the range 0xD800 to 0xDBFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xD800).is_leading_surrogate(), content=\"true\")\n/// inspect((0xDBFF).is_leading_surrogate(), content=\"true\")\n/// inspect((0xDC00).is_leading_surrogate(), content=\"false\")\n/// inspect((0x41).is_leading_surrogate(), content=\"false\") // 'A'\n/// }\n/// ```\npub fn Int::is_leading_surrogate(self : Int) -> Bool {\n 0xD800 <= self && self <= 0xDBFF\n}\n\n///|\n/// Checks if the integer value represents a UTF-16 trailing surrogate.\n/// Trailing surrogates are in the range 0xDC00 to 0xDFFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xDC00).is_trailing_surrogate(), content=\"true\")\n/// inspect((0xDFFF).is_trailing_surrogate(), content=\"true\")\n/// inspect((0xD800).is_trailing_surrogate(), content=\"false\")\n/// inspect((0x41).is_trailing_surrogate(), content=\"false\") // 'A'\n/// }\n/// ```\npub fn Int::is_trailing_surrogate(self : Int) -> Bool {\n 0xDC00 <= self && self <= 0xDFFF\n}\n\n///|\n/// Checks if the integer value represents any UTF-16 surrogate (leading or trailing).\n/// Surrogates are in the range 0xD800 to 0xDFFF.\n///\n/// Example:\n/// ```mbt check\n/// test {\n/// inspect((0xD800).is_surrogate(), content=\"true\") // leading surrogate\n/// inspect((0xDC00).is_surrogate(), content=\"true\") // trailing surrogate\n/// inspect((0xDFFF).is_surrogate(), content=\"true\") // trailing surrogate\n/// inspect((0x41).is_surrogate(), content=\"false\") // 'A'\n/// inspect((0x1F600).is_surrogate(), content=\"false\") // 😀 emoji codepoint\n/// }\n/// ```\npub fn Int::is_surrogate(self : Int) -> Bool {\n 0xD800 <= self && self <= 0xDFFF\n}\n\n///|\n/// Computes the absolute value of an integer.\n///\n/// Parameters:\n///\n/// * `self` : The integer whose absolute value is to be computed.\n///\n/// Returns the absolute value of the integer.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(Int::abs(42), content=\"42\")\n/// inspect(Int::abs(-42), content=\"42\")\n/// inspect(Int::abs(0), content=\"0\")\n/// }\n/// ```\npub fn Int::abs(self : Int) -> Int {\n if self < 0 {\n -self\n } else {\n self\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Creates a new dynamic array from a fixed-size array.\n///\n/// Parameters:\n///\n/// * `arr` : The fixed-size array to convert. The elements of this array will be\n/// copied to the new array.\n///\n/// Returns a new dynamic array containing all elements from the input fixed-size\n/// array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let fixed = FixedArray::make(3, 42)\n/// let dynamic = Array::from_fixed_array(fixed)\n/// debug_inspect(dynamic, content=\"[42, 42, 42]\")\n/// }\n/// ```\npub fn[T] Array::from_fixed_array(arr : FixedArray[T]) -> Array[T] {\n let len = arr.length()\n let arr2 = Array::make_uninit(len)\n UninitializedArray::unsafe_blit_fixed(arr2.buffer(), 0, arr, 0, len)\n arr2\n}\n\n///|\n/// Creates a new array with a specified length and initializes all elements with\n/// the given value.\n///\n/// Parameters:\n///\n/// * `length` : The length of the array to create. Must be a non-negative\n/// integer.\n/// * `initial_value` : The value used to initialize all elements in the array.\n///\n/// Returns a new array of type `Array[T]` with `length` elements, where each\n/// element is initialized to `initial_value`.\n///\n/// Throws an error if `length` is negative.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = Array::make(3, 42)\n/// debug_inspect(arr, content=\"[42, 42, 42]\")\n/// }\n/// ```\n///\n/// WARNING: A common pitfall is creating with the same initial value, for example:\n/// ```mbt check\n/// test {\n/// let two_dimension_array = Array::make(10, Array::make(10, 0))\n/// two_dimension_array[0][5] = 10\n/// assert_eq(two_dimension_array[5][5], 10)\n/// }\n/// ```\n/// This is because all the cells reference to the same object (the Array[Int] in this case).\n/// One should use makei() instead which creates an object for each index.\npub fn[T] Array::make(len : Int, elem : T) -> Array[T] {\n let arr = Array::make_uninit(len)\n for i in 0..<len {\n arr.unsafe_set(i, elem)\n }\n arr\n}\n\n///|\n/// Creates a new array of the specified length, where each element is\n/// initialized using an index-based initialization function.\n///\n/// Parameters:\n///\n/// * `length` : The length of the new array. If `length` is less than or equal\n/// to 0, returns an empty array.\n/// * `initializer` : A function that takes an index (starting from 0) and\n/// returns a value of type `T`. This function is called for each index to\n/// initialize the corresponding element.\n///\n/// Returns a new array of type `Array[T]` with the specified length, where each\n/// element is initialized using the provided function.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = Array::makei(3, i => i * 2)\n/// debug_inspect(arr, content=\"[0, 2, 4]\")\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::makei(length : Int, f : (Int) -> T raise?) -> Array[T] raise? {\n if length <= 0 {\n []\n } else {\n let array = Array::make_uninit(length)\n for i in 0..<length {\n array.unsafe_set(i, f(i))\n }\n array\n }\n}\n\n///|\n/// Returns the total capacity of the array, which is the number of elements that\n/// the array can hold without requiring reallocation of its internal buffer.\n///\n/// Parameters:\n///\n/// * `array` : The array whose capacity is to be determined.\n///\n/// Returns the current capacity of the array as an integer.\n///\n/// NOTE: The capacity of an array may not be consistent across different backends\n/// and/or different versions of the MoonBit compiler/core.\npub fn[T] Array::capacity(self : Array[T]) -> Int {\n self.buffer().0.length()\n}\n\n///|\n/// Retrieves the element at the specified index from an array without bounds\n/// checking.\n///\n/// Parameters:\n///\n/// * `array` : The array from which to retrieve the element.\n/// * `index` : The position in the array from which to retrieve the element.\n///\n/// Returns the element at the specified index.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// inspect(arr.unsafe_get(1), content=\"2\")\n/// }\n/// ```\n///\n#intrinsic(\"%array.unsafe_get\")\npub fn[T] Array::unsafe_get(self : Array[T], idx : Int) -> T {\n self.buffer()[idx]\n}\n\n///|\n/// Retrieves an element from the array at the specified index.\n///\n/// Parameters:\n///\n/// * `array` : The array to get the element from.\n/// * `index` : The position in the array from which to retrieve the element.\n///\n/// Returns the element at the specified index.\n///\n/// Throws a panic if the index is negative or greater than or equal to the\n/// length of the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// inspect(arr[1], content=\"2\")\n/// }\n/// ```\n///\n#intrinsic(\"%array.get\")\n#alias(\"_[_]\")\npub fn[T] Array::at(self : Array[T], index : Int) -> T {\n let len = self.length()\n guard index >= 0 && index < len\n self.buffer()[index]\n}\n\n///|\n/// Retrieves the element at the specified index from the array.\n///\n/// Parameters:\n///\n/// * `self` : The array to get the element from.\n/// * `index` : The position in the array from which to retrieve the element.\n///\n/// Returns `Some(element)` if the index is within bounds, or `None` if the index\n/// is out of bounds.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// debug_inspect(arr.get(-1), content=\"None\")\n/// debug_inspect(arr.get(0), content=\"Some(1)\")\n/// debug_inspect(arr.get(3), content=\"None\")\n/// }\n/// ```\npub fn[T] Array::get(self : Array[T], index : Int) -> T? {\n let len = self.length()\n guard index >= 0 && index < len else { None }\n Some(self.unsafe_get(index))\n}\n\n///|\n/// Write `val` to `idx` without bounds checking.\n///\n/// This is unsafe: caller must ensure `0 <= idx < self.length()`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// arr.unsafe_set(1, 99)\n/// debug_inspect(arr, content=\"[1, 99, 3]\")\n/// }\n/// ```\n#intrinsic(\"%array.unsafe_set\")\npub fn[T] Array::unsafe_set(self : Array[T], idx : Int, val : T) -> Unit {\n self.buffer()[idx] = val\n}\n\n///|\n/// Sets the element at the specified index in the array to a new value. The\n/// original value at that index is overwritten.\n///\n/// Parameters:\n///\n/// * `array` : The array to modify.\n/// * `index` : The position in the array where the value will be set.\n/// * `value` : The new value to assign at the specified index.\n///\n/// Throws an error if `index` is negative or greater than or equal to the length\n/// of the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// arr[1] = 42\n/// debug_inspect(arr, content=\"[1, 42, 3]\")\n/// }\n/// ```\n///\n#intrinsic(\"%array.set\")\n#alias(\"_[_]=_\")\npub fn[T] Array::set(self : Array[T], index : Int, value : T) -> Unit {\n let len = self.length()\n guard index >= 0 && index < len\n self.buffer()[index] = value\n}\n\n///|\n/// Compares two arrays for equality. Returns true if both arrays have the same\n/// length and contain equal elements in the same order.\n///\n/// Parameters:\n///\n/// * `self` : The first array to compare.\n/// * `other` : The second array to compare.\n///\n/// Returns true if the arrays are equal, false otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr1 = [1, 2, 3]\n/// let arr2 = [1, 2, 3]\n/// let arr3 = [1, 2, 4]\n/// inspect(arr1 == arr2, content=\"true\")\n/// inspect(arr1 == arr3, content=\"false\")\n/// }\n/// ```\npub impl[T : Eq] Eq for Array[T] with equal(self, other) {\n let self_len = self.length()\n let other_len = other.length()\n guard self_len == other_len else { return false }\n for i in 0..<self_len {\n guard self.unsafe_get(i) == other.unsafe_get(i) else { break false }\n } nobreak {\n true\n }\n}\n\n///|\npub impl[T : Hash] Hash for Array[T] with hash_combine(self, hasher) {\n for v in self {\n v.hash_combine(hasher)\n }\n}\n\n///|\n/// Compares two arrays based on shortlex order.\n///\n/// First compares the lengths of the arrays. If they differ, returns -1 if the\n/// first array is shorter, 1 if it's longer. If the lengths are equal, compares\n/// elements pairwise until a difference is found or all elements have been\n/// compared.\n///\n/// Parameters:\n///\n/// * `self` : The first array to compare.\n/// * `other` : The second array to compare.\n///\n/// Returns an integer that indicates the relative order:\n///\n/// * A negative value if `self` is less than `other`\n/// * Zero if `self` equals `other`\n/// * A positive value if `self` is greater than `other`\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr1 = [1, 2, 3]\n/// let arr2 = [1, 2, 4]\n/// let arr3 = [1, 2]\n/// inspect(arr1.compare(arr2), content=\"-1\") // arr1 < arr2\n/// inspect(arr2.compare(arr1), content=\"1\") // arr2 > arr1\n/// inspect(arr1.compare(arr3), content=\"1\") // arr1 > arr3 (longer)\n/// inspect(arr1.compare(arr1), content=\"0\") // arr1 = arr1\n/// }\n/// ```\npub impl[T : Compare] Compare for Array[T] with compare(self, other) {\n let len_self = self.length()\n let len_other = other.length()\n let cmp = len_self.compare(len_other)\n guard cmp is 0 else { return cmp }\n for i in 0..<len_self {\n let cmp = self.unsafe_get(i).compare(other.unsafe_get(i))\n guard cmp is 0 else { break cmp }\n } nobreak {\n 0\n }\n}\n\n///|\n/// Concatenates two arrays into a new array. The resulting array contains all\n/// elements from the first array followed by all elements from the second array.\n///\n/// Parameters:\n///\n/// * `self` : The first array to concatenate.\n/// * `other` : The second array to concatenate.\n///\n/// Returns a new array containing all elements from both arrays in order.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let a = [1, 2, 3]\n/// let b = [4, 5]\n/// debug_inspect(a + b, content=\"[1, 2, 3, 4, 5]\")\n/// }\n/// ```\npub impl[T] Add for Array[T] with add(self, other) {\n let result = Array::make_uninit(self.length() + other.length())\n UninitializedArray::unsafe_blit(\n result.buffer(),\n 0,\n self.buffer(),\n 0,\n self.length(),\n )\n UninitializedArray::unsafe_blit(\n result.buffer(),\n self.length(),\n other.buffer(),\n 0,\n other.length(),\n )\n result\n}\n\n///|\n/// Appends all elements from one array to the end of another array. The elements\n/// are added in-place, modifying the original array.\n///\n/// Parameters:\n///\n/// * `self` : The array to append to.\n/// * `other` : The array whose elements will be appended.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let v1 = [1, 2, 3]\n/// let v2 = [4, 5, 6]\n/// v1.append(v2)\n/// debug_inspect(v1, content=\"[1, 2, 3, 4, 5, 6]\")\n/// let v1 = [1, 2, 3]\n/// let v2 : Array[Int] = []\n/// v1.append(v2)\n/// debug_inspect(v1, content=\"[1, 2, 3]\")\n/// }\n/// ```\npub fn[T] Array::append(self : Array[T], other : ArrayView[T]) -> Unit {\n other.blit_to(self, dst_offset=self.length())\n}\n\n///|\n/// Iterates through each element of the array in order, applying the given\n/// function to each element.\n///\n/// Parameters:\n///\n/// * `array` : The array to iterate over.\n/// * `function` : A function that takes a single element of type `T` as input\n/// and returns `Unit`. This function is applied to each element of the array in\n/// order.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// let mut sum = 0\n/// arr.each(x => sum = sum + x)\n/// inspect(sum, content=\"6\")\n/// }\n/// ```\n/// This method uses the array iterator. Structural mutations during traversal\n/// are unsupported: appended elements are not visited, and shrinking the array\n/// with operations such as `remove`, `truncate`, `clear`, or `drain` may cause\n/// later iterator steps to fail.\n#locals(f)\npub fn[T] Array::each(self : Array[T], f : (T) -> Unit raise?) -> Unit raise? {\n for v in self {\n f(v)\n }\n}\n\n///|\n/// Iterates over the elements of the array in reverse order, applying the given\n/// function to each element.\n///\n/// Parameters:\n///\n/// * `array` : The array to iterate over.\n/// * `f` : A function that takes an element of type `T` and returns `Unit`. This\n/// function is applied to each element of the array in reverse order.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let mut sum = 0\n/// v.rev_each(x => sum = sum - x)\n/// @json.json_inspect(sum, content=-12)\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::rev_each(\n self : Array[T],\n f : (T) -> Unit raise?,\n) -> Unit raise? {\n let len = self.length()\n for i in 0..<len {\n f(self[len - i - 1])\n }\n}\n\n///|\n/// Iterates over the elements of the array with index in reversed order.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let mut sum = 0\n/// v.rev_eachi((i, x) => sum = sum + x + i)\n/// assert_eq(sum, 15)\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::rev_eachi(\n self : Array[T],\n f : (Int, T) -> Unit raise?,\n) -> Unit raise? {\n let len = self.length()\n for i in 0..<len {\n f(i, self[len - i - 1])\n }\n}\n\n///|\n/// Iterates over the elements of the array with index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let mut sum = 0\n/// v.eachi((i, x) => sum = sum + x + i)\n/// inspect(sum, content=\"15\")\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::eachi(\n self : Array[T],\n f : (Int, T) -> Unit raise?,\n) -> Unit raise? {\n for i, v in self {\n f(i, v)\n }\n}\n\n///|\n/// Checks whether all elements satisfy the predicate.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// assert_true(arr.all(x => x < 6))\n/// assert_false(arr.all(x => x < 5))\n/// }\n/// ```\n#alias(every)\npub fn[T] Array::all(self : Array[T], f : (T) -> Bool raise?) -> Bool raise? {\n self[:].all(f)\n}\n\n///|\n/// Checks whether any element satisfies the predicate.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// assert_true(arr.any(x => x < 6))\n/// assert_false(arr.any(x => x < 1))\n/// }\n/// ```\n#alias(exists)\npub fn[T] Array::any(self : Array[T], f : (T) -> Bool raise?) -> Bool raise? {\n self[:].any(f)\n}\n\n///|\n/// Clears the array, removing all values.\n///\n/// This method has no effect on the allocated capacity of the array, only setting the length to 0.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// v.clear()\n/// assert_eq(v.length(), 0)\n/// }\n/// ```\npub fn[T] Array::clear(self : Array[T]) -> Unit {\n self.unsafe_truncate_to_length(0)\n}\n\n///|\n/// Maps a function over the elements of the array.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let v2 = v.map(x => x + 1)\n/// assert_eq(v2, [4, 5, 6])\n/// }\n/// ```\n#locals(f)\npub fn[T, U] Array::map(\n self : Array[T],\n f : (T) -> U raise?,\n) -> Array[U] raise? {\n let arr = Array::make_uninit(self.length())\n for i, v in self {\n arr.unsafe_set(i, f(v))\n }\n arr\n}\n\n///|\n/// Maps a function over the elements of the array in place.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// v.map_in_place(x => x + 1)\n/// assert_eq(v, [4, 5, 6])\n/// }\n/// ```\n#locals(f)\n#alias(map_inplace, deprecated)\npub fn[T] Array::map_in_place(\n self : Array[T],\n f : (T) -> T raise?,\n) -> Unit raise? {\n for i, v in self {\n self[i] = f(v)\n }\n}\n\n///|\n/// Maps a function over the elements of the array with index.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let v2 = v.mapi((i, x) => x + i)\n/// assert_eq(v2, [3, 5, 7])\n/// }\n/// ```\n#locals(f)\npub fn[T, U] Array::mapi(\n self : Array[T],\n f : (Int, T) -> U raise?,\n) -> Array[U] raise? {\n if self.is_empty() {\n return []\n }\n let arr = Array::make_uninit(self.length())\n for i, v in self {\n arr.unsafe_set(i, f(i, v))\n }\n arr\n}\n\n///|\n/// Maps a function over the elements of the array with index in place.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// v.mapi_in_place((i, x) => x + i)\n/// assert_eq(v, [3, 5, 7])\n/// }\n/// ```\n#locals(f)\n#alias(mapi_inplace, deprecated)\npub fn[T] Array::mapi_in_place(\n self : Array[T],\n f : (Int, T) -> T raise?,\n) -> Unit raise? {\n for i, v in self {\n self[i] = f(i, v)\n }\n}\n\n///|\n/// Creates a new array containing all elements from the input array that satisfy\n/// the given predicate function.\n///\n/// Parameters:\n///\n/// * `array` : The array to filter.\n/// * `predicate` : A function that takes an element and returns a boolean\n/// indicating whether the element should be included in the result.\n///\n/// Returns a new array containing only the elements for which the predicate\n/// function returns `true`. The relative order of the elements is preserved.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// let evens = arr.filter(x => x % 2 == 0)\n/// debug_inspect(evens, content=\"[2, 4]\")\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::filter(\n self : Array[T],\n f : (T) -> Bool raise?,\n) -> Array[T] raise? {\n let arr = []\n for v in self {\n if f(v) {\n arr.push(v)\n }\n }\n arr\n}\n\n///|\n/// Tests whether the array contains no elements.\n///\n/// Parameters:\n///\n/// * `array` : The array to check.\n///\n/// Returns `true` if the array has no elements, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let empty : Array[Int] = []\n/// inspect(empty.is_empty(), content=\"true\")\n/// let non_empty = [1, 2, 3]\n/// inspect(non_empty.is_empty(), content=\"false\")\n/// }\n/// ```\npub fn[T] Array::is_empty(self : Array[T]) -> Bool {\n self.length() == 0\n}\n\n///|\n/// Reverses the order of elements in an array in place, modifying the original\n/// array.\n///\n/// Parameters:\n///\n/// * `self` : The array to be reversed.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.rev_in_place()\n/// debug_inspect(arr, content=\"[5, 4, 3, 2, 1]\")\n/// let arr : Array[Int] = []\n/// arr.rev_in_place()\n/// debug_inspect(arr, content=\"[]\")\n/// }\n/// ```\n#alias(rev_inplace, deprecated)\npub fn[T] Array::rev_in_place(self : Array[T]) -> Unit {\n let len = self.length()\n for i in 0..<(len / 2) {\n let temp = self.unsafe_get(i)\n self.unsafe_set(i, self.unsafe_get(len - i - 1))\n self.unsafe_set(len - i - 1, temp)\n }\n}\n\n///|\n/// Creates a new array with elements in reversed order.\n///\n/// Parameters:\n///\n/// * `self` : The array to be reversed.\n///\n/// Returns a new array containing the same elements as the input array but in\n/// reverse order. The original array remains unchanged.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// debug_inspect(arr.rev(), content=\"[5, 4, 3, 2, 1]\")\n/// debug_inspect(arr, content=\"[1, 2, 3, 4, 5]\") // original array unchanged\n/// }\n/// ```\npub fn[T] Array::rev(self : Array[T]) -> Array[T] {\n let len = self.length()\n let arr = Array::make_uninit(len)\n for i in 0..<len {\n arr.unsafe_set(i, self.unsafe_get(len - i - 1))\n }\n arr\n}\n\n///|\n/// Split the array into two at the given index.\n/// This function will panic if the index is out of bounds.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let (v1, v2) = (v[:1], v[1:])\n/// assert_eq(v1, [3])\n/// assert_eq(v2, [4, 5])\n/// }\n/// ```\n#deprecated(\"Use ArrayView instead, e.g, (a[:index], a[index:])\")\n#doc(hidden)\npub fn[T] Array::split_at(self : Array[T], index : Int) -> (Array[T], Array[T]) {\n if index < 0 || index > self.length() {\n let len = self.length()\n abort(\n \"index out of bounds: the len is from 0 to \\{len} but the index is \\{index}\",\n )\n }\n let v1 = Array::make_uninit(index)\n let v2 = Array::make_uninit(self.length() - index)\n UninitializedArray::unsafe_blit(v1.buffer(), 0, self.buffer(), 0, index)\n if index != self.length() {\n UninitializedArray::unsafe_blit(\n v2.buffer(),\n 0,\n self.buffer(),\n index,\n self.length() - index,\n )\n }\n (v1, v2)\n}\n\n///|\n/// Checks whether the array contains an element equal to the given value.\n///\n/// Parameters:\n///\n/// * `array` : The array to search in.\n/// * `value` : The value to search for.\n///\n/// Returns `true` if the array contains an element equal to the given value,\n/// `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// inspect(arr.contains(3), content=\"true\")\n/// inspect(arr.contains(6), content=\"false\")\n/// let arr : Array[Int] = []\n/// inspect(arr.contains(1), content=\"false\")\n/// }\n/// ```\npub fn[T : Eq] Array::contains(self : Array[T], value : T) -> Bool {\n for v in self {\n if v == value {\n break true\n }\n } nobreak {\n false\n }\n}\n\n///|\n/// Checks if the array begins with all elements of the provided prefix array in\n/// order.\n///\n/// Parameters:\n///\n/// * `self` : The array to check against.\n/// * `prefix` : The array containing the sequence of elements to look for at the\n/// beginning.\n///\n/// Returns `true` if the array starts with all elements in `prefix` in the same\n/// order, `false` otherwise. An empty prefix array always returns `true`, and a\n/// prefix longer than the array always returns `false`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// inspect(arr.starts_with([1, 2]), content=\"true\")\n/// inspect(arr.starts_with([2, 3]), content=\"false\")\n/// inspect(arr.starts_with([]), content=\"true\")\n/// inspect(arr.starts_with([1, 2, 3, 4, 5, 6]), content=\"false\")\n/// }\n/// ```\npub fn[T : Eq] Array::starts_with(\n self : Array[T],\n prefix : ArrayView[T],\n) -> Bool {\n self[:].starts_with(prefix)\n}\n\n///|\n/// Tests if an array ends with the given suffix.\n///\n/// Parameters:\n///\n/// * `self` : The array to check.\n/// * `suffix` : The array to test against.\n///\n/// Returns `true` if the array ends with the given suffix, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// inspect(arr.ends_with([4, 5]), content=\"true\")\n/// inspect(arr.ends_with([3, 4]), content=\"false\")\n/// inspect(arr.ends_with([]), content=\"true\")\n/// let arr : Array[Int] = []\n/// inspect(arr.ends_with([]), content=\"true\")\n/// inspect(arr.ends_with([1]), content=\"false\")\n/// }\n/// ```\npub fn[T : Eq] Array::ends_with(self : Array[T], suffix : ArrayView[T]) -> Bool {\n self[:].ends_with(suffix)\n}\n\n///|\n/// Strip a prefix from the array.\n///\n/// If the array starts with the prefix, return a view of the array after the\n/// prefix, otherwise return None. The returned view shares the original\n/// backing array — no allocation.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [1, 2, 3, 4, 5]\n/// let v2 = v.strip_prefix([1, 2][:])\n/// debug_inspect(\n/// v2,\n/// content=(\n/// #|Some(<ArrayView: [3, 4, 5]>)\n/// ),\n/// )\n/// }\n/// ```\npub fn[T : Eq] Array::strip_prefix(\n self : Array[T],\n prefix : ArrayView[T],\n) -> ArrayView[T]? {\n self[:].strip_prefix(prefix)\n}\n\n///|\n/// Strip a suffix from the array.\n///\n/// If the array ends with the suffix, return a view of the array before the\n/// suffix, otherwise return None. The returned view shares the original\n/// backing array — no allocation.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let v2 = v.strip_suffix([5][:])\n/// debug_inspect(\n/// v2,\n/// content=(\n/// #|Some(<ArrayView: [3, 4]>)\n/// ),\n/// )\n/// }\n/// ```\npub fn[T : Eq] Array::strip_suffix(\n self : Array[T],\n suffix : ArrayView[T],\n) -> ArrayView[T]? {\n self[:].strip_suffix(suffix)\n}\n\n///|\n/// Searches for the first occurrence of a value in the array and returns its\n/// index.\n///\n/// Parameters:\n///\n/// * `self` : The array to search in.\n/// * `value` : The value to search for.\n///\n/// Returns an `Option` containing the index of the first occurrence of `value`\n/// if found, or `None` if the value is not present in the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 2, 4]\n/// debug_inspect(arr.search(2), content=\"Some(1)\") // first occurrence\n/// debug_inspect(arr.search(5), content=\"None\") // not found\n/// }\n/// ```\npub fn[T : Eq] Array::search(self : Array[T], value : T) -> Int? {\n self[:].search(value)\n}\n\n///|\n/// Search the index of the first element that satisfies the predicate.\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let v = [1, 2, 3, 4, 5]\n/// match v.search_by(x => x == 3) {\n/// Some(index) => assert_eq(index, 2) // 2\n/// None => println(\"Not found\")\n/// }\n/// }\n/// ```\n#locals(f)\n#alias(find_index, deprecated)\npub fn[T] Array::search_by(\n self : Array[T],\n f : (T) -> Bool raise?,\n) -> Int? raise? {\n for i, v in self {\n if f(v) {\n break Some(i)\n }\n } nobreak {\n None\n }\n}\n\n///|\n/// Performs a binary search on a sorted array to find the index of a given element.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let v = [3, 4, 5]\n/// let result = v.binary_search(3)\n/// assert_eq(result, Ok(0)) // The element 3 is found at index 0\n/// }\n/// ```\n///\n/// # Arguments\n/// - `self`: The array in which to perform the search.\n/// - `value`: The element to search for in the array.\n///\n/// # Returns\n/// - `Result[Int, Int]`:\n/// If the element is found, an `Ok` variant is returned, containing the index of the matching element in the array.\n/// If there are multiple matches, the leftmost match will be returned.\n/// If the element is not found, an `Err` variant is returned, containing the index where the element could be inserted to maintain the sorted order.\n///\n/// # Notes\n/// - Ensure that the array is sorted in increasing order before calling this function.\n/// - If the array is not sorted, the returned result is undefined and should not be relied on.\npub fn[T : Compare] Array::binary_search(\n self : Array[T],\n value : T,\n) -> Result[Int, Int] {\n self[:].binary_search(value)\n}\n\n///|\n/// Performs a binary search on a sorted array using a custom comparison\n/// function. Returns the position of the matching element if found, or the\n/// position where the element could be inserted while maintaining the sorted\n/// order.\n///\n/// Parameters:\n///\n/// * `array` : The sorted array to search in.\n/// * `comparator` : A function that compares each element with the target value,\n/// returning:\n/// * A negative integer if the element is less than the target\n/// * Zero if the element equals the target\n/// * A positive integer if the element is greater than the target\n///\n/// Returns a `Result` containing either:\n///\n/// * `Ok(index)` if a matching element is found at position `index`\n/// * `Err(index)` if no match is found, where `index` is the position where the\n/// element could be inserted\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 3, 5, 7, 9]\n/// let find_3 = arr.binary_search_by(x => x.compare(3))\n/// debug_inspect(find_3, content=\"Ok(1)\")\n/// let find_4 = arr.binary_search_by(x => x.compare(4))\n/// debug_inspect(find_4, content=\"Err(2)\")\n/// }\n/// ```\n///\n/// Notes:\n///\n/// * Assumes the array is sorted according to the ordering implied by the\n/// comparison function\n/// * For multiple matches, returns the leftmost matching position\n/// * Returns an insertion point that maintains the sort order when no match is\n/// found\npub fn[T] Array::binary_search_by(\n self : Array[T],\n cmp : (T) -> Int raise?,\n) -> Result[Int, Int] raise? {\n self[:].binary_search_by(cmp)\n}\n\n///|\n/// Swaps the values at two positions in the array.\n///\n/// Parameters:\n///\n/// * `array` : The array in which to swap elements.\n/// * `index1` : The index of the first element to be swapped.\n/// * `index2` : The index of the second element to be swapped.\n///\n/// This function will panic if either index is negative or greater than or equal to\n/// the length of the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// arr.swap(0, 2)\n/// debug_inspect(arr, content=\"[3, 2, 1]\")\n/// }\n/// ```\npub fn[T] Array::swap(self : Array[T], i : Int, j : Int) -> Unit {\n if i >= self.length() || j >= self.length() || i < 0 || j < 0 {\n let len = self.length()\n abort(\n \"index out of bounds: the len is from 0 to \\{len} but the index is (\\{i}, \\{j})\",\n )\n }\n let temp = self.unsafe_get(i)\n self.unsafe_set(i, self.unsafe_get(j))\n self.unsafe_set(j, temp)\n}\n\n///|\n/// Removes all elements from the array that do not satisfy the predicate\n/// function, modifying the array in place. The order of remaining elements is\n/// preserved.\n///\n/// Parameters:\n///\n/// * `array` : The array to be filtered.\n/// * `predicate` : A function that takes an element and returns `true` if the\n/// element should be kept, `false` if it should be removed.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.retain(x => x % 2 == 0)\n/// debug_inspect(arr, content=\"[2, 4]\")\n/// let arr = [1, 2, 3]\n/// arr.retain(x => x > 10)\n/// debug_inspect(arr, content=\"[]\")\n/// let arr = [1, 2, 3]\n/// arr.retain(_ => true)\n/// debug_inspect(arr, content=\"[1, 2, 3]\")\n/// }\n/// ```\n/// TODO: perf could be improved\n#locals(f)\npub fn[T] Array::retain(self : Array[T], f : (T) -> Bool raise?) -> Unit raise? {\n for v in self; j = 0 {\n if f(v) {\n self.unsafe_set(j, v)\n continue j + 1\n }\n continue j\n } nobreak {\n self.unsafe_truncate_to_length(j)\n }\n}\n\n///|\n/// Resizes an array to a specified length, either by truncating if the new\n/// length is smaller, or by appending copies of a default value if the new\n/// length is larger.\n///\n/// Parameters:\n///\n/// * `array` : The array to be resized.\n/// * `new_length` : The desired length of the array after resizing.\n/// * `default_value` : The value to append when extending the array.\n///\n/// Throws a panic if `new_length` is negative.\n///\n/// Examples:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.resize(3, 0)\n/// debug_inspect(arr, content=\"[1, 2, 3]\")\n/// let arr = [1, 2, 3]\n/// arr.resize(5, 0)\n/// debug_inspect(arr, content=\"[1, 2, 3, 0, 0]\")\n/// }\n/// ```\n///\npub fn[T] Array::resize(self : Array[T], new_len : Int, f : T) -> Unit {\n if new_len < 0 {\n abort(\"negative new length\")\n }\n if new_len < self.length() {\n self.unsafe_truncate_to_length(new_len)\n } else {\n let len = self.length()\n for _ in len..<new_len {\n self.push(f)\n }\n }\n}\n\n///|\n/// Flattens an array of arrays into an array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let v = [[3, 4], [5, 6]].flatten()\n/// assert_eq(v, [3, 4, 5, 6])\n/// }\n/// ```\npub fn[T] Array::flatten(self : Array[Array[T]]) -> Array[T] {\n let len = for x in self; len = 0 {\n continue len + x.length()\n } nobreak {\n len\n }\n let res = Array::make_uninit(len)\n for xs in self; i = 0 {\n res.unsafe_blit(i, xs, 0, xs.length())\n continue i + xs.length()\n }\n res\n}\n\n///|\n/// Create an array by repeating `self` `times` times.\n///\n/// Aborts if `times` is negative. When `times` is `0`, returns an empty array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let v = [3, 4].repeat(2)\n/// assert_eq(v, [3, 4, 3, 4])\n/// }\n/// ```\npub fn[T] Array::repeat(self : Array[T], times : Int) -> Array[T] {\n if times < 0 {\n abort(\"negative repeat count\")\n }\n let len = self.length()\n if times == 0 || len == 0 {\n return []\n }\n let total = len * times\n guard total / times == len else { abort(\"repeat result too large\") }\n let v = Array::new(capacity=total)\n for _ in 0..<times {\n v.append(self)\n }\n v\n}\n\n///|\n/// Fold out values from an array according to certain rules.\n/// This method traverses the array through `self.iter()`, so the traversal\n/// bounds are fixed when folding starts.\n///\n/// Structural mutations to `self` inside `f` are unsupported. Appended\n/// elements are not visited, and shrinking the array with operations such as\n/// `remove`, `truncate`, `clear`, or `drain` may cause later fold steps to\n/// fail.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sum = [1, 2, 3, 4, 5].fold(init=0, (sum, elem) => sum + elem)\n/// assert_eq(sum, 15)\n/// }\n/// ```\n#locals(f)\n#alias(fold_left, deprecated)\npub fn[A, B] Array::fold(\n self : Array[A],\n init~ : B,\n f : (B, A) -> B raise?,\n) -> B raise? {\n for item in self; acc = init {\n continue f(acc, item)\n } nobreak {\n acc\n }\n}\n\n///|\n/// Fold out values from an array according to certain rules in reversed turn.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sum = [1, 2, 3, 4, 5].rev_fold(init=0, (sum, elem) => sum + elem)\n/// assert_eq(sum, 15)\n/// }\n/// ```\n#locals(f)\n#alias(fold_right, deprecated)\npub fn[A, B] Array::rev_fold(\n self : Array[A],\n init~ : B,\n f : (B, A) -> B raise?,\n) -> B raise? {\n for i = self.length() - 1, acc = init; i >= 0; {\n continue i - 1, f(acc, self[i])\n } nobreak {\n acc\n }\n}\n\n///|\n/// Fold out values from an array according to certain rules with index.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sum = [1, 2, 3, 4, 5].foldi(init=0, (index, sum, _elem) => sum + index)\n/// assert_eq(sum, 10)\n/// }\n/// ```\n#locals(f)\n#alias(fold_lefti, deprecated)\npub fn[A, B] Array::foldi(\n self : Array[A],\n init~ : B,\n f : (Int, B, A) -> B raise?,\n) -> B raise? {\n for i, x in self; acc = init {\n continue f(i, acc, x)\n } nobreak {\n acc\n }\n}\n\n///|\n/// Fold out values from an array according to certain rules in reversed turn with index.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let sum = [1, 2, 3, 4, 5].rev_foldi(init=0, (index, sum, _elem) => sum + index)\n/// assert_eq(sum, 10)\n/// }\n/// ```\n#locals(f)\n#alias(fold_righti, deprecated)\npub fn[A, B] Array::rev_foldi(\n self : Array[A],\n init~ : B,\n f : (Int, B, A) -> B raise?,\n) -> B raise? {\n let len = self.length()\n for i in len>..0; acc = init {\n continue f(len - i - 1, acc, self[i])\n } nobreak {\n acc\n }\n}\n\n///|\n/// Removes consecutive duplicate elements from an array in-place, using equality\n/// comparison. The first occurrence of each element is retained while subsequent\n/// equal elements are removed.\n///\n/// Parameters:\n///\n/// * `array` : The array to remove duplicates from. Must contain elements that\n/// implement the `Eq` trait for equality comparison.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 2, 3, 3, 3, 2]\n/// arr.dedup()\n/// debug_inspect(arr, content=\"[1, 2, 3, 2]\")\n/// let arr = [1, 2, 2, 2, 3, 3]\n/// arr.dedup()\n/// debug_inspect(arr, content=\"[1, 2, 3]\")\n/// let arr : Array[Int] = []\n/// arr.dedup()\n/// debug_inspect(arr, content=\"[]\")\n/// }\n/// ```\n///\n/// Note: For best results when removing all duplicates regardless of position,\n/// sort the array before calling this function. When used on an unsorted array,\n/// this function only removes consecutive duplicates.\npub fn[T : Eq] Array::dedup(self : Array[T]) -> Unit {\n if self.is_empty() {\n return\n }\n let w = for i in 1..<self.length(); w = 1 {\n if self[i] != self[w - 1] {\n self[w] = self[i]\n continue w + 1\n }\n continue w\n } nobreak {\n w\n }\n self.unsafe_truncate_to_length(w)\n}\n\n///|\n/// Extracts elements from an array that satisfy a given predicate function. The\n/// extracted elements are removed from the original array and returned as a new\n/// array. The relative order of the extracted elements is preserved.\n///\n/// Parameters:\n///\n/// * `array` : The array to extract elements from.\n/// * `predicate` : A function that takes an element and returns `true` if the\n/// element should be extracted, `false` otherwise.\n///\n/// Returns a new array containing all elements that satisfy the predicate\n/// function, in the order they appeared in the original array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// let extracted = arr.extract_if(x => x % 2 == 0)\n/// debug_inspect(extracted, content=\"[2, 4]\")\n/// debug_inspect(arr, content=\"[1, 3, 5]\")\n/// }\n/// ```\n#locals(f)\npub fn[T] Array::extract_if(\n self : Array[T],\n f : (T) -> Bool raise?,\n) -> Array[T] raise? {\n let removed = []\n for read in 0..<self.length(); write = 0 {\n let elem = self[read]\n if f(elem) {\n removed.push(elem)\n continue write\n } else {\n if read != write {\n self[write] = elem\n }\n continue write + 1\n }\n } nobreak {\n self.truncate(write)\n }\n removed\n}\n\n///|\n/// Divides an array into smaller arrays (chunks) of the specified size.\n///\n/// Parameters:\n///\n/// * `array` : The array to be divided into chunks.\n/// * `size` : The size of each chunk. Must be a positive integer, otherwise it will panic.\n///\n///\n/// Returns an array of arrays, where each inner array is a chunk containing\n/// elements from the original array. If the length of the original array is not\n/// divisible by the chunk size, the last chunk will contain fewer elements.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// let chunks = arr.chunks(2)\n/// debug_inspect(\n/// chunks,\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [3, 4]>, <ArrayView: [5]>]\n/// ),\n/// )\n/// let arr : Array[Int] = []\n/// debug_inspect(arr.chunks(3), content=\"[]\")\n/// }\n/// ```\npub fn[T] Array::chunks(self : Array[T], size : Int) -> Array[ArrayView[T]] {\n guard size > 0\n let len = self.length()\n if len == 0 {\n return []\n }\n let num_chunks = (len + size - 1) / size\n Array::makei(num_chunks, i => {\n let start = i * size\n let end = Int::min(start + size, len)\n self[start:end]\n })\n}\n\n///|\n/// Groups consecutive elements of the array into chunks where adjacent elements\n/// satisfy the given predicate function.\n///\n/// Parameters:\n///\n/// * `array` : The array to be chunked.\n/// * `predicate` : A function that takes two adjacent elements and returns\n/// `true` if they should be in the same chunk, `false` otherwise.\n///\n/// Returns an array of arrays, where each inner array is a chunk of consecutive\n/// elements that satisfy the predicate with their adjacent elements.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let v = [1, 1, 2, 3, 2, 3, 2, 3, 4]\n/// let chunks = v.chunk_by((x, y) => x <= y)\n/// debug_inspect(\n/// chunks,\n/// content=(\n/// #|[\n/// #| <ArrayView: [1, 1, 2, 3]>,\n/// #| <ArrayView: [2, 3]>,\n/// #| <ArrayView: [2, 3, 4]>,\n/// #|]\n/// ),\n/// )\n/// let v : Array[Int] = []\n/// debug_inspect(v.chunk_by((x, y) => x <= y), content=\"[]\")\n/// }\n/// ```\n#locals(pred)\npub fn[T] Array::chunk_by(\n self : Array[T],\n pred : (T, T) -> Bool raise?,\n) -> Array[ArrayView[T]] raise? {\n let chunks = []\n if self.is_empty() {\n return chunks\n }\n let start = for i in 1..<self.length(); start = 0 {\n if !pred(self[i - 1], self[i]) {\n chunks.push(self[start:i])\n continue i\n }\n continue start\n } nobreak {\n start\n }\n chunks.push(self[start:self.length()])\n chunks\n}\n\n///|\n/// Generates overlapping subslices (sliding windows) of the specified size.\n///\n/// Parameters:\n///\n/// * `array` : The array to be processed with sliding windows.\n/// * `size` : The window length. Must be a positive integer, otherwise it will panic.\n///\n/// Returns an array of slices, where each inner slice is a contiguous subslice\n/// of the original array. Windows are produced with a step size of 1. If the\n/// original array's length is less than the specified window size, the result\n/// will be an empty array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// let windows = arr.windows(2)\n/// debug_inspect(\n/// windows,\n/// content=(\n/// #|[\n/// #| <ArrayView: [1, 2]>,\n/// #| <ArrayView: [2, 3]>,\n/// #| <ArrayView: [3, 4]>,\n/// #| <ArrayView: [4, 5]>,\n/// #|]\n/// ),\n/// )\n/// let arr = [1, 2]\n/// debug_inspect(arr.windows(3), content=\"[]\")\n/// }\n/// ```\npub fn[T] Array::windows(self : Array[T], size : Int) -> Array[ArrayView[T]] {\n guard size > 0\n let len = self.length() - size + 1\n if len < 1 {\n return []\n }\n Array::makei(len, i => self[i:i + size])\n}\n\n///|\n/// Return an iterator over all suffix views of this array.\n///\n/// Suffixes are yielded from longest to shortest. Set `include_empty=true` to\n/// include the final empty suffix.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let xs = [1, 2]\n/// debug_inspect(\n/// xs.suffixes().collect(),\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [2]>]\n/// ),\n/// )\n/// debug_inspect(\n/// xs.suffixes(include_empty=true).collect(),\n/// content=(\n/// #|[<ArrayView: [1, 2]>, <ArrayView: [2]>, <ArrayView: []>]\n/// ),\n/// )\n/// }\n/// ```\npub fn[T] Array::suffixes(\n self : Array[T],\n include_empty? : Bool = false,\n) -> Iter[ArrayView[T]] {\n self[:].suffixes(include_empty~)\n}\n\n///|\n/// Splits an array into chunks using a predicate function. Creates chunks by\n/// grouping consecutive elements that do not satisfy the predicate function.\n/// Elements that satisfy the predicate function are excluded from the resulting\n/// chunks and act as delimiters.\n///\n/// Parameters:\n///\n/// * `array` : The array to be split into chunks.\n/// * `predicate` : A function that takes an element and returns `true` if the\n/// element should be used as a delimiter.\n///\n/// Returns an array of arrays, where each inner array is a chunk of consecutive\n/// elements that do not satisfy the predicate.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 0, 2, 0, 3, 0, 4]\n/// debug_inspect(arr.split(x => x == 0), content=\"[[1], [2], [3], [4]]\")\n/// let arr = [0, 1, 0, 0, 2, 0]\n/// debug_inspect(arr.split(x => x == 0), content=\"[[], [1], [], [2]]\")\n/// }\n/// ```\n#locals(pred)\npub fn[T] Array::split(\n self : Array[T],\n pred : (T) -> Bool raise?,\n) -> Array[Array[T]] raise? {\n let chunks = []\n for i = 0; i < self.length(); {\n let chunk = []\n let i = for i = i; i < self.length() && !pred(self[i]); {\n chunk.push(self[i])\n continue i + 1\n } nobreak {\n i\n }\n chunks.push(chunk)\n continue i + 1\n }\n chunks\n}\n\n///|\n/// Creates an iterator over the elements of the array.\n///\n/// Parameters:\n///\n/// * `array` : The array to create an iterator from.\n///\n/// Returns an iterator that yields each element of the array in order.\n/// This iterator is created from `self[:]`, so the traversal bounds are fixed\n/// when iteration starts.\n///\n/// Structural mutations after the iterator is created are unsupported.\n/// Appended elements are not visited, and shrinking the array with operations\n/// such as `remove`, `truncate`, `clear`, or `drain` may cause later iterator\n/// steps to fail. The same caveat applies to `rev_iter()`, `iter2()`, and\n/// helpers built on top of them such as `each()`, `eachi()`, and `fold()`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// let mut sum = 0\n/// arr.iter().each(x => sum = sum + x)\n/// inspect(sum, content=\"6\")\n/// }\n/// ```\n#alias(iterator, deprecated)\npub fn[T] Array::iter(self : Array[T]) -> Iter[T] {\n self[:].iter()\n}\n\n///|\n/// Returns an iterator that yields elements from the array in reverse order,\n/// from the last element to the first.\n///\n/// Parameters:\n///\n/// * `array` : The array to iterate over in reverse order.\n///\n/// Returns an iterator that yields each element of the array, starting from the\n/// last element and moving towards the first.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// let result = []\n/// arr.rev_iter().each(x => result.push(x))\n/// debug_inspect(result, content=\"[3, 2, 1]\")\n/// }\n/// ```\n#alias(rev_iterator, deprecated)\npub fn[T] Array::rev_iter(self : Array[T]) -> Iter[T] {\n self[:].rev_iter()\n}\n\n///|\n/// Returns an iterator that provides both indices and values of the array in\n/// order.\n///\n/// Parameters:\n///\n/// * `self` : The array to iterate over.\n///\n/// Returns an iterator that yields tuples of index and value pairs, where\n/// indices start from 0.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [10, 20, 30]\n/// let mut sum = 0\n/// arr.iter2().each((i, x) => sum = sum + i + x)\n/// inspect(sum, content=\"63\") // (0 + 10) + (1 + 20) + (2 + 30) = 63\n/// }\n/// ```\n#alias(iterator2, deprecated)\npub fn[A] Array::iter2(self : Array[A]) -> Iter2[Int, A] {\n self[:].iter2()\n}\n\n///|\n/// Creates a new empty array.\n///\n/// Returns an empty array of type `Array[T]`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr : Array[Int] = Array::default()\n/// inspect(arr.length(), content=\"0\")\n/// inspect(arr.is_empty(), content=\"true\")\n/// }\n/// ```\npub impl[T] Default for Array[T] with default() {\n []\n}\n\n///|\n/// Removes a back element from an array.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let array = [1, 2, 3, 4, 5]\n/// array.unsafe_pop_back()\n/// assert_eq(array.last(), Some(4))\n/// }\n/// ```\n#internal(unsafe, \"Panic if the array is empty on non-JS backend.\")\n#doc(hidden)\npub fn[A] Array::unsafe_pop_back(self : Array[A]) -> Unit {\n self.unsafe_pop() |> ignore\n}\n\n///|\n/// Truncates the array in-place to the specified length.\n///\n/// If `len` is greater than or equal to the current array length,\n/// the function does nothing. If `len` is 0, the array is cleared.\n/// Otherwise, removes elements from the end until the array reaches the given length.\n///\n/// Parameters:\n///\n/// * `self` : The target array (modified in-place).\n/// * `len` : The new desired length (must be non-negative).\n///\n/// Important:\n/// - If `len` is negative, the function does nothing.\n/// - If `len` exceeds current length, the array remains unchanged.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.truncate(3)\n/// debug_inspect(arr, content=\"[1, 2, 3]\")\n/// }\n/// ```\npub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit {\n guard len >= 0 && len < self.length() else { return }\n self.unsafe_truncate_to_length(len)\n}\n\n///|\n/// In-place filter and map for Array\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// arr.retain_map(fn(x) { if x % 2 == 0 { Some(x * 2) } else { None } })\n/// debug_inspect(arr, content=\"[4, 8]\")\n/// }\n/// ```\n#locals(f)\npub fn[A] Array::retain_map(\n self : Array[A],\n f : (A) -> A? raise?,\n) -> Unit raise? {\n if self.is_empty() {\n return\n }\n let buf = self.buffer()\n let len = self.length()\n for read_idx in 0..<len; write_idx = 0 {\n let val = buf[read_idx]\n match f(val) {\n Some(new_val) => {\n buf[write_idx] = new_val\n continue write_idx + 1\n }\n None => continue write_idx\n }\n } nobreak {\n self.unsafe_truncate_to_length(write_idx)\n }\n}\n\n///|\n/// Creates a new array containing all elements from an iterator.\n///\n/// Parameters:\n///\n/// * `iterator` : An iterator containing elements of type `T`.\n///\n/// Returns a new array containing all elements from the iterator in the same\n/// order.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let iter = Iter::singleton(42)\n/// let arr = Array::from_iter(iter)\n/// debug_inspect(arr, content=\"[42]\")\n/// }\n/// ```\n#alias(from_iterator, deprecated)\npub fn[T] Array::from_iter(iter : Iter[T]) -> Array[T] {\n iter.collect()\n}\n\n///|\n/// Adds all elements from an iterator to the end of the array.\n///\n/// This function iterates over each element in the provided iterator\n/// and adds them to the array using the `push` method.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let u = [1, 2, 3]\n/// let v = [4, 5, 6]\n/// u.push_iter(v.iter())\n/// assert_eq(u, [1, 2, 3, 4, 5, 6])\n/// }\n/// ```\npub fn[T] Array::push_iter(self : Self[T], iter : Iter[T]) -> Unit {\n // This function used by [Array spread operator](https://docs.moonbitlang.com/en/latest/language/fundamentals.html#spread-operator)\n // it can't be removed and deprecated\n if iter.size_hint() is Some(n) {\n self.reserve_capacity(self.length() + n)\n }\n for x in iter {\n self.push(x)\n }\n}\n\n///|\n/// Shuffle the array using Knuth shuffle\n///\n/// To use this function, you need to provide a rand function, which takes an integer as it upper bound\n/// and returns an integer.\n/// *rand n* is expected to returns a uniformly distribution integer between 0 and n - 1\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3, 4, 5]\n/// fn rand(upper : Int) -> Int {\n/// let rng = @random.Rand::new()\n/// rng.int(limit=upper)\n/// }\n///\n/// Array::shuffle_in_place(arr, rand~)\n/// }\n/// ```\n#locals(rand)\npub fn[T] Array::shuffle_in_place(\n self : Array[T],\n rand~ : (Int) -> Int,\n) -> Unit {\n let n = self.length()\n for i in n>..1 {\n let j = rand(i + 1) % (i + 1)\n // for safety, perf is not a concern here\n // TODO: maybe return an error later\n self.swap(i, j)\n }\n}\n\n///|\n/// Shuffle the array using Knuth shuffle\n///\n/// To use this function, you need to provide a rand function, which takes an integer as it upper bound\n/// and returns an integer.\n/// *rand n* is expected to returns a uniformly distribution integer between 0 and n - 1\n/// # Example\n///\n/// ```mbt nocheck\n/// let arr = [1, 2, 3, 4, 5]\n///\n/// fn rand(upper : Int) -> Int {\n/// let rng = @random.Rand::new()\n/// rng.int(limit=upper)\n/// }\n///\n/// let _shuffled = Array::shuffle(arr, rand~)\n/// ```\npub fn[T] Array::shuffle(self : Array[T], rand~ : (Int) -> Int) -> Array[T] {\n let new_arr = self.copy()\n Array::shuffle_in_place(new_arr, rand~)\n new_arr\n}\n\n///|\n/// Returns a new array containing the elements of the original array that satisfy the given predicate.\n///\n/// # Arguments\n///\n/// * `self` - The array to filter.\n/// * `f` - The predicate function.\n///\n/// # Returns\n///\n#locals(f)\npub fn[A, B] Array::filter_map(\n self : Array[A],\n f : (A) -> B? raise?,\n) -> Array[B] raise? {\n let result = []\n for x in self {\n if f(x) is Some(x) {\n result.push(x)\n }\n }\n result\n}\n\n///|\n/// Returns the last element of the array, or `None` if the array is empty.\n///\n/// Parameters:\n///\n/// * `array` : The array to get the last element from.\n///\n/// Returns an optional value containing the last element of the array. The\n/// result is `None` if the array is empty, or `Some(x)` where `x` is the last\n/// element of the array.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr = [1, 2, 3]\n/// debug_inspect(arr.last(), content=\"Some(3)\")\n/// let empty : Array[Int] = []\n/// debug_inspect(empty.last(), content=\"None\")\n/// }\n/// ```\npub fn[A] Array::last(self : Array[A]) -> A? {\n match self {\n [] => None\n [.., last] => Some(last)\n }\n}\n\n///|\n/// Zips two arrays into a single array of tuples.\n///\n/// Parameters:\n///\n/// * `self` : The first array.\n/// * `other` : The second array.\n///\n/// Returns an array of tuples, where each tuple contains corresponding elements\n/// from the two input arrays.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr1 = [1, 2, 3]\n/// let arr2 = ['a', 'b', 'c']\n/// debug_inspect(arr1.zip(arr2), content=\"[(1, 'a'), (2, 'b'), (3, 'c')]\")\n/// }\n/// ```\npub fn[A, B] Array::zip(self : Array[A], other : Array[B]) -> Array[(A, B)] {\n let length = if self.length() < other.length() {\n self.length()\n } else {\n other.length()\n }\n Array::makei(length, i => (self[i], other[i]))\n}\n\n///|\n/// Splits an array of pairs into two arrays, separating the first and second elements.\n///\n/// # Example\n/// ```mbt check\n/// test {\n/// let arr = [(1, \"a\"), (2, \"b\"), (3, \"c\")]\n/// let (nums, strs) = arr.unzip()\n/// debug_inspect(nums, content=\"[1, 2, 3]\")\n/// debug_inspect(strs, content=\"[\\\"a\\\", \\\"b\\\", \\\"c\\\"]\")\n/// }\n/// ```\npub fn[T1, T2] Array::unzip(self : Array[(T1, T2)]) -> (Array[T1], Array[T2]) {\n let arr1 : Array[T1] = Array::new(capacity=self.length())\n let arr2 : Array[T2] = Array::new(capacity=self.length())\n for pair in self {\n let (x, y) = pair\n arr1.push(x)\n arr2.push(y)\n }\n (arr1, arr2)\n}\n\n///|\n/// Zips two arrays into an iterator that yields corresponding elements.\n///\n/// Parameters:\n///\n/// * `self` : The first array.\n/// * `other` : The second array.\n///\n/// Returns an `Iter2` iterator that produces corresponding elements\n/// from both arrays. The iteration continues until the shorter array is exhausted.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let arr1 = [1, 2, 3]\n/// let arr2 = ['a', 'b', 'c']\n/// debug_inspect(\n/// arr1.zip_to_iter2(arr2).to_array(),\n/// content=\"[(1, 'a'), (2, 'b'), (3, 'c')]\",\n/// )\n/// }\n/// ```\npub fn[A, B] Array::zip_to_iter2(\n self : Array[A],\n other : Array[B],\n) -> Iter2[A, B] {\n let length = if self.length() < other.length() {\n self.length()\n } else {\n other.length()\n }\n let mut i = 0\n Iter2::new(\n () => {\n guard i < length else { None }\n let elem = (self[i], other[i])\n i += 1\n Some(elem)\n },\n size_hint=length,\n ).iter2()\n}\n\n///|\n/// Join an array of strings using the provided `separator`.\n///\n/// Parameters:\n/// * `separator` : The string inserted between each element.\n///\n/// Returns a single concatenated `String`.\n/// # Example:\n/// ```mbt check\n/// test {\n/// let s = \"hello world\"\n/// inspect(s.split(\" \").to_array().join(\":\"), content=\"hello:world\")\n/// }\n/// ```\npub fn[A : ToStringView] Array::join(\n self : Array[A],\n separator : StringView,\n) -> String {\n self[:].join(separator)\n}\n\n///|\n/// Performs a lexicographical comparison of two arrays.\n///\n/// This method compares the arrays element by element until a difference is\n/// found or one array is exhausted. Unlike the `Compare` trait implementation\n/// which uses shortlex order (shorter arrays come first), this method compares\n/// based purely on element values until a difference is found.\n///\n/// # Returns\n///\n/// - A negative integer if `self` is lexicographically less than `other`\n/// - Zero if `self` is lexicographically equal to `other`\n/// - A positive integer if `self` is lexicographically greater than `other`\n///\n/// # Example\n///\n/// ```mbt check\n/// test {\n/// inspect([1, 2].lexical_compare([1, 2, 3]), content=\"-1\")\n/// inspect([1, 2, 3].lexical_compare([1, 2]), content=\"1\")\n/// inspect([1, 2, 3].lexical_compare([1, 2, 3]), content=\"0\")\n/// inspect([1, 2, 3].lexical_compare([1, 2, 4]), content=\"-1\")\n/// }\n/// ```\npub fn[T : Compare] Array::lexical_compare(\n self : Array[T],\n other : Array[T],\n) -> Int {\n self[:].lexical_compare(other)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Converts a double-precision floating-point number to a 32-bit integer.\n/// Handles special cases including NaN and numbers outside the valid Int range.\n///\n/// Parameters:\n///\n/// * `self` : The double-precision floating-point number to be converted.\n///\n/// Returns an 32-bit integer value according to the following rules:\n///\n/// * Returns 0 if the input is NaN\n/// * Returns `@int.MAX_VALUE` (2147483647) if the input is greater than or\n/// equal to `@int.MAX_VALUE`\n/// * Returns `@int.MIN_VALUE` (-2147483648) if the input is less than or equal\n/// to `@int.MIN_VALUE`\n/// * Otherwise returns the integer part of the input by truncating towards zero\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42.0.to_int(), content=\"42\")\n/// inspect((-42.5).to_int(), content=\"-42\")\n/// inspect((0.0 / 0.0).to_int(), content=\"0\") // NaN\n/// inspect((1.0 / 0.0).to_int(), content=\"2147483647\") // Infinity\n/// inspect((-1.0 / 0.0).to_int(), content=\"-2147483648\") // -Infinity\n/// }\n/// ```\npub fn Double::to_int(self : Double) -> Int {\n if self != self {\n 0\n } else if self >= 2147483647 {\n 2147483647\n } else if self <= -2147483648 {\n -2147483648\n } else {\n self.to_unchecked_int()\n }\n}\n\n///|\nfn Double::to_unchecked_int(self : Double) -> Int = \"%f64_to_i32\"\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Converts an integer to a double-precision floating-point number.\n///\n/// Parameters:\n///\n/// * `integer` : The integer value to be converted.\n///\n/// Returns a double-precision floating-point number representing the given\n/// integer value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(Double::from_int(42), content=\"42\")\n/// inspect(Double::from_int(-1), content=\"-1\")\n/// }\n/// ```\npub fn Double::from_int(i : Int) -> Double {\n i.to_double()\n}\n\n///|\n/// Returns the absolute value of a double-precision floating-point number.\n///\n/// Parameters:\n///\n/// * `value` : The double-precision floating-point number to compute the\n/// absolute value of.\n///\n/// Returns the absolute value of the input number. For any input `x`, the result\n/// is equivalent to `if x < 0.0 { -x } else { x }`.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect((-2.5).abs(), content=\"2.5\")\n/// inspect(3.14.abs(), content=\"3.14\")\n/// inspect(0.0.abs(), content=\"0\")\n/// }\n/// ```\npub fn Double::abs(self : Double) -> Double = \"%f64.abs\"\n\n///|\n/// Returns the minimum of two double-precision floating-point values.\n///\n/// If exactly one argument is NaN, returns the other argument.\npub fn Double::min(self : Double, other : Double) -> Double {\n if self.is_nan() {\n other\n } else if other.is_nan() {\n self\n } else if self < other {\n self\n } else {\n other\n }\n}\n\n///|\n/// Returns the maximum of two double-precision floating-point values.\n///\n/// If exactly one argument is NaN, returns the other argument.\npub fn Double::max(self : Double, other : Double) -> Double {\n if self.is_nan() {\n other\n } else if other.is_nan() {\n self\n } else if self > other {\n self\n } else {\n other\n }\n}\n\n///|\n/// Clamps the value between `min` and `max` (inclusive).\n///\n/// Parameters:\n///\n/// * `self` : The value to clamp.\n/// * `min` : The lower bound of the range.\n/// * `max` : The upper bound of the range.\n///\n/// Returns `min` if `self < min`, `max` if `self > max`, and `self` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(0.5.clamp(min=0.0, max=1.0), content=\"0.5\")\n/// inspect((-1.0).clamp(min=0.0, max=1.0), content=\"0\")\n/// inspect(2.0.clamp(min=0.0, max=1.0), content=\"1\")\n/// }\n/// ```\npub fn Double::clamp(self : Double, min~ : Double, max~ : Double) -> Double {\n guard min <= max\n if self < min {\n min\n } else if self > max {\n max\n } else {\n self\n }\n}\n\n///|\n/// Performs linear interpolation from `self` to `target` by factor `t`.\n///\n/// The interpolation formula is `self + (target - self) * t`.\n///\n/// Parameters:\n///\n/// * `self` : The start value.\n/// * `target` : The end value.\n/// * `t` : The interpolation factor.\n///\n/// Returns the interpolated value.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(0.0.lerp(target=10.0, t=0.25), content=\"2.5\")\n/// inspect(5.0.lerp(target=15.0, t=0.0), content=\"5\")\n/// inspect(5.0.lerp(target=15.0, t=1.0), content=\"15\")\n/// }\n/// ```\npub fn Double::lerp(self : Double, target~ : Double, t~ : Double) -> Double {\n self + (target - self) * t\n}\n\n///|\n/// Returns the sign of the double.\n/// - If the double is positive, returns 1.0.\n/// - If the double is negative, returns -1.0.\n/// - Otherwise, returns the double itself (0.0, -0.0 and NaN).\npub fn Double::signum(self : Double) -> Double {\n if self < 0.0 {\n -1.0\n } else if self > 0.0 {\n 1.0\n } else {\n self // handles 0.0, -0.0, NaN\n }\n}\n\n///|\n/// Checks whether a double-precision floating-point number represents a \"Not a\n/// Number\" (NaN) value.\n///\n/// Parameters:\n///\n/// * `number` : A double-precision floating-point value to be checked.\n///\n/// Returns `true` if the number is NaN, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(@double.not_a_number.is_nan(), content=\"true\")\n/// inspect(42.0.is_nan(), content=\"false\")\n/// inspect((0.0 / 0.0).is_nan(), content=\"true\")\n/// }\n/// ```\npub fn Double::is_nan(self : Double) -> Bool {\n // only NaNs satisfy f != f.\n self != self\n}\n\n///|\n/// Checks whether a double-precision floating-point number represents positive\n/// or negative infinity.\n///\n/// Parameters:\n///\n/// * `value` : The double-precision floating-point number to check.\n///\n/// Returns `true` if the value is either positive or negative infinity, `false`\n/// otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(@double.infinity.is_inf(), content=\"true\")\n/// inspect(@double.neg_infinity.is_inf(), content=\"true\")\n/// inspect(42.0.is_inf(), content=\"false\")\n/// }\n/// ```\npub fn Double::is_inf(self : Double) -> Bool {\n self > double_max_value || self < double_min_value\n}\n\n///|\n/// Checks whether a double-precision floating-point number is positive infinity.\n///\n/// Parameters:\n///\n/// * `value` : The double-precision floating-point number to check.\n///\n/// Returns `true` if the number is positive infinity, `false` otherwise.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(@double.infinity.is_pos_inf(), content=\"true\")\n/// inspect(@double.neg_infinity.is_pos_inf(), content=\"false\")\n/// inspect(42.0.is_pos_inf(), content=\"false\") // TODO: better formatter\n/// }\n/// ```\npub fn Double::is_pos_inf(self : Double) -> Bool {\n self > double_max_value\n}\n\n///|\n/// Checks whether a double-precision floating-point number is negative infinity.\n///\n/// Parameters:\n///\n/// * `self` : The double-precision floating-point number to check.\n///\n/// Returns a boolean value indicating whether the number is negative infinity.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect((-1.0 / 0.0).is_neg_inf(), content=\"true\")\n/// inspect(42.0.is_neg_inf(), content=\"false\")\n/// inspect((1.0 / 0.0).is_neg_inf(), content=\"false\") // positive infinity\n/// }\n/// ```\npub fn Double::is_neg_inf(self : Double) -> Bool {\n self < double_min_value\n}\n\n///|\npub impl Hash for Double with hash_combine(self, hasher) {\n hasher.combine_double(self)\n}\n\n///|\n/// Converts a double-precision floating-point number to its string\n/// representation.\n///\n/// Parameters:\n///\n/// * `self`: The double-precision floating-point number to be converted.\n///\n/// Returns a string representation of the double-precision floating-point\n/// number.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// inspect(42.0.to_string(), content=\"42\")\n/// inspect(3.14159.to_string(), content=\"3.14159\")\n/// inspect((-0.0).to_string(), content=\"0\")\n/// inspect(@double.not_a_number.to_string(), content=\"NaN\")\n/// }\n/// ```\n///\n#intrinsic(\"%f64.to_string\")\npub fn Double::to_string(self : Double) -> String {\n ryu_to_string(self)\n}\n\n///|\npub impl Show for Double with to_string(self) {\n Double::to_string(self)\n}\n\n///|\n/// Determines whether two floating-point numbers are approximately equal within\n/// specified tolerances.\n/// The implementation follows the algorithm described in PEP 485 for Python's\n/// `math.isclose()`.\n///\n/// Parameters:\n///\n/// * `self` : The first floating-point number to compare.\n/// * `other` : The second floating-point number to compare.\n/// * `relative_tolerance` : The relative tolerance for the comparison. Must be\n/// non-negative. Defaults to 1e-9.\n/// * `absolute_tolerance` : The absolute tolerance for the comparison. Must be\n/// non-negative. Defaults to 0.0.\n///\n/// Returns whether the two numbers are considered approximately equal. Returns\n/// `true` if the numbers are exactly equal or if they are within either the\n/// relative or absolute tolerance. Returns `false` if either number is infinite.\n///\n/// Example:\n///\n/// ```mbt check\n/// test {\n/// let x = 1.0\n/// let y = 1.000000001\n/// inspect(x.is_close(y), content=\"false\")\n/// inspect(x.is_close(y, relative_tolerance=1.0e-10), content=\"false\")\n/// inspect(@double.infinity.is_close(@double.infinity), content=\"true\")\n/// }\n/// ```\npub fn Double::is_close(\n self : Self,\n other : Self,\n relative_tolerance? : Self = 1.0e-09,\n absolute_tolerance? : Self = 0.0,\n) -> Bool {\n if relative_tolerance < 0.0 || absolute_tolerance < 0.0 {\n abort(\"Tolerances must be non-negative\")\n }\n if self == other {\n return true\n }\n if self.is_inf() || other.is_inf() {\n return false\n }\n let diff = (other - self).abs()\n return (\n diff <= (relative_tolerance * other).abs() ||\n diff <= (relative_tolerance * self).abs()\n ) ||\n diff <= absolute_tolerance\n}\n\n///|\n/// Converts a double-precision floating-point number to a sequence of bytes in\n/// big-endian byte order (most significant byte first).\n///\n/// Parameters:\n///\n/// * `self` : The double-precision floating-point number to be converted.\n///\n/// Returns a sequence of 8 bytes representing the double-precision\n/// floating-point number in big-endian byte order.\n///\n#deprecated\n#doc(hidden)\npub fn Double::to_be_bytes(self : Double) -> Bytes {\n self.reinterpret_as_uint64().to_be_bytes()\n}\n\n///|\n/// Converts a double-precision floating-point number to a sequence of bytes in\n/// little-endian order (least significant byte first).\n///\n/// Parameters:\n///\n/// * `self` : A double-precision floating-point number to be converted.\n///\n/// Returns a sequence of 8 bytes representing the double-precision\n/// floating-point number in little-endian order.\n///\n#deprecated\n#doc(hidden)\npub fn Double::to_le_bytes(self : Double) -> Bytes {\n self.reinterpret_as_uint64().to_le_bytes()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn Error::to_string(self : Error) -> String = \"%error.to_string\"\n\n///|\npub impl Show for Error with to_string(self) {\n Error::to_string(self)\n}\n\n///|\nfn Error::to_json(self : Error) -> Json = \"%error.to_json\"\n\n///|\npub impl ToJson for Error with to_json(self) {\n self.to_json()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nlet range_err_str = \"value out of range\"\n\n///|\nlet syntax_err_str = \"invalid syntax\"\n\n///|\nlet base_err_str = \"invalid base\"\n\n///|\nfn[T] range_err() -> T raise {\n raise Failure::Failure(range_err_str)\n}\n\n///|\nfn[T] syntax_err() -> T raise {\n raise Failure::Failure(syntax_err_str)\n}\n\n///|\nfn[T] base_err() -> T raise {\n raise Failure::Failure(base_err_str)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Returns the accumulated value, the slice left, and the number of digits consumed.\n/// It ignores underscore and stops when a non-digit character is found.\nfn[T] StringView::fold_digits(\n self : Self,\n init : T,\n f : (Int, T) -> T,\n) -> (Self, T, Int) {\n let mut ret = init\n let mut len = 0\n let mut str = self\n while str is [ch, .. rest] {\n if ch is ('0'..='9') {\n len += 1\n ret = f(ch.to_int() - '0', ret)\n } else if ch != '_' {\n break\n }\n str = rest\n }\n (str, ret, len)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nlet min_19digit_int : UInt64 = 100_0000_0000_0000_0000UL\n\n///|\npriv struct Number {\n exponent : Int64\n mantissa : UInt64\n negative : Bool\n many_digits : Bool\n}\n\n///|\n/// Returns the remaining slice, the parsed number, and the number of digits parsed.\nfn parse_digits(s : StringView, x : UInt64) -> (StringView, UInt64, Int) {\n s.fold_digits(x, (digit, acc : UInt64) => {\n acc * 10UL + UInt64::extend_uint(digit.reinterpret_as_uint())\n })\n}\n\n///|\nfn try_parse_19digits(s : StringView, x : UInt64) -> (StringView, UInt64, Int) {\n let mut x = x\n let mut len = 0\n for s = s {\n match s {\n ['0'..='9' as ch, .. rest] if x < min_19digit_int => {\n len += 1\n x = x * 10UL +\n UInt64::extend_uint((ch.to_int() - '0').reinterpret_as_uint()) // no overflows here\n continue rest\n }\n ['_', .. rest] => continue rest\n s => break (s, x, len)\n }\n }\n}\n\n///|\nfn parse_scientific(s : StringView) -> (StringView, Int64)? {\n let mut s = s\n let exp_num = 0L\n let mut neg_exp = false\n if s is ['+' | '-' as ch, .. rest] {\n neg_exp = ch == '-'\n s = rest\n }\n if s is ['0'..='9', ..] {\n let (s, exp_num, _) = s.fold_digits(exp_num, (digit, exp_num : Int64) => {\n if exp_num < 0x10000L {\n 10L * exp_num + digit.to_int64() // no overflows here\n } else {\n exp_num\n }\n })\n if neg_exp {\n Some((s, -exp_num))\n } else {\n Some((s, exp_num))\n }\n } else {\n None\n }\n}\n\n///|\n/// Parse the number from the string, raising `Failure` if invalid.\nfn parse_number(s : StringView) -> Number? raise {\n let start = s\n\n // handle optional +/- sign\n let (s, negative) = match s {\n ['-', .. rest] => (rest, true)\n ['+', .. rest] | rest => (rest, false)\n }\n if s.is_empty() {\n return None\n }\n\n // parse initial digits before dot\n let (s, mantissa, consumed) = parse_digits(s, 0UL)\n let mut mantissa = mantissa\n let mut s = s\n let mut n_digits = consumed\n\n // handle dot with the following digits\n let mut n_after_dot = 0\n let mut exponent = 0L\n if s is ['.', .. rest] {\n s = rest\n // TODO: optimization chance. In the original Rust implementation,\n // the digits are stored as consecutive bytes in the string.\n // It directly reads 8 bytes to `u64`.\n let (new_s, new_mantissa, consumed_digit) = parse_digits(s, mantissa)\n s = new_s\n mantissa = new_mantissa\n n_after_dot = consumed_digit\n exponent = -n_after_dot.to_int64()\n }\n n_digits += n_after_dot\n if n_digits == 0 {\n return None\n }\n\n // handle scientific format\n let exp_number = 0L\n if s is ['e' | 'E', .. rest] {\n let (new_s, exp_number) = match parse_scientific(rest) {\n Some(res) => res\n None => return None\n }\n s = new_s\n exponent += exp_number\n }\n guard s is \"\" else { syntax_err() }\n\n // handle uncommon case with many digits\n if n_digits <= 19 {\n return Some({ exponent, mantissa, negative, many_digits: false })\n }\n n_digits -= 19\n let mut many_digits = false\n for s = start {\n match s {\n ['0' | '.' as ch, .. rest] => {\n n_digits -= (ch.to_int() - 46) / 2 // '0' = b'.' + 2\n continue rest\n }\n _ => break\n }\n }\n let mut mantissa = mantissa\n if n_digits > 0 {\n // at this point we have more than 19 significant digits, let's try again\n many_digits = true\n mantissa = 0UL\n let s = start\n let (s, new_mantissa, consumed_digit) = try_parse_19digits(s, mantissa)\n mantissa = new_mantissa\n exponent = (if mantissa >= min_19digit_int {\n consumed_digit // big int\n } else {\n // fractional component, skip the '.'\n guard s is [_, .. s] else { return None }\n let (_, new_mantissa, consumed_digit) = try_parse_19digits(s, mantissa)\n mantissa = new_mantissa\n consumed_digit\n }).to_int64()\n exponent += exp_number\n } // add back the explicit part\n Some({ exponent, mantissa, negative, many_digits })\n}\n\n///|\n/// Parse the number from the string, raising `Failure` if invalid.\nfn parse_inf_nan(rest : StringView) -> Double raise {\n let (pos, rest) = match rest {\n ['-', .. rest] => (false, rest)\n ['+', .. rest] | rest => (true, rest)\n }\n lexmatch rest with longest {\n \"(?i:nan)\" => @double.not_a_number\n \"(?i:inf(inity)?)\" =>\n if pos {\n @double.infinity\n } else {\n @double.neg_infinity\n }\n _ => syntax_err()\n }\n}\n\n///|\n/// Returns None if the multiplication might overflow (there are some false-negative corner cases).\n/// Otherwise, returns Some(m), where m = self * b.\n/// WARNING: Note this function is only used internally in the strconv module,\n/// the current implementation is not completely safe against overflows.\nfn checked_mul(a : UInt64, b : UInt64) -> UInt64? {\n if a == 0UL || b == 0UL {\n return Some(0UL)\n }\n if a == 1UL {\n return Some(b)\n }\n if b == 1UL {\n return Some(a)\n }\n // Can only multiply by 1 or 0, which is handled above.\n if b.clz() == 0 || a.clz() == 0 {\n return None\n }\n let quotient : UInt64 = @uint64.MAX_VALUE / b\n if a > quotient {\n return None\n }\n Some(a * b)\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nconst INT_MIN = 0x80000000\n\n///|\nconst INT_MAX = 0x7fffffff\n\n///|\nconst INT64_MIN = -0x8000000000000000L\n\n///|\nconst INT64_MAX = 0x7fffffffffffffffL\n\n///|\n/// This function check whether the prefix of the string is consistent with the given base,\n/// and consume the prefix.\n/// The boolean flag `allow_underscore` is used to check validity of underscores.\nfn check_and_consume_base(\n view : StringView,\n base : Int,\n) -> (Int, StringView, Bool) raise {\n // if the base is not given, we need to determine it from the prefix\n if base == 0 {\n match view {\n ['0', 'x' | 'X', .. rest] => (16, rest, true)\n ['0', 'o' | 'O', .. rest] => (8, rest, true)\n ['0', 'b' | 'B', .. rest] => (2, rest, true)\n _ => (10, view, false)\n }\n } else {\n // if the base is given, we need to check whether the prefix is consistent with it\n match view {\n ['0', 'x' | 'X', .. rest] if base == 16 => (16, rest, true)\n ['0', 'o' | 'O', .. rest] if base == 8 => (8, rest, true)\n ['0', 'b' | 'B', .. rest] if base == 2 => (2, rest, true)\n _ => if base is (2..=36) { (base, view, false) } else { base_err() }\n }\n }\n}\n\n///|\ntest {\n assert_true(\n (try? parse_int64(\"0b01\", base=3)) is Err(Failure(\"invalid syntax\")),\n )\n assert_true(\n (try? parse_int64(\"0x01\", base=3)) is Err(Failure(\"invalid syntax\")),\n )\n assert_true(\n (try? parse_int64(\"0o01\", base=3)) is Err(Failure(\"invalid syntax\")),\n )\n}\n\n///|\n/// Parses a string into an Int64 number using the specified base, or returns an error.\n/// The base must be 0 or between 2 and 36 (inclusive). If base is 0, it will be\n/// inferred from the string prefix:\n/// - \"0x\" or \"0X\" for base 16 (hex)\n/// - \"0o\" or \"0O\" for base 8 (octal)\n/// - \"0b\" or \"0B\" for base 2 (binary)\n/// - Default is base 10 (decimal)\n/// For readability, underscores may appear after base prefixes or between digits.\n/// These underscores do not affect the value.\n/// Examples:\n/// ```mbt check\n/// test {\n/// inspect(@strconv.parse_int64(\"123\"), content=\"123\")\n/// inspect(@strconv.parse_int64(\"0xff\", base=0), content=\"255\")\n/// inspect(@strconv.parse_int64(\"0o10\"), content=\"8\")\n/// inspect(@strconv.parse_int64(\"0b1010\"), content=\"10\")\n/// inspect(@strconv.parse_int64(\"1_234\"), content=\"1234\")\n/// inspect(@strconv.parse_int64(\"-123\"), content=\"-123\")\n/// inspect(@strconv.parse_int64(\"ff\", base=16), content=\"255\")\n/// inspect(@strconv.parse_int64(\"zz\", base=36), content=\"1295\")\n/// }\n/// ```\n///\npub fn parse_int64(str : StringView, base? : Int = 0) -> Int64 raise {\n guard str != \"\" else { syntax_err() }\n let (neg, rest) = match str.view() {\n ['+', .. rest] => (false, rest)\n ['-', .. rest] => (true, rest)\n rest => (false, rest)\n }\n\n // `allow_underscore` is used to check validity of underscores\n let (num_base, rest, allow_underscore) = check_and_consume_base(rest, base)\n\n // calculate overflow threshold\n let overflow_threshold = overflow_threshold(num_base, neg)\n let has_digit = rest\n is (['0'..='9' | 'a'..='z' | 'A'..='Z', ..]\n | ['_', '0'..='9' | 'a'..='z' | 'A'..='Z', ..])\n guard has_digit else { syntax_err() }\n // convert\n for rest = rest, acc = 0L, allow_underscore = allow_underscore {\n match (rest, acc, allow_underscore) {\n (['_'], _, _) =>\n // the last character cannot be underscore\n syntax_err()\n (['_', ..], _, false) => syntax_err()\n (['_', .. rest], acc, true) => continue rest, acc, false\n ([c, .. rest], acc, _) => {\n let c = c.to_int()\n let d = match c {\n '0'..='9' => c - '0'\n 'a'..='z' => c + (10 - 'a')\n 'A'..='Z' => c + (10 - 'A')\n _ => syntax_err()\n }\n guard d < num_base else { syntax_err() }\n if neg {\n guard acc >= overflow_threshold else { range_err() }\n let next_acc = acc * num_base.to_int64() - d.to_int64()\n guard next_acc <= acc else { range_err() }\n continue rest, next_acc, true\n } else {\n guard acc < overflow_threshold else { range_err() }\n let next_acc = acc * num_base.to_int64() + d.to_int64()\n guard next_acc >= acc else { range_err() }\n continue rest, next_acc, true\n }\n }\n ([], acc, _) => break acc\n }\n }\n}\n\n///|\n/// Parse a string in the given base (0, 2 to 36), return a Int number or an error.\n/// If the `base` argument is 0, the base will be inferred by the prefix.\npub fn parse_int(str : StringView, base? : Int = 0) -> Int raise {\n let n = parse_int64(str, base~)\n if n < INT_MIN.to_int64() || n > INT_MAX.to_int64() {\n range_err()\n }\n n.to_int()\n}\n\n// Check whether the underscores are correct.\n// Underscores must appear only between digits or between a base prefix and a digit.\n\n///|\nfn check_underscore(str : StringView) -> Bool {\n // skip the sign\n let rest = match str {\n ['+' | '-', .. rest] => rest\n rest => rest\n // CR: the type maybe a bit confusing?\n }\n\n // base prefix\n let (rest, allow_underscore, hex) = lexmatch rest with longest {\n (\"0[xX]\", rest) => (rest, true, true)\n (\"0[oO]\", rest) => (rest, true, false)\n (\"0[bB]\", rest) => (rest, true, false)\n _ => (rest, false, false)\n }\n\n // 'e' and 'E' are valid hex digits\n // but are not treated as digits in decimal strings since they're used for scientific notation\n fn is_digit(c : Char) -> Bool {\n c is ('0'..='9') || (hex && c is ('a'..='f' | 'A'..='F'))\n }\n\n // Track whether the previous character was an underscore\n let follow_underscore = false\n for rest = rest, allow_underscore = allow_underscore, follow_underscore = follow_underscore {\n match (rest, allow_underscore, follow_underscore) {\n // Empty string is valid\n ([], _, _) => break true\n // String ending with underscore is invalid\n (['_'], _, _) => break false\n // Underscore not allowed in current position (e.g., between non-digits)\n (['_', ..], false, _) => break false\n // Valid underscore - continue but mark that next char must be a digit\n (['_', .. rest], true, _) => continue rest, false, true\n // Handle non-underscore character\n ([c, .. rest], _, follow_underscore) =>\n if is_digit(c) {\n // Digit found - allow underscore in next position\n continue rest, true, false\n } else if follow_underscore {\n // Non-digit found after underscore - invalid\n break false\n } else {\n // Non-digit found (not after underscore) - continue but don't allow underscores\n continue rest, false, false\n }\n }\n }\n}\n\n///|\nfn overflow_threshold(base : Int, neg : Bool) -> Int64 {\n if !neg {\n if base == 10 {\n INT64_MAX / 10L + 1L\n } else if base == 16 {\n INT64_MAX / 16L + 1L\n } else {\n INT64_MAX / base.to_int64() + 1L\n }\n } else if base == 10 {\n INT64_MIN / 10L\n } else if base == 16 {\n INT64_MIN / 16L\n } else {\n INT64_MIN / base.to_int64()\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn offset_to_position(input : StringView, offset : Int) -> Position {\n for i in 0..<offset; line = 1, column = 0 {\n if input.unsafe_get(i) == '\\n' {\n continue line + 1, 0\n } else {\n continue line, column + 1\n }\n } nobreak {\n Position::{ line, column }\n }\n}\n\n///|\nfn[T] ParseContext::invalid_char(\n ctx : ParseContext,\n shift? : Int = 0,\n) -> T raise ParseError {\n let offset = ctx.offset + shift\n let replacement_char : Char = '\\u{fffd}'\n raise InvalidChar(\n offset_to_position(ctx.input, offset),\n ctx.input.get_char(offset).unwrap_or(replacement_char),\n )\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Type `Position` used by this package APIs.\npub(all) struct Position {\n line : Int // 1-based\n column : Int // 0-based\n} derive(Eq, ToJson, @debug.Debug)\n\n///|\n/// Error type `ParseError`.\npub(all) suberror ParseError {\n InvalidChar(Position, Char)\n InvalidEof\n InvalidNumber(Position, String)\n InvalidIdentEscape(Position)\n DepthLimitExceeded\n} derive(Eq, ToJson, @debug.Debug)\n\n///|\npub impl Show for ParseError with output(self, logger) {\n match self {\n InvalidChar({ line, column }, c) => {\n logger.write_string(\"Invalid character \")\n logger.write_string(c.escape())\n logger.write_string(\" at line \")\n logger.write_object(line)\n logger.write_string(\", column \")\n logger.write_object(column)\n }\n InvalidEof => logger.write_string(\"Unexpected end of file\")\n InvalidNumber({ line, column }, s) => {\n logger.write_string(\"Invalid number \")\n logger.write_string(s)\n logger.write_string(\" at line \")\n logger.write_object(line)\n logger.write_string(\", column \")\n logger.write_object(column)\n }\n InvalidIdentEscape({ line, column }) => {\n logger.write_string(\"Invalid escape sequence in identifier at line \")\n logger.write_object(line)\n logger.write_string(\", column \")\n logger.write_object(column)\n }\n DepthLimitExceeded =>\n logger.write_string(\n \"Depth limit exceeded, please increase the max_nesting_depth parameter\",\n )\n }\n}\n\n///|\n#deprecated(\"Use Debug instead of Show for debugging purposes. See https://github.com/moonbitlang/core/blob/main/debug/README.mbt.md\")\npub impl Show for Json\n\n///|\n#warnings(\"-deprecated\")\npub impl Show for Json with output(self, logger) {\n match self {\n Null => logger.write_string(\"Null\")\n True => logger.write_string(\"True\")\n False => logger.write_string(\"False\")\n Number(n, repr~) => {\n logger.write_string(\"Number(\")\n Show::output(n, logger)\n if repr is Some(repr) {\n logger.write_string(\", repr=\")\n logger.write_string(\"Some(\")\n Show::output(repr, logger)\n logger.write_string(\")\")\n }\n logger.write_string(\")\")\n }\n String(s) => {\n logger.write_string(\"String(\")\n Show::output(s, logger)\n logger.write_string(\")\")\n }\n Array(a) => {\n logger.write_string(\"Array(\")\n Show::output(a, logger)\n logger.write_string(\")\")\n }\n Object(o) => {\n logger.write_string(\"Object(\")\n Show::output(o, logger)\n logger.write_string(\")\")\n }\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Error type `JsonDecodeError`.\n#warnings(\"-deprecated_syntax\")\npub(all) suberror JsonDecodeError {\n JsonDecodeError((JsonPath, String))\n} derive(Eq, Show, ToJson, @debug.Debug)\n\n///|\n/// Trait for types that can be converted from `Json`\npub(open) trait FromJson {\n from_json(Json, JsonPath) -> Self raise JsonDecodeError\n}\n\n///|\n/// Create from `json`.\npub fn[T : FromJson] from_json(\n json : Json,\n path? : JsonPath = Root,\n) -> T raise JsonDecodeError {\n FromJson::from_json(json, path)\n}\n\n///|\nfn[T] decode_error(path : JsonPath, msg : String) -> T raise JsonDecodeError {\n raise JsonDecodeError((path, msg))\n}\n\n///|\npub impl FromJson for Bool with from_json(json, path) {\n match json {\n true => true\n false => false\n _ => decode_error(path, \"Bool::from_json: expected boolean\")\n }\n}\n\n///|\npub impl FromJson for Int with from_json(json, path) {\n guard json is Number(n, ..) &&\n n != @double.infinity &&\n n != @double.neg_infinity else {\n decode_error(path, \"Int::from_json: expected number\")\n }\n // Range check before conversion to avoid silent wrap/truncation\n let max_ok = 2147483647.0\n let min_ok = -2147483648.0\n if n > max_ok || n < min_ok {\n decode_error(path, \"Int::from_json: overflow\")\n }\n n.to_int()\n}\n\n///|\n\n///|\npub impl FromJson for Int64 with from_json(json, path) {\n guard json is String(str) else {\n decode_error(\n path, \"Int64::from_json: expected number in string representation\",\n )\n }\n @internal/strconv.parse_int64(str) catch {\n Failure::Failure(error) =>\n decode_error(path, \"Int64::from_json: parsing failure \\{error}\")\n error => decode_error(path, \"Int64::from_json: parsing failure \\{error}\")\n }\n}\n\n///|\npub impl FromJson for UInt with from_json(json, path) {\n guard json is Number(n, ..) &&\n n != @double.infinity &&\n n != @double.neg_infinity else {\n decode_error(path, \"UInt::from_json: expected number\")\n }\n // Range check before conversion to avoid silent wrap/truncation\n let max_ok = 4294967295.0\n if n < 0.0 || n > max_ok {\n decode_error(path, \"UInt::from_json: overflow\")\n }\n n.to_uint()\n}\n\n///|\n\n///|\npub impl FromJson for UInt64 with from_json(json, path) {\n guard json is String(str) else {\n decode_error(\n path, \"UInt64::from_json: expected number in string representation\",\n )\n }\n @internal/strconv.parse_uint64(str) catch {\n Failure::Failure(error) =>\n decode_error(path, \"UInt64::from_json: parsing failure \\{error}\")\n error => decode_error(path, \"UInt64::from_json: parsing failure \\{error}\")\n }\n}\n\n///|\npub impl FromJson for Double with from_json(json, path) {\n match json {\n String(\"NaN\") => @double.not_a_number\n String(\"Infinity\") => @double.infinity\n String(\"-Infinity\") => @double.neg_infinity\n Number(n, ..) if n != @double.infinity && n != @double.neg_infinity => n\n _ => decode_error(path, \"Double::from_json: expected number\")\n }\n}\n\n///|\npub impl FromJson for Float with from_json(json, path) {\n match json {\n String(\"NaN\") => @float.not_a_number\n String(\"Infinity\") => @float.infinity\n String(\"-Infinity\") => @float.neg_infinity\n Number(n, ..) if n != @double.infinity && n != @double.neg_infinity =>\n Float::from_double(n)\n _ => decode_error(path, \"Float::from_json: expected number\")\n }\n}\n\n///|\npub impl FromJson for String with from_json(json, path) {\n guard json is String(a) else {\n decode_error(path, \"String::from_json: expected string\")\n }\n a\n}\n\n///|\npub impl FromJson for StringView with from_json(json, path) {\n guard json is String(a) else {\n decode_error(path, \"View::from_json: expected string\")\n }\n a\n}\n\n///|\npub impl FromJson for Char with from_json(json, path) {\n guard json is String(a) else {\n decode_error(path, \"Char::from_json: expected string\")\n }\n let len = a.length()\n if len == 1 {\n a.unsafe_get(0).unsafe_to_char()\n } else if len == 2 {\n let c1 = a.unsafe_get(0).to_int()\n let c2 = a.unsafe_get(1).to_int()\n if c1 is (0xD800..=0xDBFF) && c2 is (0xDC00..=0xDFFF) {\n let c3 = (c1 << 10) + c2 - 0x35fdc00\n c3.unsafe_to_char()\n } else {\n decode_error(path, \"Char::from_json: invalid surrogate pair\")\n }\n } else {\n decode_error(path, \"Char::from_json: expected single character\")\n }\n}\n\n///|\npub impl[X : FromJson] FromJson for Array[X] with from_json(json, path) {\n guard json is Array(a) else {\n decode_error(path, \"Array::from_json: expected array\")\n }\n guard JsonPath::Index(path, index=0) is (Index(_) as new_path)\n a.mapi((i, x) => {\n new_path.index = i\n FromJson::from_json(x, new_path)\n })\n}\n\n///|\npub impl[X : FromJson] FromJson for ArrayView[X] with from_json(json, path) {\n guard json is Array(a) else {\n decode_error(path, \"ArrayView::from_json: expected array\")\n }\n guard JsonPath::Index(path, index=0) is (Index(_) as new_path)\n a.mapi((i, x) => {\n new_path.index = i\n FromJson::from_json(x, new_path)\n })\n}\n\n///|\npub impl[X : FromJson] FromJson for FixedArray[X] with from_json(json, path) {\n guard json is Array(a) else {\n decode_error(path, \"FixedArray::from_json: expected array\")\n }\n let len = a.length()\n if len == 0 {\n return []\n }\n guard JsonPath::Index(path, index=0) is (Index(_) as new_path)\n let res = FixedArray::make(\n len,\n FromJson::from_json(a.unsafe_get(0), new_path),\n )\n for i in 1..<len {\n new_path.index = i\n res[i] = FromJson::from_json(a.unsafe_get(i), new_path)\n }\n res\n}\n\n///|\npub impl[V : FromJson] FromJson for Map[String, V] with from_json(json, path) {\n // Note in theory, we can make it more general like\n // Map[K : FromString, V : FromJson]\n // but currently we don't have FromString \n // Here ToJson we have \n // Map[K : Show, V : ToJson]\n guard json is Object(obj) else {\n decode_error(path, \"Map::from_json: expected object\")\n }\n let res = {}\n guard JsonPath::Key(path, key=\"\") is (Key(_) as new_path)\n // Map::map_with_key\n for k, v in obj {\n new_path.key = k\n res[k] = FromJson::from_json(v, new_path)\n }\n res\n}\n\n///|\npub impl[T : FromJson] FromJson for T? with from_json(json, path) {\n match json {\n Null => None\n Array([value]) => Some(FromJson::from_json(value, path.add_index(0)))\n _ => decode_error(path, \"Option::from_json: expected array or null\")\n }\n}\n\n///|\npub impl[Ok : FromJson, Err : FromJson] FromJson for Result[Ok, Err] with from_json(\n json,\n path,\n) {\n guard json is Object(obj) else {\n decode_error(path, \"Result::from_json: expected object\")\n }\n if obj.length() != 1 {\n decode_error(path, \"Result::from_json: expected object with one field\")\n }\n match obj {\n { \"Ok\": ok, .. } => Ok(FromJson::from_json(ok, path.add_key(\"Ok\")))\n { \"Err\": err, .. } => Err(FromJson::from_json(err, path.add_key(\"Err\")))\n _ =>\n decode_error(\n path, \"Result::from_json: expected object with Ok or Err field\",\n )\n }\n}\n\n///|\npub impl FromJson for Unit with from_json(json, path) {\n guard json is Null else {\n decode_error(path, \"Unit::from_json: expected null\")\n }\n}\n\n///|\npub impl FromJson for Json with from_json(json, _path) {\n json\n}\n\n///|\n/// Converts a JSON string to `Bytes`.\n/// \n/// The expected string format consists of:\n/// - Hexadecimal byte sequences represented as `\\xNN`, where `NN` are two hex digits.\n/// - Printable ASCII characters (except `\\` and `\"`), which are directly converted to their byte values.\n/// - Any invalid escape sequence or character will result in a `JsonDecodeError`.\n/// \n/// Example valid input: `\"hello\\\\x20world\"` (where `\\\\x20` is a space character).\npub impl FromJson for Bytes with from_json(json, path) {\n guard json is String(a) else {\n decode_error(path, \"Bytes::from_json: expected string\")\n }\n let buffer = @buffer.Buffer(size_hint=a.length())\n for x = a[:] {\n match x {\n [] => break\n [\n .. \"\\\\x\",\n '0'..='9'\n | 'a'..='f' as x,\n '0'..='9'\n | 'a'..='f' as y,\n .. rest,\n ] => {\n let upper = (x.to_int() & 0xF) + (x.to_int() >> 6) * 9\n let lower = (y.to_int() & 0xF) + (y.to_int() >> 6) * 9\n buffer.write_byte(((upper << 4) | lower).to_byte())\n continue rest\n }\n [' '..='~' as ch, .. rest] => {\n guard ch != '\\\\' && ch != '\"' else {\n decode_error(path, \"Bytes::from_json: invalid escape sequence\")\n }\n buffer.write_byte(ch.to_uint().to_byte())\n continue rest\n }\n _ => decode_error(path, \"Bytes::from_json: invalid byte sequence\")\n }\n }\n buffer.to_bytes()\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nenum JsonPath {\n Root\n Key(JsonPath, mut key~ : String)\n Index(JsonPath, mut index~ : Int)\n} derive(Eq, @debug.Debug)\n\n///|\n/// Appends an array index to the JSON path.\npub fn JsonPath::add_index(self : JsonPath, index : Int) -> JsonPath {\n Index(self, index~)\n}\n\n///|\n/// Appends an object key to the JSON path.\npub fn JsonPath::add_key(self : JsonPath, key : String) -> JsonPath {\n Key(self, key~)\n}\n\n///|\npub impl Show for JsonPath with output(self, logger) {\n // Helper to write a JSON Pointer token without intermediate allocations\n fn write_token(logger : &Logger, token : String) -> Unit {\n if !token.contains_any(chars=\"~/\") {\n logger.write_string(token)\n return\n }\n for ch in token.iter() {\n match ch {\n '~' => logger.write_string(\"~0\")\n '/' => logger.write_string(\"~1\")\n _ => logger.write_char(ch)\n }\n }\n }\n\n // Recursively build the JSON Pointer string\n fn build_path(path : JsonPath, logger : &Logger) -> Unit {\n match path {\n Root => ()\n Key(parent, key~) => {\n build_path(parent, logger)\n logger.write_char('/')\n write_token(logger, key)\n }\n Index(parent, index~) => {\n build_path(parent, logger)\n logger.write_char('/')\n logger.write_object(index)\n }\n }\n }\n\n build_path(self, logger)\n}\n\n///|\npub impl ToJson for JsonPath with to_json(self) {\n String(self.to_string())\n}\n\n///|\ntest \"show JsonPath - JSON Pointer format\" {\n // Test root path\n @builtin.inspect(Root, content=\"\")\n\n // Test simple key access\n @builtin.inspect(Root.add_key(\"foo\"), content=\"/foo\")\n\n // Test simple array index\n @builtin.inspect(Root.add_index(0), content=\"/0\")\n\n // Test mixed path\n let path : JsonPath = Key(Index(Root, index=0), key=\"foo\")\n @builtin.inspect(path, content=\"/0/foo\")\n @builtin.inspect(path.add_index(1), content=\"/0/foo/1\")\n @builtin.inspect(path.add_key(\"bar\"), content=\"/0/foo/bar\")\n\n // Test complex paths\n @builtin.inspect(\n Root.add_key(\"foo\").add_key(\"foo1\").add_index(2),\n content=\"/foo/foo1/2\",\n )\n @builtin.inspect(Root.add_key(\"foo\").add_key(\"foo1\"), content=\"/foo/foo1\")\n @builtin.inspect(\n Root.add_key(\"foo\").add_key(\"foo1\").add_index(2).add_key(\"bar\"),\n content=\"/foo/foo1/2/bar\",\n )\n @builtin.inspect(\n Root.add_key(\"foo\").add_key(\"foo1\").add_index(2).add_key(\"bar\").add_index(3),\n content=\"/foo/foo1/2/bar/3\",\n )\n @builtin.inspect(\n Root\n .add_key(\"foo\")\n .add_key(\"foo1\")\n .add_index(2)\n .add_key(\"bar\")\n .add_index(3)\n .add_key(\"baz\"),\n content=\"/foo/foo1/2/bar/3/baz\",\n )\n @builtin.inspect(\n Root.add_key(\"foo\").add_key(\"foo1\").add_index(2).add_index(3).add_index(4),\n content=\"/foo/foo1/2/3/4\",\n )\n}\n\n///|\ntest \"show JsonPath - special characters escaping\" {\n // Test tilde escaping (~ becomes ~0)\n @builtin.inspect(Root.add_key(\"foo~bar\"), content=\"/foo~0bar\")\n @builtin.inspect(Root.add_key(\"foo~~bar~~\"), content=\"/foo~0~0bar~0~0\")\n\n // Test slash escaping (/ becomes ~1)\n @builtin.inspect(Root.add_key(\"foo/bar\"), content=\"/foo~1bar\")\n @builtin.inspect(Root.add_key(\"foo//bar//\"), content=\"/foo~1~1bar~1~1\")\n\n // Test both special characters\n @builtin.inspect(Root.add_key(\"foo~/bar\"), content=\"/foo~0~1bar\")\n @builtin.inspect(Root.add_key(\"~foo/bar~\"), content=\"/~0foo~1bar~0\")\n\n // Test complex path with special characters\n @builtin.inspect(\n Root.add_key(\"a/b\").add_key(\"c~d\").add_index(0).add_key(\"e~/f\"),\n content=\"/a~1b/c~0d/0/e~0~1f\",\n )\n\n // Test empty string key\n @builtin.inspect(Root.add_key(\"\"), content=\"/\")\n\n // Test key with only special characters\n @builtin.inspect(Root.add_key(\"~/\"), content=\"/~0~1\")\n}\n\n///|\ntest \"show JsonPath - RFC 6901 compliance examples\" {\n // Examples from RFC 6901\n // \"\" // the whole document\n @builtin.inspect(Root, content=\"\")\n\n // \"/foo\" [\"bar\", \"baz\"]\n @builtin.inspect(Root.add_key(\"foo\"), content=\"/foo\")\n\n // \"/foo/0\" \"bar\"\n @builtin.inspect(Root.add_key(\"foo\").add_index(0), content=\"/foo/0\")\n\n // \"/\" \"value\" (empty string key)\n @builtin.inspect(Root.add_key(\"\"), content=\"/\")\n\n // \"/a~1b\" 1 (key is \"a/b\")\n @builtin.inspect(Root.add_key(\"a/b\"), content=\"/a~1b\")\n\n // \"/c%d\" 2 (key is \"c%d\", % doesn't need escaping)\n @builtin.inspect(Root.add_key(\"c%d\"), content=\"/c%d\")\n\n // \"/e^f\" 3 (key is \"e^f\", ^ doesn't need escaping)\n @builtin.inspect(Root.add_key(\"e^f\"), content=\"/e^f\")\n\n // \"/g|h\" 4 (key is \"g|h\", | doesn't need escaping)\n @builtin.inspect(Root.add_key(\"g|h\"), content=\"/g|h\")\n\n // \"/i\\\\j\" 5 (key is \"i\\j\", \\ doesn't need escaping)\n @builtin.inspect(Root.add_key(\"i\\\\j\"), content=\"/i\\\\j\")\n\n // \"/k\\\"l\" 6 (key is \"k\"l\", \" doesn't need escaping)\n @builtin.inspect(Root.add_key(\"k\\\"l\"), content=\"/k\\\"l\")\n\n // \"/ \" 7 (key is \" \", space doesn't need escaping)\n @builtin.inspect(Root.add_key(\" \"), content=\"/ \")\n\n // \"/m~0n\" 8 (key is \"m~n\")\n @builtin.inspect(Root.add_key(\"m~n\"), content=\"/m~0n\")\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn ParseContext::read_char(ctx : ParseContext) -> Char? {\n if ctx.offset < ctx.end_offset {\n let c1 = ctx.input.unsafe_get(ctx.offset).to_int()\n ctx.offset += 1\n if c1 >= 0xD800 && c1 <= 0xDBFF {\n if ctx.offset < ctx.end_offset {\n let c2 = ctx.input.unsafe_get(ctx.offset).to_int()\n if c2 >= 0xDC00 && c2 <= 0xDFFF {\n ctx.offset += 1\n let c3 = (c1 << 10) + c2 - 0x35fdc00\n return Some(c3.unsafe_to_char())\n }\n }\n }\n Some(c1.unsafe_to_char())\n } else {\n None\n }\n}\n\n///|\n/// low surrogate\nconst SURROGATE_LOW_CHAR = 0xD800\n\n///|\n/// high surrogate\nconst SURROGATE_HIGH_CHAR = 0xDFFF\n\n///|\n/// `ctx.expect_char(c)` check the current context is c,\n/// if it is, consume the character and return `()`,\n/// otherwise raise an error, when it is an error, the position is unspecified.\nfn ParseContext::expect_char(\n ctx : ParseContext,\n c : Char,\n) -> Unit raise ParseError {\n guard ctx.offset < ctx.end_offset else { raise InvalidEof }\n let c1 = ctx.input.unsafe_get(ctx.offset).to_int()\n ctx.offset += 1\n let c0 = c.to_int()\n if c0 < 0xFFFF {\n // c0 < SURROGATE_LOW_CHAR || c0 is (0xE000..=0XFFFF) \n // c0 is a valid char so only need check if c0<0xFFFF is BMP code point\n if c0 != c1 {\n ctx.invalid_char(shift=-1)\n }\n } else {\n // c0 is not bmp code point\n // c1 has to be surrogate pair otherwise it is invalid\n guard c1 is (SURROGATE_LOW_CHAR..=SURROGATE_HIGH_CHAR) &&\n ctx.offset < ctx.end_offset else {\n ctx.invalid_char(shift=-1)\n }\n let c2 = ctx.input.unsafe_get(ctx.offset).to_int()\n let c3 = (c1 << 10) + c2 - 0x35fdc00\n if c3 != c0 {\n ctx.invalid_char(shift=-1)\n } else {\n ctx.offset += 1 // consume and move forward\n }\n }\n}\n\n///|\n/// `ctx.expect_ascii_char(c)` check the current context is c,\n/// \nfn ParseContext::expect_ascii_char(\n ctx : ParseContext,\n c : Byte,\n) -> Unit raise ParseError {\n guard ctx.offset < ctx.end_offset else { raise InvalidEof }\n let c1 = ctx.input.unsafe_get(ctx.offset).to_int()\n ctx.offset += 1\n if c.to_int() != c1 {\n ctx.invalid_char(shift=-1)\n }\n}\n\n///|\ntest \"expect_char\" {\n let ctx = ParseContext::make(\"abc\", 1)\n ctx.expect_char('a')\n ctx.expect_char('b')\n ctx.expect_char('c')\n json_inspect(try? ctx.expect_char('d'), content={ \"Err\": \"InvalidEof\" })\n}\n\n///|\ntest \"expect_char with surrogate pair\" {\n // \"\\uD83D\\uDE00\" // todo: shall we allow this?\n let ctx = ParseContext::make(\"a\\u{1F600}bc\\u{1F600}c\", 1)\n ctx.expect_char('a')\n ctx.expect_char((0x1F600).unsafe_to_char())\n ctx.expect_char('b')\n ctx.expect_char('c')\n ctx.expect_char((0x1F600).unsafe_to_char())\n ctx.expect_char('c')\n json_inspect(try? ctx.expect_char('d'), content={ \"Err\": \"InvalidEof\" })\n}\n\n///|\nfn ParseContext::lex_skip_whitespace(ctx : ParseContext) -> Unit {\n let rest = ctx.input.view(start_offset=ctx.offset, end_offset=ctx.end_offset)\n lexmatch rest with longest {\n (\"[ \\t\\r\\n]+\", next) => ctx.offset = ctx.end_offset - next.length()\n _ => ()\n }\n}\n\n///|\nfn ParseContext::lex_after_array_value(\n ctx : ParseContext,\n) -> Token raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some(']') => RBracket\n Some(',') => Comma\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n}\n\n///|\nfn ParseContext::lex_after_property_name(\n ctx : ParseContext,\n) -> Unit raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some(':') => ()\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n}\n\n///|\nfn ParseContext::lex_after_object_value(\n ctx : ParseContext,\n) -> Token raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some('}') => RBrace\n Some(',') => Comma\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n}\n\n///|\n/// In the context of `{`, try to lex token `}` or a property name,\n/// otherwise raise an error.\nfn ParseContext::lex_property_name(\n ctx : ParseContext,\n) -> Token raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some('}') => RBrace\n Some('\"') => {\n let s = ctx.lex_string()\n String(s)\n }\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n}\n\n///|\n/// In the context of `{ ...,` try to lex a property name,\n/// otherwise raise an error.\n/// since it is in comma context, `}` is not allowed.\nfn ParseContext::lex_property_name2(\n ctx : ParseContext,\n) -> Token raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some('\"') => {\n let s = ctx.lex_string()\n String(s)\n }\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\npriv struct ParseContext {\n mut offset : Int\n input : StringView\n end_offset : Int\n mut remaining_available_depth : Int\n}\n\n///|\nfn ParseContext::make(\n input : StringView,\n max_nesting_depth : Int,\n) -> ParseContext {\n {\n offset: 0,\n input,\n end_offset: input.length(),\n remaining_available_depth: max_nesting_depth,\n }\n}\n\n///|\npriv enum Token {\n Null\n True\n False\n Number(Double, String?)\n String(String)\n LBrace\n RBrace\n LBracket\n RBracket\n Comma\n // Colon\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn ParseContext::lex_string(ctx : ParseContext) -> String raise ParseError {\n let string_start = ctx.offset\n // Fast path for ordinary strings: scan raw UTF-16 code units and materialize\n // the slice directly when there are no escapes or control characters.\n for i = string_start; i < ctx.end_offset; i = i + 1 {\n let c = ctx.input.unsafe_get(i)\n if c == '\"' {\n ctx.offset = i + 1\n return ctx.input.view(start_offset=string_start, end_offset=i).to_owned()\n } else if c == '\\\\' {\n return ctx.lex_string_slow()\n } else if c == '\\n' || c == '\\r' || c.to_int() < 32 {\n ctx.offset = i + 1\n ctx.invalid_char(shift=-1)\n }\n }\n raise InvalidEof\n}\n\n///|\nfn ParseContext::lex_string_slow(ctx : ParseContext) -> String raise ParseError {\n let buf = StringBuilder()\n let mut start = ctx.offset\n fn flush(end : Int) {\n if start > 0 && end > start {\n buf.write_view(ctx.input[start:end])\n }\n }\n\n for ;; {\n match ctx.read_char() {\n Some('\"') => {\n flush(ctx.offset - 1)\n break\n }\n Some('\\n' | '\\r') => ctx.invalid_char(shift=-1)\n Some('\\\\') => {\n flush(ctx.offset - 1)\n match ctx.read_char() {\n Some('b') => buf.write_char('\\b')\n Some('f') => buf.write_char('\\u{0C}')\n Some('n') => buf.write_char('\\n')\n Some('r') => buf.write_char('\\r')\n Some('t') => buf.write_char('\\t')\n Some('\"') => buf.write_char('\"')\n Some('\\\\') => buf.write_char('\\\\')\n Some('/') => buf.write_char('/')\n Some('u') => {\n let c = ctx.lex_hex_digits(4)\n buf.write_char(c.unsafe_to_char())\n }\n Some(_) => ctx.invalid_char(shift=-1)\n None => raise InvalidEof\n }\n start = ctx.offset\n }\n Some(ch) =>\n if ch.to_int() < 32 {\n ctx.invalid_char(shift=-1)\n } else {\n continue\n }\n None => raise InvalidEof\n }\n }\n buf.to_string()\n}\n\n///|\nfn ParseContext::lex_hex_digits(\n ctx : ParseContext,\n n : Int,\n) -> Int raise ParseError {\n for _ in 0..<n; r = 0 {\n match ctx.read_char() {\n Some(c) =>\n if c >= 'A' {\n let d = (c.to_int() & (32).lnot()) - 'A'.to_int() + 10\n if d > 15 {\n ctx.invalid_char(shift=-1)\n }\n continue (r << 4) | d\n } else if c >= '0' {\n let d = c.to_int() - '0'.to_int()\n if d > 9 {\n ctx.invalid_char(shift=-1)\n }\n continue (r << 4) | d\n } else {\n ctx.invalid_char(shift=-1)\n }\n None => raise InvalidEof\n }\n } nobreak {\n r\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\nfn ParseContext::lex_value(\n ctx : ParseContext,\n allow_rbracket~ : Bool,\n) -> Token raise ParseError {\n ctx.lex_skip_whitespace()\n match ctx.read_char() {\n Some('{') => return LBrace\n Some('[') => return LBracket\n Some(']') =>\n if allow_rbracket {\n return RBracket\n } else {\n ctx.invalid_char(shift=-1)\n }\n Some('n') => {\n ctx.expect_ascii_char(b'u')\n ctx.expect_ascii_char(b'l')\n ctx.expect_ascii_char(b'l')\n return Null\n }\n Some('t') => {\n ctx.expect_ascii_char(b'r')\n ctx.expect_ascii_char(b'u')\n ctx.expect_ascii_char(b'e')\n return True\n }\n Some('f') => {\n ctx.expect_ascii_char(b'a')\n ctx.expect_ascii_char(b'l')\n ctx.expect_ascii_char(b's')\n ctx.expect_ascii_char(b'e')\n return False\n }\n Some('-') =>\n match ctx.read_char() {\n Some('0') => {\n let (n, repr) = ctx.lex_zero(start=ctx.offset - 2)\n return Number(n, repr.map(repr => repr.to_owned()))\n }\n Some(c2) => {\n if c2 is ('1'..='9') {\n let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 2)\n return Number(n, repr.map(repr => repr.to_owned()))\n }\n ctx.invalid_char(shift=-1)\n }\n None => raise InvalidEof\n }\n Some('0') => {\n let (n, repr) = ctx.lex_zero(start=ctx.offset - 1)\n return Number(n, repr.map(repr => repr.to_owned()))\n }\n Some('1'..='9') => {\n let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 1)\n return Number(n, repr.map(repr => repr.to_owned()))\n }\n Some('\"') => {\n let s = ctx.lex_string()\n return String(s)\n }\n Some(c) => {\n let shift = -c.utf16_len()\n ctx.invalid_char(shift~)\n }\n None => raise InvalidEof\n }\n}\n","// Copyright 2026 International Digital Economy Academy\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n///|\n/// Validate input and return whether it is valid.\npub fn valid(input : StringView) -> Bool {\n try {\n parse(input) |> ignore\n true\n } catch {\n _ => return false\n }\n}\n\n///|\n/// Parse a JSON input string into a Json value, with an optional maximum nesting depth (default is 1024)\n#label_migration(max_nesting_depth, fill=false)\npub fn parse(\n input : StringView,\n max_nesting_depth? : Int = 1024,\n) -> Json raise ParseError {\n let ctx = ParseContext::make(input, max_nesting_depth)\n let val = ctx.parse_value()\n ctx.lex_skip_whitespace()\n if ctx.offset >= ctx.end_offset {\n val\n } else {\n ctx.invalid_char()\n }\n}\n\n///|\nfn ParseContext::parse_value(ctx : ParseContext) -> Json raise ParseError {\n let tok = ctx.lex_value(allow_rbracket=false)\n ctx.parse_value2(tok)\n}\n\n///|\nfn ParseContext::parse_value2(\n ctx : ParseContext,\n tok : Token,\n) -> Json raise ParseError {\n match tok {\n Null => null\n True => Json::boolean(true)\n False => Json::boolean(false)\n Number(n, repr) => Json::number(n, repr?)\n String(s) => Json::string(s)\n LBrace => ctx.parse_object()\n LBracket => ctx.parse_array()\n RBracket | RBrace | Comma => abort(\"unreachable\")\n }\n}\n\n///|\nfn ParseContext::parse_object(ctx : ParseContext) -> Json raise ParseError {\n if ctx.remaining_available_depth <= 0 {\n raise DepthLimitExceeded\n }\n ctx.remaining_available_depth -= 1\n let map = Map([])\n for x = ctx.lex_property_name() {\n match x {\n RBrace => {\n ctx.remaining_available_depth += 1\n break Json::object(map)\n }\n String(name) => {\n ctx.lex_after_property_name()\n map[name] = ctx.parse_value()\n match ctx.lex_after_object_value() {\n Comma => continue ctx.lex_property_name2()\n RBrace => {\n ctx.remaining_available_depth += 1\n break Json::object(map)\n }\n _ => abort(\"unreachable\")\n }\n }\n _ => abort(\"unreachable\")\n }\n }\n}\n\n///|\nfn ParseContext::parse_array(ctx : ParseContext) -> Json raise ParseError {\n if ctx.remaining_available_depth <= 0 {\n raise DepthLimitExceeded\n }\n ctx.remaining_available_depth -= 1\n let vec = []\n for x = ctx.lex_value(allow_rbracket=true) {\n match x {\n RBracket => {\n ctx.remaining_available_depth += 1\n break Json::array(vec)\n }\n tok => {\n vec.push(ctx.parse_value2(tok))\n let tok2 = ctx.lex_after_array_value()\n match tok2 {\n Comma => continue ctx.lex_value(allow_rbracket=false)\n RBracket => {\n ctx.remaining_available_depth += 1\n break Json::array(vec)\n }\n _ => abort(\"unreachable\")\n }\n }\n }\n }\n}\n","///|\npub(all) struct InlineRun {\n text : String\n marks : Array[String]\n href : String?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct ListItem {\n blocks : Array[Block]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct TableColumn {\n key : String\n header : String\n align : String?\n width : Json?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct TableCell {\n text : String\n colspan : Int?\n rowspan : Int?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum Block {\n Heading(id~ : String, level~ : Int, content~ : Array[InlineRun])\n Paragraph(id~ : String, content~ : Array[InlineRun])\n List(id~ : String, ordered~ : Bool, items~ : Array[ListItem])\n Code(id~ : String, language~ : String?, source~ : String)\n Table(\n id~ : String,\n columns~ : Array[TableColumn],\n rows~ : Array[Array[TableCell]],\n caption~ : String?\n )\n Mermaid(id~ : String, source~ : String, caption~ : String?)\n Excalidraw(\n id~ : String,\n elements~ : Array[Json],\n app_state~ : Map[String, Json]?,\n files~ : Map[String, Json]?,\n svg~ : String?,\n caption~ : String?\n )\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PapyrDocument {\n id : String\n title : String?\n blocks : Array[Block]\n meta : Json?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct Diagnostic {\n kind : String\n code : String\n path : String\n message : String\n expected : String?\n received : String?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\nfn path_join(base : String, segment : String) -> String {\n if base == \"\" {\n segment\n } else if segment == \"\" {\n base\n } else {\n base + \".\" + segment\n }\n}\n\n///|\nfn missing_field(path : String, field : String) -> Diagnostic {\n {\n kind: \"validation\",\n code: \"missing_field\",\n path: path_join(path, field),\n message: \"Missing required field \\{field}\",\n expected: Some(\"present\"),\n received: Some(\"missing\"),\n }\n}\n\n///|\nfn expected_type(\n path : String,\n expected : String,\n received : String,\n) -> Diagnostic {\n {\n kind: \"validation\",\n code: \"expected_type\",\n path,\n message: \"Expected \\{expected} but received \\{received}\",\n expected: Some(expected),\n received: Some(received),\n }\n}\n\n///|\nfn invalid_value(\n path : String,\n expected : String,\n received : String,\n) -> Diagnostic {\n {\n kind: \"validation\",\n code: \"invalid_value\",\n path,\n message: \"Expected \\{expected} but received \\{received}\",\n expected: Some(expected),\n received: Some(received),\n }\n}\n","///|\npub(all) struct PdfRect {\n x : Int\n y : Int\n width : Int\n height : Int\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfPageSize {\n width : Int\n height : Int\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfColor {\n red : Int\n green : Int\n blue : Int\n alpha : Int\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfTextAlign {\n PdfTextAlignLeft\n PdfTextAlignCenter\n PdfTextAlignRight\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTextStyle {\n font_family : String\n font_size : Int\n color : PdfColor\n align : PdfTextAlign\n bold : Bool\n italic : Bool\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfImageFit {\n PdfImageFitContain\n PdfImageFitCover\n PdfImageFitFill\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfShapeKind {\n PdfShapeRectangle\n PdfShapeLine\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfShapeStyle {\n fill : PdfColor?\n stroke : PdfColor?\n stroke_width : Int\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfTextSource {\n PdfFixedText(String)\n PdfBoundText(String)\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfImageSource {\n PdfFixedImage(String)\n PdfBoundImage(String)\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTableColumn {\n key : String\n header : String\n width : Int?\n align : PdfTextAlign\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfDataTableColumn {\n key : String\n header : String\n field_key : String\n width : Int?\n align : PdfTextAlign\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfNodeFrame {\n id : String\n rect : PdfRect\n visible_when : PdfConditionGroup?\n locked : Bool\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTextNode {\n frame : PdfNodeFrame\n source : PdfTextSource\n style : PdfTextStyle\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfImageNode {\n frame : PdfNodeFrame\n source : PdfImageSource\n alt : PdfTextSource?\n fit : PdfImageFit\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfStaticTableNode {\n frame : PdfNodeFrame\n columns : Array[PdfTableColumn]\n rows : Array[Array[PdfTextSource]]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfDataTableNode {\n frame : PdfNodeFrame\n collection_key : String\n columns : Array[PdfDataTableColumn]\n empty_text : String\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfShapeNode {\n frame : PdfNodeFrame\n kind : PdfShapeKind\n style : PdfShapeStyle\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfGroupNode {\n frame : PdfNodeFrame\n children : Array[PdfLayoutNode]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfLayoutNode {\n PdfLayoutText(PdfTextNode)\n PdfLayoutImage(PdfImageNode)\n PdfLayoutStaticTable(PdfStaticTableNode)\n PdfLayoutDataTable(PdfDataTableNode)\n PdfLayoutShape(PdfShapeNode)\n PdfLayoutGroup(PdfGroupNode)\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutPage {\n id : String\n size : PdfPageSize\n nodes : Array[PdfLayoutNode]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutPages {\n first : PdfLayoutPage\n rest : Array[PdfLayoutPage]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutDocument {\n id : String\n title : String\n pages : PdfLayoutPages\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTextBinding {\n key : String\n value : String\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfImageBinding {\n key : String\n url : String\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfNumberBinding {\n key : String\n value : Int\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfBoolBinding {\n key : String\n value : Bool\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfDataRow {\n cells : Array[PdfTextBinding]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfDataListBinding {\n key : String\n rows : Array[PdfDataRow]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutData {\n text_values : Array[PdfTextBinding]\n image_values : Array[PdfImageBinding]\n number_values : Array[PdfNumberBinding]\n bool_values : Array[PdfBoolBinding]\n data_lists : Array[PdfDataListBinding]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfStringConditionOperator {\n PdfStringEquals\n PdfStringNotEquals\n PdfStringContains\n PdfStringNotContains\n PdfStringStartsWith\n PdfStringEndsWith\n PdfStringEmpty\n PdfStringNotEmpty\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfNumberConditionOperator {\n PdfNumberEquals\n PdfNumberNotEquals\n PdfNumberGreaterThan\n PdfNumberGreaterThanOrEqual\n PdfNumberLessThan\n PdfNumberLessThanOrEqual\n PdfNumberEmpty\n PdfNumberNotEmpty\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfBoolConditionOperator {\n PdfBoolEquals\n PdfBoolNotEquals\n PdfBoolEmpty\n PdfBoolNotEmpty\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfConditionExpression {\n PdfStringCondition(\n field_key~ : String,\n operator~ : PdfStringConditionOperator,\n expected~ : String\n )\n PdfNumberCondition(\n field_key~ : String,\n operator~ : PdfNumberConditionOperator,\n expected~ : Int\n )\n PdfBoolCondition(\n field_key~ : String,\n operator~ : PdfBoolConditionOperator,\n expected~ : Bool\n )\n PdfNestedConditionGroup(PdfConditionGroup)\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfConditionGroupOperator {\n PdfConditionAll\n PdfConditionAny\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfConditionGroup {\n operator : PdfConditionGroupOperator\n conditions : Array[PdfConditionExpression]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfLayoutResolveMode {\n PdfEditorPreview\n PdfRenderOutput\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfResolvedPage {\n id : String\n size : PdfPageSize\n nodes : Array[PdfResolvedNode]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfResolvedNode {\n node_id : String\n node_type : String\n rect : PdfRect\n content : PdfResolvedNodeContent?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfResolvedNodeContent {\n PdfResolvedText(value~ : String, style~ : PdfTextStyle)\n PdfResolvedImage(url~ : String, alt~ : String?, fit~ : PdfImageFit)\n PdfResolvedStaticTable(headers~ : Array[String], rows~ : Array[Array[String]])\n PdfResolvedDataTable(\n headers~ : Array[String],\n rows~ : Array[Array[String]],\n empty_text~ : String\n )\n PdfResolvedShape(kind~ : PdfShapeKind, style~ : PdfShapeStyle)\n PdfResolvedGroup(children~ : Array[PdfResolvedNode])\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutResolveResult {\n ok : Bool\n tool : String\n document_id : String\n mode : String\n pages : Array[PdfResolvedPage]\n diagnostics : Array[Diagnostic]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutValidationResult {\n ok : Bool\n diagnostics : Array[Diagnostic]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfRectPatch {\n x : Int?\n y : Int?\n width : Int?\n height : Int?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfNodeFramePatch {\n rect : PdfRectPatch?\n visible_when : PdfConditionGroup?\n clear_visible_when : Bool?\n locked : Bool?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTextStylePatch {\n font_family : String?\n font_size : Int?\n color : PdfColor?\n align : PdfTextAlign?\n bold : Bool?\n italic : Bool?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfTextNodePatch {\n frame : PdfNodeFramePatch?\n source : PdfTextSource?\n style : PdfTextStylePatch?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfImageNodePatch {\n frame : PdfNodeFramePatch?\n source : PdfImageSource?\n alt : PdfTextSource?\n clear_alt : Bool?\n fit : PdfImageFit?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfStaticTableNodePatch {\n frame : PdfNodeFramePatch?\n columns : Array[PdfTableColumn]?\n rows : Array[Array[PdfTextSource]]?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfDataTableNodePatch {\n frame : PdfNodeFramePatch?\n collection_key : String?\n columns : Array[PdfDataTableColumn]?\n empty_text : String?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfShapeNodePatch {\n frame : PdfNodeFramePatch?\n kind : PdfShapeKind?\n style : PdfShapeStyle?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfGroupNodePatch {\n frame : PdfNodeFramePatch?\n children : Array[PdfLayoutNode]?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) enum PdfLayoutPatch {\n PdfPatchText(PdfTextNodePatch)\n PdfPatchImage(PdfImageNodePatch)\n PdfPatchStaticTable(PdfStaticTableNodePatch)\n PdfPatchDataTable(PdfDataTableNodePatch)\n PdfPatchShape(PdfShapeNodePatch)\n PdfPatchGroup(PdfGroupNodePatch)\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub(all) struct PdfLayoutPatchResult {\n document : PdfLayoutDocument\n changed : Bool\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub fn pdf_layout_default_color() -> PdfColor {\n { red: 33, green: 38, blue: 41, alpha: 255 }\n}\n\n///|\npub fn pdf_layout_default_text_style() -> PdfTextStyle {\n {\n font_family: \"sans-serif\",\n font_size: 12,\n color: pdf_layout_default_color(),\n align: PdfTextAlignLeft,\n bold: false,\n italic: false,\n }\n}\n\n///|\npub fn pdf_layout_empty_data() -> PdfLayoutData {\n {\n text_values: [],\n image_values: [],\n number_values: [],\n bool_values: [],\n data_lists: [],\n }\n}\n\n///|\npub fn pdf_layout_pages_to_array(\n pages : PdfLayoutPages,\n) -> Array[PdfLayoutPage] {\n let all_pages : Array[PdfLayoutPage] = [pages.first]\n for page in pages.rest {\n all_pages.push(page)\n }\n all_pages\n}\n\n///|\npub fn pdf_layout_resolve_mode_from_string(\n value : String,\n) -> PdfLayoutResolveMode {\n match value {\n \"editor\" | \"preview\" | \"editor_preview\" => PdfEditorPreview\n _ => PdfRenderOutput\n }\n}\n\n///|\npub fn pdf_layout_resolve_mode_name(mode : PdfLayoutResolveMode) -> String {\n match mode {\n PdfEditorPreview => \"editor_preview\"\n PdfRenderOutput => \"pdf_render\"\n }\n}\n\n///|\npub fn validate_pdf_layout_document(\n document : PdfLayoutDocument,\n) -> PdfLayoutValidationResult {\n let diagnostics : Array[Diagnostic] = []\n if document.id == \"\" {\n diagnostics.push(invalid_value(\"id\", \"non-empty string\", \"empty string\"))\n }\n let seen_ids : Array[String] = []\n let seen_page_ids : Array[String] = []\n for page_index, page in pdf_layout_pages_to_array(document.pages) {\n validate_pdf_layout_page(\n page,\n page_index,\n seen_page_ids,\n seen_ids,\n diagnostics,\n )\n }\n { ok: diagnostics.length() == 0, diagnostics }\n}\n\n///|\npub fn resolve_pdf_layout_document(\n document : PdfLayoutDocument,\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> PdfLayoutResolveResult {\n let validation = validate_pdf_layout_document(document)\n if !validation.ok {\n return {\n ok: false,\n tool: \"resolve_pdf_layout_document\",\n document_id: document.id,\n mode: pdf_layout_resolve_mode_name(mode),\n pages: [],\n diagnostics: validation.diagnostics,\n }\n }\n let pages : Array[PdfResolvedPage] = []\n for page in pdf_layout_pages_to_array(document.pages) {\n pages.push({\n id: page.id,\n size: page.size,\n nodes: resolve_pdf_layout_nodes(page.nodes, data, mode),\n })\n }\n {\n ok: true,\n tool: \"resolve_pdf_layout_document\",\n document_id: document.id,\n mode: pdf_layout_resolve_mode_name(mode),\n pages,\n diagnostics: [],\n }\n}\n\n///|\npub fn pdf_layout_resolve_error(message : String) -> PdfLayoutResolveResult {\n {\n ok: false,\n tool: \"resolve_pdf_layout_document\",\n document_id: \"\",\n mode: \"unknown\",\n pages: [],\n diagnostics: [\n {\n kind: \"parse\",\n code: \"bridge_error\",\n path: \"request\",\n message,\n expected: Some(\"valid PDF layout resolve request\"),\n received: Some(\"invalid request\"),\n },\n ],\n }\n}\n\n///|\npub fn update_pdf_layout_text_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfTextNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchText(patch))\n}\n\n///|\npub fn update_pdf_layout_image_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfImageNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchImage(patch))\n}\n\n///|\npub fn update_pdf_layout_static_table_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfStaticTableNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchStaticTable(patch))\n}\n\n///|\npub fn update_pdf_layout_data_table_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfDataTableNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchDataTable(patch))\n}\n\n///|\npub fn update_pdf_layout_shape_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfShapeNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchShape(patch))\n}\n\n///|\npub fn update_pdf_layout_group_node(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfGroupNodePatch,\n) -> PdfLayoutPatchResult {\n patch_pdf_layout_document(document, node_id, PdfPatchGroup(patch))\n}\n\n///|\nfn validate_pdf_layout_page(\n page : PdfLayoutPage,\n page_index : Int,\n seen_page_ids : Array[String],\n seen_ids : Array[String],\n diagnostics : Array[Diagnostic],\n) -> Unit {\n let path = pdf_layout_page_path(page_index)\n if page.id == \"\" {\n diagnostics.push(missing_field(path, \"id\"))\n } else if string_array_contains(seen_page_ids, page.id) {\n diagnostics.push(\n invalid_value(path_join(path, \"id\"), \"unique page id\", page.id),\n )\n } else {\n seen_page_ids.push(page.id)\n }\n if page.size.width <= 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"size.width\"),\n \"positive integer\",\n page.size.width.to_string(),\n ),\n )\n }\n if page.size.height <= 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"size.height\"),\n \"positive integer\",\n page.size.height.to_string(),\n ),\n )\n }\n validate_pdf_layout_nodes(\n page.nodes,\n path_join(path, \"nodes\"),\n seen_ids,\n diagnostics,\n )\n}\n\n///|\nfn pdf_layout_page_path(page_index : Int) -> String {\n if page_index == 0 {\n \"pages.first\"\n } else {\n path_join(\"pages.rest\", (page_index - 1).to_string())\n }\n}\n\n///|\nfn validate_pdf_layout_nodes(\n nodes : Array[PdfLayoutNode],\n path : String,\n seen_ids : Array[String],\n diagnostics : Array[Diagnostic],\n) -> Unit {\n for index, node in nodes {\n validate_pdf_layout_node(\n node,\n index_path(path, index),\n seen_ids,\n diagnostics,\n )\n }\n}\n\n///|\nfn validate_pdf_layout_node(\n node : PdfLayoutNode,\n path : String,\n seen_ids : Array[String],\n diagnostics : Array[Diagnostic],\n) -> Unit {\n let frame = pdf_layout_node_frame(node)\n validate_pdf_node_frame(\n frame,\n path_join(path, \"frame\"),\n seen_ids,\n diagnostics,\n )\n match node {\n PdfLayoutText(_) => ()\n PdfLayoutImage(_) => ()\n PdfLayoutStaticTable(table) =>\n if table.columns.length() == 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"columns\"),\n \"at least one column\",\n \"empty array\",\n ),\n )\n }\n PdfLayoutDataTable(table) => {\n if table.collection_key == \"\" {\n diagnostics.push(missing_field(path, \"collection_key\"))\n }\n if table.columns.length() == 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"columns\"),\n \"at least one column\",\n \"empty array\",\n ),\n )\n }\n }\n PdfLayoutShape(shape) =>\n if shape.style.stroke_width < 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"style.stroke_width\"),\n \"non-negative integer\",\n shape.style.stroke_width.to_string(),\n ),\n )\n }\n PdfLayoutGroup(group) =>\n validate_pdf_layout_nodes(\n group.children,\n path_join(path, \"children\"),\n seen_ids,\n diagnostics,\n )\n }\n}\n\n///|\nfn validate_pdf_node_frame(\n frame : PdfNodeFrame,\n path : String,\n seen_ids : Array[String],\n diagnostics : Array[Diagnostic],\n) -> Unit {\n if frame.id == \"\" {\n diagnostics.push(missing_field(path, \"id\"))\n } else if string_array_contains(seen_ids, frame.id) {\n diagnostics.push(\n invalid_value(path_join(path, \"id\"), \"unique node id\", frame.id),\n )\n } else {\n seen_ids.push(frame.id)\n }\n if frame.rect.width <= 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"rect.width\"),\n \"positive integer\",\n frame.rect.width.to_string(),\n ),\n )\n }\n if frame.rect.height <= 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"rect.height\"),\n \"positive integer\",\n frame.rect.height.to_string(),\n ),\n )\n }\n}\n\n///|\nfn resolve_pdf_layout_nodes(\n nodes : Array[PdfLayoutNode],\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> Array[PdfResolvedNode] {\n let resolved : Array[PdfResolvedNode] = []\n for node in nodes {\n resolved.push(resolve_pdf_layout_node(node, data, mode))\n }\n resolved\n}\n\n///|\nfn resolve_pdf_layout_node(\n node : PdfLayoutNode,\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> PdfResolvedNode {\n let frame = pdf_layout_node_frame(node)\n if !pdf_node_is_visible(frame, data) {\n return {\n node_id: frame.id,\n node_type: pdf_layout_node_type(node),\n rect: frame.rect,\n content: None,\n }\n }\n {\n node_id: frame.id,\n node_type: pdf_layout_node_type(node),\n rect: frame.rect,\n content: Some(resolve_pdf_layout_node_content(node, data, mode)),\n }\n}\n\n///|\nfn resolve_pdf_layout_node_content(\n node : PdfLayoutNode,\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> PdfResolvedNodeContent {\n match node {\n PdfLayoutText(text) =>\n PdfResolvedText(\n value=resolve_pdf_text_source(text.source, data, mode),\n style=text.style,\n )\n PdfLayoutImage(image) =>\n PdfResolvedImage(\n url=resolve_pdf_image_source(image.source, data, mode),\n alt=match image.alt {\n Some(source) => Some(resolve_pdf_text_source(source, data, mode))\n None => None\n },\n fit=image.fit,\n )\n PdfLayoutStaticTable(table) =>\n PdfResolvedStaticTable(\n headers=resolve_pdf_table_headers(table.columns),\n rows=resolve_pdf_static_table_rows(table.rows, data, mode),\n )\n PdfLayoutDataTable(table) =>\n PdfResolvedDataTable(\n headers=resolve_pdf_data_table_headers(table.columns),\n rows=resolve_pdf_data_table_rows(\n table.collection_key,\n table.columns,\n data,\n mode,\n ),\n empty_text=table.empty_text,\n )\n PdfLayoutShape(shape) =>\n PdfResolvedShape(kind=shape.kind, style=shape.style)\n PdfLayoutGroup(group) =>\n PdfResolvedGroup(\n children=resolve_pdf_layout_nodes(group.children, data, mode),\n )\n }\n}\n\n///|\nfn pdf_layout_node_frame(node : PdfLayoutNode) -> PdfNodeFrame {\n match node {\n PdfLayoutText(text) => text.frame\n PdfLayoutImage(image) => image.frame\n PdfLayoutStaticTable(table) => table.frame\n PdfLayoutDataTable(table) => table.frame\n PdfLayoutShape(shape) => shape.frame\n PdfLayoutGroup(group) => group.frame\n }\n}\n\n///|\nfn pdf_layout_node_type(node : PdfLayoutNode) -> String {\n match node {\n PdfLayoutText(_) => \"text\"\n PdfLayoutImage(_) => \"image\"\n PdfLayoutStaticTable(_) => \"static_table\"\n PdfLayoutDataTable(_) => \"data_table\"\n PdfLayoutShape(_) => \"shape\"\n PdfLayoutGroup(_) => \"group\"\n }\n}\n\n///|\nfn pdf_node_is_visible(frame : PdfNodeFrame, data : PdfLayoutData) -> Bool {\n match frame.visible_when {\n Some(condition) => evaluate_pdf_condition_group(condition, data)\n None => true\n }\n}\n\n///|\nfn evaluate_pdf_condition_group(\n group : PdfConditionGroup,\n data : PdfLayoutData,\n) -> Bool {\n match group.operator {\n PdfConditionAll => {\n for condition in group.conditions {\n if !evaluate_pdf_condition(condition, data) {\n return false\n }\n }\n true\n }\n PdfConditionAny => {\n for condition in group.conditions {\n if evaluate_pdf_condition(condition, data) {\n return true\n }\n }\n false\n }\n }\n}\n\n///|\nfn evaluate_pdf_condition(\n condition : PdfConditionExpression,\n data : PdfLayoutData,\n) -> Bool {\n match condition {\n PdfStringCondition(field_key~, operator~, expected~) =>\n evaluate_pdf_string_condition(\n lookup_pdf_text(data, field_key),\n operator,\n expected,\n )\n PdfNumberCondition(field_key~, operator~, expected~) =>\n evaluate_pdf_number_condition(\n lookup_pdf_number(data, field_key),\n operator,\n expected,\n )\n PdfBoolCondition(field_key~, operator~, expected~) =>\n evaluate_pdf_bool_condition(\n lookup_pdf_bool(data, field_key),\n operator,\n expected,\n )\n PdfNestedConditionGroup(group) => evaluate_pdf_condition_group(group, data)\n }\n}\n\n///|\nfn evaluate_pdf_string_condition(\n value : String?,\n operator : PdfStringConditionOperator,\n expected : String,\n) -> Bool {\n let actual = value.unwrap_or(\"\")\n match operator {\n PdfStringEquals => actual == expected\n PdfStringNotEquals => actual != expected\n PdfStringContains => actual.contains(expected[:])\n PdfStringNotContains => !actual.contains(expected[:])\n PdfStringStartsWith => string_starts_with(actual, expected)\n PdfStringEndsWith => string_ends_with(actual, expected)\n PdfStringEmpty => actual == \"\"\n PdfStringNotEmpty => actual != \"\"\n }\n}\n\n///|\nfn evaluate_pdf_number_condition(\n value : Int?,\n operator : PdfNumberConditionOperator,\n expected : Int,\n) -> Bool {\n match operator {\n PdfNumberEmpty => value is None\n PdfNumberNotEmpty => value is Some(_)\n _ => {\n let actual = value.unwrap_or(0)\n match operator {\n PdfNumberEquals => actual == expected\n PdfNumberNotEquals => actual != expected\n PdfNumberGreaterThan => actual > expected\n PdfNumberGreaterThanOrEqual => actual >= expected\n PdfNumberLessThan => actual < expected\n PdfNumberLessThanOrEqual => actual <= expected\n PdfNumberEmpty | PdfNumberNotEmpty => false\n }\n }\n }\n}\n\n///|\nfn evaluate_pdf_bool_condition(\n value : Bool?,\n operator : PdfBoolConditionOperator,\n expected : Bool,\n) -> Bool {\n match operator {\n PdfBoolEmpty => value is None\n PdfBoolNotEmpty => value is Some(_)\n _ => {\n let actual = value.unwrap_or(false)\n match operator {\n PdfBoolEquals => actual == expected\n PdfBoolNotEquals => actual != expected\n PdfBoolEmpty | PdfBoolNotEmpty => false\n }\n }\n }\n}\n\n///|\nfn resolve_pdf_text_source(\n source : PdfTextSource,\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> String {\n match source {\n PdfFixedText(value) => value\n PdfBoundText(key) =>\n match lookup_pdf_text(data, key) {\n Some(value) => value\n None => missing_pdf_binding_text(key, mode)\n }\n }\n}\n\n///|\nfn resolve_pdf_image_source(\n source : PdfImageSource,\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> String {\n match source {\n PdfFixedImage(url) => url\n PdfBoundImage(key) =>\n match lookup_pdf_image(data, key) {\n Some(url) => url\n None => missing_pdf_binding_text(key, mode)\n }\n }\n}\n\n///|\nfn missing_pdf_binding_text(\n key : String,\n mode : PdfLayoutResolveMode,\n) -> String {\n match mode {\n PdfEditorPreview => \"{{\" + key + \"}}\"\n PdfRenderOutput => \"\"\n }\n}\n\n///|\nfn resolve_pdf_table_headers(columns : Array[PdfTableColumn]) -> Array[String] {\n let headers : Array[String] = []\n for column in columns {\n headers.push(column.header)\n }\n headers\n}\n\n///|\nfn resolve_pdf_data_table_headers(\n columns : Array[PdfDataTableColumn],\n) -> Array[String] {\n let headers : Array[String] = []\n for column in columns {\n headers.push(column.header)\n }\n headers\n}\n\n///|\nfn resolve_pdf_static_table_rows(\n rows : Array[Array[PdfTextSource]],\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> Array[Array[String]] {\n let resolved_rows : Array[Array[String]] = []\n for row in rows {\n let resolved_row : Array[String] = []\n for cell in row {\n resolved_row.push(resolve_pdf_text_source(cell, data, mode))\n }\n resolved_rows.push(resolved_row)\n }\n resolved_rows\n}\n\n///|\nfn resolve_pdf_data_table_rows(\n collection_key : String,\n columns : Array[PdfDataTableColumn],\n data : PdfLayoutData,\n mode : PdfLayoutResolveMode,\n) -> Array[Array[String]] {\n let resolved_rows : Array[Array[String]] = []\n match lookup_pdf_data_list(data, collection_key) {\n Some(list) =>\n for row in list.rows {\n let resolved_row : Array[String] = []\n for column in columns {\n resolved_row.push(\n lookup_pdf_row_text(row, column.field_key).unwrap_or(\n missing_pdf_binding_text(\n pdf_data_table_binding_key(collection_key, column.field_key),\n mode,\n ),\n ),\n )\n }\n resolved_rows.push(resolved_row)\n }\n None =>\n if mode == PdfEditorPreview {\n let placeholder_row : Array[String] = []\n for column in columns {\n placeholder_row.push(\n missing_pdf_binding_text(\n pdf_data_table_binding_key(collection_key, column.field_key),\n mode,\n ),\n )\n }\n resolved_rows.push(placeholder_row)\n }\n }\n resolved_rows\n}\n\n///|\nfn pdf_data_table_binding_key(collection_key : String, field_key : String) -> String {\n if collection_key == \"\" {\n field_key\n } else if field_key == \"\" {\n collection_key\n } else {\n collection_key + \".\" + field_key\n }\n}\n\n///|\nfn patch_pdf_layout_document(\n document : PdfLayoutDocument,\n node_id : String,\n patch : PdfLayoutPatch,\n) -> PdfLayoutPatchResult {\n let (first, first_changed) = patch_pdf_layout_page(\n document.pages.first,\n node_id,\n patch,\n )\n let rest : Array[PdfLayoutPage] = []\n let mut rest_changed = false\n for page in document.pages.rest {\n let (patched_page, page_changed) = patch_pdf_layout_page(\n page, node_id, patch,\n )\n rest.push(patched_page)\n if page_changed {\n rest_changed = true\n }\n }\n let changed = first_changed || rest_changed\n {\n document: if changed {\n { id: document.id, title: document.title, pages: { first, rest } }\n } else {\n document\n },\n changed,\n }\n}\n\n///|\nfn patch_pdf_layout_page(\n page : PdfLayoutPage,\n node_id : String,\n patch : PdfLayoutPatch,\n) -> (PdfLayoutPage, Bool) {\n let (nodes, changed) = patch_pdf_layout_nodes(page.nodes, node_id, patch)\n if changed {\n ({ id: page.id, size: page.size, nodes }, true)\n } else {\n (page, false)\n }\n}\n\n///|\nfn patch_pdf_layout_nodes(\n nodes : Array[PdfLayoutNode],\n node_id : String,\n patch : PdfLayoutPatch,\n) -> (Array[PdfLayoutNode], Bool) {\n let patched_nodes : Array[PdfLayoutNode] = []\n let mut changed = false\n for node in nodes {\n let (patched_node, node_changed) = patch_pdf_layout_node(\n node, node_id, patch,\n )\n patched_nodes.push(patched_node)\n if node_changed {\n changed = true\n }\n }\n (patched_nodes, changed)\n}\n\n///|\nfn patch_pdf_layout_node(\n node : PdfLayoutNode,\n node_id : String,\n patch : PdfLayoutPatch,\n) -> (PdfLayoutNode, Bool) {\n let frame = pdf_layout_node_frame(node)\n if frame.id == node_id {\n return apply_pdf_layout_patch(node, patch)\n }\n match node {\n PdfLayoutGroup(group) => {\n let (children, changed) = patch_pdf_layout_nodes(\n group.children,\n node_id,\n patch,\n )\n if changed {\n (PdfLayoutGroup({ frame: group.frame, children }), true)\n } else {\n (node, false)\n }\n }\n _ => (node, false)\n }\n}\n\n///|\nfn apply_pdf_layout_patch(\n node : PdfLayoutNode,\n patch : PdfLayoutPatch,\n) -> (PdfLayoutNode, Bool) {\n match (node, patch) {\n (PdfLayoutText(text), PdfPatchText(patch)) =>\n (\n PdfLayoutText({\n frame: patch_pdf_node_frame(text.frame, patch.frame),\n source: patch.source.unwrap_or(text.source),\n style: patch_pdf_text_style(text.style, patch.style),\n }),\n true,\n )\n (PdfLayoutImage(image), PdfPatchImage(patch)) =>\n (\n PdfLayoutImage({\n frame: patch_pdf_node_frame(image.frame, patch.frame),\n source: patch.source.unwrap_or(image.source),\n alt: patch_pdf_optional_text_source(\n image.alt,\n patch.alt,\n patch.clear_alt,\n ),\n fit: patch.fit.unwrap_or(image.fit),\n }),\n true,\n )\n (PdfLayoutStaticTable(table), PdfPatchStaticTable(patch)) =>\n (\n PdfLayoutStaticTable({\n frame: patch_pdf_node_frame(table.frame, patch.frame),\n columns: patch.columns.unwrap_or(table.columns),\n rows: patch.rows.unwrap_or(table.rows),\n }),\n true,\n )\n (PdfLayoutDataTable(table), PdfPatchDataTable(patch)) =>\n (\n PdfLayoutDataTable({\n frame: patch_pdf_node_frame(table.frame, patch.frame),\n collection_key: patch.collection_key.unwrap_or(table.collection_key),\n columns: patch.columns.unwrap_or(table.columns),\n empty_text: patch.empty_text.unwrap_or(table.empty_text),\n }),\n true,\n )\n (PdfLayoutShape(shape), PdfPatchShape(patch)) =>\n (\n PdfLayoutShape({\n frame: patch_pdf_node_frame(shape.frame, patch.frame),\n kind: patch.kind.unwrap_or(shape.kind),\n style: patch.style.unwrap_or(shape.style),\n }),\n true,\n )\n (PdfLayoutGroup(group), PdfPatchGroup(patch)) =>\n (\n PdfLayoutGroup({\n frame: patch_pdf_node_frame(group.frame, patch.frame),\n children: patch.children.unwrap_or(group.children),\n }),\n true,\n )\n _ => (node, false)\n }\n}\n\n///|\nfn patch_pdf_node_frame(\n frame : PdfNodeFrame,\n patch : PdfNodeFramePatch?,\n) -> PdfNodeFrame {\n match patch {\n Some(patch) =>\n {\n id: frame.id,\n rect: patch_pdf_rect(frame.rect, patch.rect),\n visible_when: patch_pdf_optional_condition(\n frame.visible_when,\n patch.visible_when,\n patch.clear_visible_when,\n ),\n locked: patch.locked.unwrap_or(frame.locked),\n }\n None => frame\n }\n}\n\n///|\nfn patch_pdf_optional_condition(\n original : PdfConditionGroup?,\n replacement : PdfConditionGroup?,\n clear : Bool?,\n) -> PdfConditionGroup? {\n if clear.unwrap_or(false) {\n None\n } else {\n match replacement {\n Some(value) => Some(value)\n None => original\n }\n }\n}\n\n///|\nfn patch_pdf_optional_text_source(\n original : PdfTextSource?,\n replacement : PdfTextSource?,\n clear : Bool?,\n) -> PdfTextSource? {\n if clear.unwrap_or(false) {\n None\n } else {\n match replacement {\n Some(value) => Some(value)\n None => original\n }\n }\n}\n\n///|\nfn patch_pdf_rect(rect : PdfRect, patch : PdfRectPatch?) -> PdfRect {\n match patch {\n Some(patch) =>\n {\n x: patch.x.unwrap_or(rect.x),\n y: patch.y.unwrap_or(rect.y),\n width: patch.width.unwrap_or(rect.width),\n height: patch.height.unwrap_or(rect.height),\n }\n None => rect\n }\n}\n\n///|\nfn patch_pdf_text_style(\n style : PdfTextStyle,\n patch : PdfTextStylePatch?,\n) -> PdfTextStyle {\n match patch {\n Some(patch) =>\n {\n font_family: patch.font_family.unwrap_or(style.font_family),\n font_size: patch.font_size.unwrap_or(style.font_size),\n color: patch.color.unwrap_or(style.color),\n align: patch.align.unwrap_or(style.align),\n bold: patch.bold.unwrap_or(style.bold),\n italic: patch.italic.unwrap_or(style.italic),\n }\n None => style\n }\n}\n\n///|\nfn lookup_pdf_text(data : PdfLayoutData, key : String) -> String? {\n for binding in data.text_values {\n if binding.key == key {\n return Some(binding.value)\n }\n }\n None\n}\n\n///|\nfn lookup_pdf_image(data : PdfLayoutData, key : String) -> String? {\n for binding in data.image_values {\n if binding.key == key {\n return Some(binding.url)\n }\n }\n None\n}\n\n///|\nfn lookup_pdf_number(data : PdfLayoutData, key : String) -> Int? {\n for binding in data.number_values {\n if binding.key == key {\n return Some(binding.value)\n }\n }\n None\n}\n\n///|\nfn lookup_pdf_bool(data : PdfLayoutData, key : String) -> Bool? {\n for binding in data.bool_values {\n if binding.key == key {\n return Some(binding.value)\n }\n }\n None\n}\n\n///|\nfn lookup_pdf_data_list(\n data : PdfLayoutData,\n key : String,\n) -> PdfDataListBinding? {\n for binding in data.data_lists {\n if binding.key == key {\n return Some(binding)\n }\n }\n None\n}\n\n///|\nfn lookup_pdf_row_text(row : PdfDataRow, key : String) -> String? {\n for cell in row.cells {\n if cell.key == key {\n return Some(cell.value)\n }\n }\n None\n}\n\n///|\nfn string_array_contains(values : Array[String], target : String) -> Bool {\n for value in values {\n if value == target {\n return true\n }\n }\n false\n}\n\n///|\nfn string_starts_with(text : String, prefix : String) -> Bool {\n text.length() >= prefix.length() &&\n text[0:prefix.length()].to_owned() == prefix\n}\n\n///|\nfn string_ends_with(text : String, suffix : String) -> Bool {\n if suffix.length() > text.length() {\n false\n } else {\n text[text.length() - suffix.length():].to_owned() == suffix\n }\n}\n","///|\nfn index_path(base : String, index : Int) -> String {\n path_join(base, index.to_string())\n}\n\n///|\nfn parse_error(message : String) -> Diagnostic {\n {\n kind: \"parse\",\n code: \"json_parse_error\",\n path: \"\",\n message,\n expected: None,\n received: None,\n }\n}\n","///|\npub struct DocumentStackToolEnvelope {\n ok : Bool\n tool : String\n result : Json?\n diagnostics : Array[Diagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentPreviewResult {\n document_id : String\n title : String\n mode : String\n text : String\n html : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentSearchHit {\n id : String\n title : String\n score : Int\n snippet : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentSearchResult {\n query : String\n total : Int\n hits : Array[DocumentSearchHit]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentWorkspaceExport {\n schema_version : String\n exported_at : String\n documents : Array[PapyrDocument]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentPublicationExport {\n schema_version : String\n exported_at : String\n publication_id : String\n document : PapyrDocument\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub(all) struct DocumentMarkdownMirror {\n document_id : String\n markdown : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentPreviewHtml {\n document_id : String\n title : String\n mode : String\n html : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentSlideArtifact {\n document_id : String\n slide_id : String\n slide_number : Int\n title : String\n document : PapyrDocument\n html : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PapyrBundleExport {\n schema_version : String\n artifact_kind : String\n generated_at : String\n documents : Array[PapyrDocument]\n markdown_mirrors : Array[DocumentMarkdownMirror]\n preview_html : Array[DocumentPreviewHtml]\n slides : Array[DocumentSlideArtifact]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub let document_stack_schema_version : String = \"papyr.document-stack.v0\"\n\n///|\npub let papyr_bundle_artifact_kind : String = \"papyr_bundle\"\n\n///|\npub fn document_stack_success(\n tool : String,\n result : Json,\n) -> DocumentStackToolEnvelope {\n { ok: true, tool, result: Some(result), diagnostics: [] }\n}\n\n///|\npub fn document_stack_failure(\n tool : String,\n diagnostics : Array[Diagnostic],\n) -> DocumentStackToolEnvelope {\n { ok: false, tool, result: None, diagnostics }\n}\n\n///|\npub fn document_stack_error(\n tool : String,\n code : String,\n path : String,\n message : String,\n expected? : String? = None,\n received? : String? = None,\n) -> DocumentStackToolEnvelope {\n document_stack_failure(tool, [\n { kind: \"tool\", code, path, message, expected, received },\n ])\n}\n\n///|\npub fn document_stack_validate_document(\n document : PapyrDocument,\n) -> DocumentStackToolEnvelope {\n let envelope = validate_papyr_document(document)\n if envelope.ok {\n document_stack_success(\"validate_document\", document.to_json())\n } else {\n document_stack_failure(\"validate_document\", envelope.diagnostics)\n }\n}\n\n///|\npub fn document_stack_preview_document(\n document : PapyrDocument,\n mode? : String = \"document\",\n) -> DocumentStackToolEnvelope {\n let envelope = validate_papyr_document(document)\n if !envelope.ok {\n return document_stack_failure(\"preview_document\", envelope.diagnostics)\n }\n document_stack_success(\n \"preview_document\",\n {\n document_id: document.id,\n title: document_title(document),\n mode,\n text: document_text(document),\n html: render_document_html(document, mode),\n }.to_json(),\n )\n}\n\n///|\npub fn document_stack_search_documents(\n documents : Array[PapyrDocument],\n query : String,\n limit? : Int = 20,\n) -> DocumentStackToolEnvelope {\n if limit <= 0 {\n return document_stack_error(\n \"search_documents\",\n \"invalid_limit\",\n \"limit\",\n \"Search limit must be greater than zero\",\n expected=Some(\"positive integer\"),\n received=Some(limit.to_string()),\n )\n }\n let diagnostics : Array[Diagnostic] = []\n let hits : Array[DocumentSearchHit] = []\n let normalized_query = query.trim().to_owned().to_lower()\n for i, document in documents {\n let envelope = validate_papyr_document(document)\n if !envelope.ok {\n for diagnostic in envelope.diagnostics {\n diagnostics.push({\n kind: diagnostic.kind,\n code: diagnostic.code,\n path: path_join(index_path(\"documents\", i), diagnostic.path),\n message: diagnostic.message,\n expected: diagnostic.expected,\n received: diagnostic.received,\n })\n }\n continue\n }\n let title = document_title(document)\n let body = document_text(document)\n let score = search_score(title, body, normalized_query)\n if score > 0 || normalized_query == \"\" {\n hits.push({\n id: document.id,\n title,\n score,\n snippet: search_snippet(body, title, normalized_query),\n })\n }\n }\n if diagnostics.length() > 0 {\n return document_stack_failure(\"search_documents\", diagnostics)\n }\n let limited : Array[DocumentSearchHit] = []\n for i, hit in hits {\n if i < limit {\n limited.push(hit)\n }\n }\n document_stack_success(\n \"search_documents\",\n { query, total: hits.length(), hits: limited }.to_json(),\n )\n}\n\n///|\npub fn document_stack_export_workspace(\n documents : Array[PapyrDocument],\n generated_at~ : String,\n) -> DocumentStackToolEnvelope {\n let diagnostics : Array[Diagnostic] = []\n for i, document in documents {\n let envelope = validate_papyr_document(document)\n if !envelope.ok {\n for diagnostic in envelope.diagnostics {\n diagnostics.push({\n kind: diagnostic.kind,\n code: diagnostic.code,\n path: path_join(index_path(\"documents\", i), diagnostic.path),\n message: diagnostic.message,\n expected: diagnostic.expected,\n received: diagnostic.received,\n })\n }\n }\n }\n if diagnostics.length() > 0 {\n return document_stack_failure(\"export_workspace\", diagnostics)\n }\n document_stack_success(\n \"export_workspace\",\n {\n schema_version: document_stack_schema_version,\n exported_at: generated_at,\n documents,\n }.to_json(),\n )\n}\n\n///|\npub fn document_stack_export_publication(\n documents : Array[PapyrDocument],\n publication_id : String,\n generated_at~ : String,\n) -> DocumentStackToolEnvelope {\n let workspace = document_stack_export_workspace(documents, generated_at~)\n if !workspace.ok {\n return {\n ok: false,\n tool: \"export_publication\",\n result: None,\n diagnostics: workspace.diagnostics,\n }\n }\n for document in documents {\n if document.id == publication_id {\n return document_stack_success(\n \"export_publication\",\n {\n schema_version: document_stack_schema_version,\n exported_at: generated_at,\n publication_id,\n document,\n }.to_json(),\n )\n }\n }\n document_stack_error(\n \"export_publication\",\n \"publication_not_found\",\n \"publication_id\",\n \"Publication \\{publication_id} was not found\",\n expected=Some(\"document id present in documents\"),\n received=Some(publication_id),\n )\n}\n\n///|\npub fn document_stack_export_papyr_bundle(\n documents : Array[PapyrDocument],\n markdown_mirrors : Array[DocumentMarkdownMirror],\n generated_at~ : String,\n) -> DocumentStackToolEnvelope {\n let diagnostics = validate_documents_for_tool(\n documents, \"export_papyr_bundle\",\n )\n if diagnostics.length() > 0 {\n return document_stack_failure(\"export_papyr_bundle\", diagnostics)\n }\n let mirror_diagnostics = validate_markdown_mirrors(\n documents, markdown_mirrors,\n )\n if mirror_diagnostics.length() > 0 {\n return document_stack_failure(\"export_papyr_bundle\", mirror_diagnostics)\n }\n let preview_html : Array[DocumentPreviewHtml] = []\n let slides : Array[DocumentSlideArtifact] = []\n for document in documents {\n preview_html.push({\n document_id: document.id,\n title: document_title(document),\n mode: \"document\",\n html: render_document_html(document, \"document\"),\n })\n for slide in build_document_slides(document) {\n slides.push(slide)\n }\n }\n document_stack_success(\n \"export_papyr_bundle\",\n {\n schema_version: document_stack_schema_version,\n artifact_kind: papyr_bundle_artifact_kind,\n generated_at,\n documents,\n markdown_mirrors,\n preview_html,\n slides,\n }.to_json(),\n )\n}\n\n///|\nfn validate_documents_for_tool(\n documents : Array[PapyrDocument],\n _tool : String,\n) -> Array[Diagnostic] {\n let diagnostics : Array[Diagnostic] = []\n for i, document in documents {\n let envelope = validate_papyr_document(document)\n if !envelope.ok {\n for diagnostic in envelope.diagnostics {\n diagnostics.push({\n kind: diagnostic.kind,\n code: diagnostic.code,\n path: path_join(index_path(\"documents\", i), diagnostic.path),\n message: diagnostic.message,\n expected: diagnostic.expected,\n received: diagnostic.received,\n })\n }\n }\n }\n diagnostics\n}\n\n///|\nfn validate_markdown_mirrors(\n documents : Array[PapyrDocument],\n markdown_mirrors : Array[DocumentMarkdownMirror],\n) -> Array[Diagnostic] {\n let diagnostics : Array[Diagnostic] = []\n if markdown_mirrors.length() != documents.length() {\n diagnostics.push({\n kind: \"tool\",\n code: \"markdown_mirror_count_mismatch\",\n path: \"markdown_mirrors\",\n message: \"Markdown mirror count must match document count\",\n expected: Some(documents.length().to_string()),\n received: Some(markdown_mirrors.length().to_string()),\n })\n return diagnostics\n }\n for i, document in documents {\n let mirror = markdown_mirrors[i]\n if mirror.document_id != document.id {\n diagnostics.push({\n kind: \"tool\",\n code: \"markdown_mirror_document_mismatch\",\n path: index_path(\"markdown_mirrors\", i) + \".document_id\",\n message: \"Markdown mirror document id must match canonical document id\",\n expected: Some(document.id),\n received: Some(mirror.document_id),\n })\n }\n }\n diagnostics\n}\n\n///|\nfn build_document_slides(\n document : PapyrDocument,\n) -> Array[DocumentSlideArtifact] {\n let slides : Array[DocumentSlideArtifact] = []\n let slide_blocks = split_document_into_slides(document.blocks)\n for i, blocks in slide_blocks {\n let slide_id = document.id + \"#slide-\\{i + 1}\"\n let slide_document : PapyrDocument = {\n id: slide_id,\n title: Some(resolve_slide_title(document, blocks, i)),\n blocks,\n meta: document.meta,\n }\n slides.push({\n document_id: document.id,\n slide_id,\n slide_number: i + 1,\n title: slide_document.title.unwrap_or(slide_id),\n document: slide_document,\n html: render_document_html(slide_document, \"slides\"),\n })\n }\n slides\n}\n\n///|\nfn split_document_into_slides(blocks : Array[Block]) -> Array[Array[Block]] {\n let slides : Array[Array[Block]] = []\n let mut current : Array[Block] = []\n for block in blocks {\n if is_slide_boundary(block) && current.length() > 0 {\n slides.push(current)\n current = [block]\n } else {\n current.push(block)\n }\n }\n if current.length() > 0 {\n slides.push(current)\n }\n if slides.length() == 0 {\n slides.push([])\n }\n slides\n}\n\n///|\nfn is_slide_boundary(block : Block) -> Bool {\n match block {\n Heading(level=2, ..) => true\n _ => false\n }\n}\n\n///|\nfn resolve_slide_title(\n document : PapyrDocument,\n blocks : Array[Block],\n index : Int,\n) -> String {\n if blocks.length() > 0 {\n match blocks[0] {\n Heading(content~, ..) => {\n let title = document_inline_text(content).trim().to_owned()\n if title.length() > 0 {\n return title\n }\n }\n _ => ()\n }\n }\n if index == 0 {\n document_title(document)\n } else {\n \"Slide \\{index + 1}\"\n }\n}\n\n///|\nfn search_score(title : String, body : String, query : String) -> Int {\n if query == \"\" {\n return 1\n }\n let mut score = 0\n if title.to_lower().contains(query[:]) {\n score += 4\n }\n if body.to_lower().contains(query[:]) {\n score += 1\n }\n score\n}\n\n///|\nfn search_snippet(body : String, title : String, query : String) -> String {\n if query == \"\" {\n return first_non_empty(body, title)\n }\n if title.to_lower().contains(query[:]) {\n return title\n }\n first_non_empty(body, title)\n}\n\n///|\nfn first_non_empty(first : String, fallback : String) -> String {\n let text = first.trim().to_owned()\n if text.length() > 0 {\n text\n } else {\n fallback\n }\n}\n\n///|\nfn render_document_html(document : PapyrDocument, mode : String) -> String {\n let sb = StringBuilder::new()\n sb.write_string(\"<article class=\\\"papyr-preview\\\" data-document-id=\\\"\")\n sb.write_string(html_escape(document.id))\n sb.write_string(\"\\\" data-mode=\\\"\")\n sb.write_string(html_escape(mode))\n sb.write_string(\"\\\">\")\n for block in document.blocks {\n sb.write_string(render_block_html(block))\n }\n sb.write_string(\"</article>\")\n sb.to_string()\n}\n\n///|\nfn render_block_html(block : Block) -> String {\n match block {\n Heading(id~, level~, content~) => {\n let tag = \"h\\{level}\"\n \"<\\{tag} id=\\\"\\{html_escape(id)}\\\">\" +\n render_inline_html(content) +\n \"</\\{tag}>\"\n }\n Paragraph(id~, content~) =>\n \"<p id=\\\"\\{html_escape(id)}\\\">\" + render_inline_html(content) + \"</p>\"\n List(id~, ordered~, items~) => {\n let tag = if ordered { \"ol\" } else { \"ul\" }\n let sb = StringBuilder::new()\n sb.write_string(\"<\")\n sb.write_string(tag)\n sb.write_string(\" id=\\\"\")\n sb.write_string(html_escape(id))\n sb.write_string(\"\\\">\")\n for item in items {\n sb.write_string(\"<li>\")\n for child in item.blocks {\n sb.write_string(render_block_html(child))\n }\n sb.write_string(\"</li>\")\n }\n sb.write_string(\"</\")\n sb.write_string(tag)\n sb.write_string(\">\")\n sb.to_string()\n }\n Code(id~, language~, source~) => {\n let class_attr = match language {\n Some(language) => \" class=\\\"language-\\{html_escape(language)}\\\"\"\n None => \"\"\n }\n \"<pre id=\\\"\\{html_escape(id)}\\\"><code\\{class_attr}>\" +\n html_escape(source) +\n \"</code></pre>\"\n }\n Table(id~, ..) =>\n \"<figure id=\\\"\\{html_escape(id)}\\\" class=\\\"papyr-table-block\\\"></figure>\"\n Mermaid(id~, source~, ..) =>\n \"<pre id=\\\"\\{html_escape(id)}\\\"><code class=\\\"language-mermaid\\\">\" +\n html_escape(source) +\n \"</code></pre>\"\n Excalidraw(id~, ..) =>\n \"<figure id=\\\"\\{html_escape(id)}\\\" class=\\\"papyr-excalidraw\\\"></figure>\"\n }\n}\n\n///|\nfn render_inline_html(runs : Array[InlineRun]) -> String {\n let sb = StringBuilder::new()\n for run in runs {\n let mut text = html_escape(run.text)\n for mark in run.marks {\n if mark == \"bold\" {\n text = \"<strong>\" + text + \"</strong>\"\n } else if mark == \"italic\" {\n text = \"<em>\" + text + \"</em>\"\n } else if mark == \"code\" {\n text = \"<code>\" + text + \"</code>\"\n } else if mark == \"strike\" {\n text = \"<s>\" + text + \"</s>\"\n }\n }\n match run.href {\n Some(href) =>\n sb.write_string(\n \"<a href=\\\"\" + html_escape(href) + \"\\\">\" + text + \"</a>\",\n )\n None => sb.write_string(text)\n }\n }\n sb.to_string()\n}\n\n///|\nfn html_escape(source : String) -> String {\n let sb = StringBuilder::new()\n for ch in source {\n match ch {\n '&' => sb.write_string(\"&amp;\")\n '<' => sb.write_string(\"&lt;\")\n '>' => sb.write_string(\"&gt;\")\n '\"' => sb.write_string(\"&quot;\")\n '\\'' => sb.write_string(\"&#39;\")\n _ => sb.write_char(ch)\n }\n }\n sb.to_string()\n}\n\n///|\nfn join_with(parts : Array[String], separator : String) -> String {\n let sb = StringBuilder::new()\n for i, part in parts {\n if i > 0 {\n sb.write_string(separator)\n }\n sb.write_string(part)\n }\n sb.to_string()\n}\n","///|\npub(all) struct PapyrDocumentEnvelope {\n ok : Bool\n tool : String\n document : PapyrDocument?\n diagnostics : Array[Diagnostic]\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub fn parse_papyr_document_json(source : String) -> PapyrDocumentEnvelope {\n validate_papyr_document_json(@json.parse(source)) catch {\n e =>\n {\n ok: false,\n tool: \"parse_papyr_document_json\",\n document: None,\n diagnostics: [parse_error(\"Invalid PapyrDocument JSON: \\{e}\")],\n }\n }\n}\n\n///|\npub fn validate_papyr_document_json(json : Json) -> PapyrDocumentEnvelope {\n try {\n let doc : PapyrDocument = @json.from_json(json)\n let result = validate_papyr_document(doc)\n {\n ok: result.ok,\n tool: \"validate_papyr_document_json\",\n document: result.document,\n diagnostics: result.diagnostics,\n }\n } catch {\n e =>\n {\n ok: false,\n tool: \"validate_papyr_document_json\",\n document: None,\n diagnostics: [\n expected_type(\"\", \"PapyrDocument\", \"invalid JSON shape: \\{e}\"),\n ],\n }\n }\n}\n\n///|\npub fn validate_papyr_document(doc : PapyrDocument) -> PapyrDocumentEnvelope {\n let diagnostics : Array[Diagnostic] = []\n if doc.id == \"\" {\n diagnostics.push(invalid_value(\"id\", \"non-empty string\", \"empty string\"))\n }\n validate_blocks(doc.blocks, \"blocks\", diagnostics)\n {\n ok: diagnostics.length() == 0,\n tool: \"validate_papyr_document\",\n document: if diagnostics.length() == 0 {\n Some(doc)\n } else {\n None\n },\n diagnostics,\n }\n}\n\n///|\nfn validate_blocks(\n blocks : Array[Block],\n path : String,\n diagnostics : Array[Diagnostic],\n) -> Unit {\n for i, block in blocks {\n validate_block(block, index_path(path, i), diagnostics)\n }\n}\n\n///|\nfn validate_block(\n block : Block,\n path : String,\n diagnostics : Array[Diagnostic],\n) -> Unit {\n match block {\n Heading(level~, content~, ..) => {\n if level < 1 || level > 6 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"level\"),\n \"integer in range 1..6\",\n level.to_string(),\n ),\n )\n }\n validate_inline_runs(content, path_join(path, \"content\"), diagnostics)\n }\n Paragraph(content~, ..) =>\n validate_inline_runs(content, path_join(path, \"content\"), diagnostics)\n List(items~, ..) =>\n for i, item in items {\n validate_list_item(\n item,\n index_path(path_join(path, \"items\"), i),\n diagnostics,\n )\n }\n Code(_) => ()\n Table(_) => ()\n Mermaid(_) => ()\n Excalidraw(_) => ()\n }\n}\n\n///|\nfn validate_list_item(\n item : ListItem,\n path : String,\n diagnostics : Array[Diagnostic],\n) -> Unit {\n if item.blocks.length() == 0 {\n diagnostics.push(\n invalid_value(\n path_join(path, \"blocks\"),\n \"at least one block\",\n \"empty array\",\n ),\n )\n }\n validate_blocks(item.blocks, path_join(path, \"blocks\"), diagnostics)\n}\n\n///|\nfn validate_inline_runs(\n runs : Array[InlineRun],\n path : String,\n diagnostics : Array[Diagnostic],\n) -> Unit {\n for i, run in runs {\n validate_inline_run(run, index_path(path, i), diagnostics)\n }\n}\n\n///|\nfn validate_inline_run(\n run : InlineRun,\n path : String,\n diagnostics : Array[Diagnostic],\n) -> Unit {\n let mut has_link = false\n for i, mark in run.marks {\n if mark == \"link\" {\n has_link = true\n } else if mark != \"bold\" &&\n mark != \"italic\" &&\n mark != \"code\" &&\n mark != \"strike\" {\n diagnostics.push(\n invalid_value(\n index_path(path_join(path, \"marks\"), i),\n \"one of bold, italic, code, strike, link\",\n mark,\n ),\n )\n }\n }\n if has_link && run.href is None {\n diagnostics.push(missing_field(path, \"href\"))\n }\n}\n","///|\npub struct DocumentHeading {\n id : String\n level : Int\n text : String\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub struct DocumentBlockVisit {\n block : Block\n index_path : Array[Int]\n parent_list_item : ListItem?\n} derive(Eq, Debug, ToJson, @json.FromJson)\n\n///|\npub fn document_title(document : PapyrDocument) -> String {\n match document.title {\n Some(title) => {\n let normalized = collapse_whitespace(title)\n if normalized.length() > 0 {\n return normalized\n }\n }\n None => ()\n }\n for heading in collect_document_headings(document) {\n if heading.level == 1 {\n return heading.text\n }\n }\n document.id\n}\n\n///|\npub fn document_text(document : PapyrDocument) -> String {\n let parts : Array[String] = []\n for block in document.blocks {\n let text = document_block_text(block).trim().to_owned()\n if text.length() > 0 {\n parts.push(text)\n }\n }\n join_with(parts, \"\\n\")\n}\n\n///|\npub fn collect_document_headings(\n document : PapyrDocument,\n) -> Array[DocumentHeading] {\n let headings : Array[DocumentHeading] = []\n for visit in visit_document_blocks(document) {\n match visit.block {\n Heading(id~, level~, content~) => {\n let text = document_inline_text(content)\n if text.length() > 0 {\n headings.push({ id, level, text })\n }\n }\n _ => ()\n }\n }\n headings\n}\n\n///|\npub fn visit_document_blocks(document : PapyrDocument) -> Array[DocumentBlockVisit] {\n visit_blocks(document.blocks, [], None)\n}\n\n///|\npub fn replace_document_block(\n document : PapyrDocument,\n block_id : String,\n block : Block,\n) -> PapyrDocument {\n let (blocks, changed) = replace_blocks_by_id(document.blocks, block_id, block)\n if changed {\n {\n id: document.id,\n title: document.title,\n blocks,\n meta: document.meta,\n }\n } else {\n document\n }\n}\n\n///|\npub fn insert_document_block_after(\n document : PapyrDocument,\n block_id : String,\n block : Block,\n) -> PapyrDocument {\n let (blocks, changed) = insert_block_after_id(document.blocks, block_id, block)\n if changed {\n {\n id: document.id,\n title: document.title,\n blocks,\n meta: document.meta,\n }\n } else {\n document\n }\n}\n\n///|\npub fn remove_document_block(\n document : PapyrDocument,\n block_id : String,\n) -> PapyrDocument {\n let (blocks, changed) = remove_block_by_id(document.blocks, block_id)\n if changed {\n {\n id: document.id,\n title: document.title,\n blocks,\n meta: document.meta,\n }\n } else {\n document\n }\n}\n\n///|\nfn visit_blocks(\n blocks : Array[Block],\n base_path : Array[Int],\n parent_list_item : ListItem?,\n) -> Array[DocumentBlockVisit] {\n let visits : Array[DocumentBlockVisit] = []\n for index, block in blocks {\n let index_path = append_index(base_path, index)\n visits.push({ block, index_path, parent_list_item })\n match block {\n List(items~, ..) =>\n for item_index, item in items {\n let item_path = append_index(index_path, item_index)\n for visit in visit_blocks(item.blocks, item_path, Some(item)) {\n visits.push(visit)\n }\n }\n _ => ()\n }\n }\n visits\n}\n\n///|\nfn document_block_text(block : Block) -> String {\n match block {\n Heading(content~, ..) => document_inline_text(content)\n Paragraph(content~, ..) => document_inline_text(content)\n List(items~, ..) => {\n let parts : Array[String] = []\n for item in items {\n let child_parts : Array[String] = []\n for child in item.blocks {\n let text = document_block_text(child)\n if text.length() > 0 {\n child_parts.push(text)\n }\n }\n let text = join_with(child_parts, \"\\n\")\n if text.length() > 0 {\n parts.push(text)\n }\n }\n join_with(parts, \"\\n\")\n }\n Code(source~, ..) => source\n Table(columns~, rows~, caption~, ..) => {\n let parts : Array[String] = []\n for column in columns {\n parts.push(column.header)\n }\n for row in rows {\n for cell in row {\n parts.push(cell.text)\n }\n }\n match caption {\n Some(caption) => parts.push(caption)\n None => ()\n }\n join_with(parts, \" \")\n }\n Mermaid(source~, caption~, ..) =>\n match caption {\n Some(caption) => source + \"\\n\" + caption\n None => source\n }\n Excalidraw(caption~, ..) => caption.unwrap_or(\"\")\n }\n}\n\n///|\nfn document_inline_text(runs : Array[InlineRun]) -> String {\n let sb = StringBuilder::new()\n for run in runs {\n sb.write_string(run.text)\n }\n collapse_whitespace(sb.to_string())\n}\n\n///|\nfn collapse_whitespace(text : String) -> String {\n let sb = StringBuilder::new()\n let mut previous_space = false\n for ch in text {\n if ch == ' ' || ch == '\\n' || ch == '\\t' || ch == '\\r' {\n if !previous_space && sb.to_string().length() > 0 {\n sb.write_char(' ')\n }\n previous_space = true\n } else {\n sb.write_char(ch)\n previous_space = false\n }\n }\n sb.to_string().trim().to_owned()\n}\n\n///|\nfn append_index(path : Array[Int], index : Int) -> Array[Int] {\n let next : Array[Int] = []\n for part in path {\n next.push(part)\n }\n next.push(index)\n next\n}\n\n///|\nfn block_id(block : Block) -> String {\n match block {\n Heading(id~, ..) => id\n Paragraph(id~, ..) => id\n List(id~, ..) => id\n Code(id~, ..) => id\n Table(id~, ..) => id\n Mermaid(id~, ..) => id\n Excalidraw(id~, ..) => id\n }\n}\n\n///|\nfn replace_blocks_by_id(\n blocks : Array[Block],\n target_id : String,\n replacement : Block,\n) -> (Array[Block], Bool) {\n let next : Array[Block] = []\n let mut changed = false\n for block in blocks {\n if block_id(block) == target_id {\n next.push(replacement)\n changed = true\n continue\n }\n match block {\n List(id~, ordered~, items~) => {\n let (next_items, items_changed) = replace_list_items_by_id(\n items,\n target_id,\n replacement,\n )\n if items_changed {\n next.push(List(id~, ordered~, items=next_items))\n changed = true\n } else {\n next.push(block)\n }\n }\n _ => next.push(block)\n }\n }\n (next, changed)\n}\n\n///|\nfn replace_list_items_by_id(\n items : Array[ListItem],\n target_id : String,\n replacement : Block,\n) -> (Array[ListItem], Bool) {\n let next : Array[ListItem] = []\n let mut changed = false\n for item in items {\n let (blocks, blocks_changed) = replace_blocks_by_id(\n item.blocks,\n target_id,\n replacement,\n )\n if blocks_changed {\n next.push({ blocks, })\n changed = true\n } else {\n next.push(item)\n }\n }\n (next, changed)\n}\n\n///|\nfn insert_block_after_id(\n blocks : Array[Block],\n target_id : String,\n insert : Block,\n) -> (Array[Block], Bool) {\n let next : Array[Block] = []\n let mut changed = false\n for block in blocks {\n match block {\n List(id~, ordered~, items~) => {\n let (next_items, items_changed) = insert_list_items_after_id(\n items,\n target_id,\n insert,\n )\n if items_changed {\n next.push(List(id~, ordered~, items=next_items))\n changed = true\n } else {\n next.push(block)\n }\n }\n _ => next.push(block)\n }\n if block_id(block) == target_id {\n next.push(insert)\n changed = true\n }\n }\n (next, changed)\n}\n\n///|\nfn insert_list_items_after_id(\n items : Array[ListItem],\n target_id : String,\n insert : Block,\n) -> (Array[ListItem], Bool) {\n let next : Array[ListItem] = []\n let mut changed = false\n for item in items {\n let (blocks, blocks_changed) = insert_block_after_id(\n item.blocks,\n target_id,\n insert,\n )\n if blocks_changed {\n next.push({ blocks, })\n changed = true\n } else {\n next.push(item)\n }\n }\n (next, changed)\n}\n\n///|\nfn remove_block_by_id(\n blocks : Array[Block],\n target_id : String,\n) -> (Array[Block], Bool) {\n let next : Array[Block] = []\n let mut changed = false\n for block in blocks {\n if block_id(block) == target_id {\n changed = true\n continue\n }\n match block {\n List(id~, ordered~, items~) => {\n let (next_items, items_changed) = remove_list_items_by_id(\n items,\n target_id,\n )\n if items_changed {\n next.push(List(id~, ordered~, items=next_items))\n changed = true\n } else {\n next.push(block)\n }\n }\n _ => next.push(block)\n }\n }\n (next, changed)\n}\n\n///|\nfn remove_list_items_by_id(\n items : Array[ListItem],\n target_id : String,\n) -> (Array[ListItem], Bool) {\n let next : Array[ListItem] = []\n let mut changed = false\n for item in items {\n let (blocks, blocks_changed) = remove_block_by_id(item.blocks, target_id)\n if blocks_changed {\n next.push({ blocks, })\n changed = true\n } else {\n next.push(item)\n }\n }\n (next, changed)\n}\n","///|\npub struct AuthoringToolEnvelope {\n ok : Bool\n tool : String\n snapshot : AuthoringSessionSnapshot?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentReadEnvelope {\n ok : Bool\n tool : String\n document : AuthoringDocumentRecord?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DocumentsReadEnvelope {\n ok : Bool\n tool : String\n documents : Array[AuthoringDocumentRecord]\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct WorkspacesReadEnvelope {\n ok : Bool\n tool : String\n workspace : AuthoringWorkspace\n workspaces : Array[WorkspaceSummary]\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PublicationsReadEnvelope {\n ok : Bool\n tool : String\n publications : Array[AuthoringPublicationRecord]\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PreviewReadEnvelope {\n ok : Bool\n tool : String\n preview : PreviewState\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct SearchReadEnvelope {\n ok : Bool\n tool : String\n search : SearchState\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PublicationSearchEnvelope {\n ok : Bool\n tool : String\n query : String\n section : String\n limit : Int\n results : Array[AuthoringPublicationRecord]\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DiagnosticsReadEnvelope {\n ok : Bool\n tool : String\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PublishReadinessEnvelope {\n ok : Bool\n tool : String\n ready : Bool\n blocking_reasons : Array[String]\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub let app_server_artifact_schema_version : String = \"papyr.app-server-artifact.v0\"\n\n///|\npub struct ApprovalProposal {\n kind : String\n approval_required : Bool\n summary : String\n workspace_id : String?\n target_endpoint : String?\n document_count : Int\n changed_document_ids : Array[String]\n document_id : String?\n publish_target : PublishTarget?\n snapshot : AuthoringSessionSnapshot\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct ApprovalProposalEnvelope {\n ok : Bool\n tool : String\n proposal : ApprovalProposal?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct WorkspaceSourceBundle {\n workspace : AuthoringWorkspace\n documents : Array[AuthoringDocumentRecord]\n publications : Array[AuthoringPublicationRecord]\n selection : AuthoringSelectionState\n preview : PreviewState\n search : SearchState\n publish : PublishState\n exported_at : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct WorkspaceExportEnvelope {\n ok : Bool\n tool : String\n schema_version : String\n artifact_kind : String\n workspace_id : String\n generated_at : String\n bundle : WorkspaceSourceBundle?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PublicationPayloadBundle {\n workspace_id : String\n publication : AuthoringPublicationRecord\n document : AuthoringDocumentRecord?\n target : PublishTarget?\n generated_at : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PublicationPayloadEnvelope {\n ok : Bool\n tool : String\n schema_version : String\n artifact_kind : String\n workspace_id : String\n publication_id : String\n generated_at : String\n bundle : PublicationPayloadBundle?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PreviewArtifactBundle {\n workspace_id : String\n preview : PreviewState\n document : AuthoringDocumentRecord?\n publication : AuthoringPublicationRecord?\n generated_at : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct PreviewArtifactEnvelope {\n ok : Bool\n tool : String\n schema_version : String\n artifact_kind : String\n workspace_id : String\n generated_at : String\n bundle : PreviewArtifactBundle?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DiagnosticReportBundle {\n workspace_id : String\n diagnostics : Array[AuthoringDiagnostic]\n generated_at : String\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\npub struct DiagnosticReportEnvelope {\n ok : Bool\n tool : String\n schema_version : String\n artifact_kind : String\n workspace_id : String\n generated_at : String\n bundle : DiagnosticReportBundle?\n diagnostics : Array[AuthoringDiagnostic]\n} derive(Eq, ToJson, @json.FromJson)\n\n///|\nfn empty_authoring_context() -> Map[String, Json] {\n Map::new()\n}\n\n///|\nfn authoring_diagnostic(\n code : String,\n target : String,\n message : String,\n hint? : String? = None,\n) -> AuthoringDiagnostic {\n {\n code,\n severity: \"error\",\n target,\n message,\n hint,\n context: empty_authoring_context(),\n }\n}\n\n///|\npub fn app_server_bridge_error(\n tool : String,\n message : String,\n) -> AuthoringToolEnvelope {\n {\n ok: false,\n tool,\n snapshot: None,\n diagnostics: [authoring_diagnostic(\"bridge_error\", \"request\", message)],\n }\n}\n\n///|\nfn document_validation_diagnostics(\n diagnostics : Array[Diagnostic],\n) -> Array[AuthoringDiagnostic] {\n let result : Array[AuthoringDiagnostic] = []\n for diagnostic in diagnostics {\n let context = empty_authoring_context()\n context[\"kind\"] = diagnostic.kind.to_json()\n context[\"path\"] = diagnostic.path.to_json()\n match diagnostic.expected {\n Some(expected) => context[\"expected\"] = expected.to_json()\n None => ()\n }\n match diagnostic.received {\n Some(received) => context[\"received\"] = received.to_json()\n None => ()\n }\n result.push({\n code: diagnostic.code,\n severity: \"error\",\n target: \"document.\\{diagnostic.path}\",\n message: diagnostic.message,\n hint: Some(\"Fix the PapyrDocument JSON payload before saving.\"),\n context,\n })\n }\n result\n}\n\n///|\nfn validate_optional_document_payload(\n document : PapyrDocument?,\n) -> (PapyrDocument?, Array[AuthoringDiagnostic]) {\n match document {\n Some(value) => {\n let envelope = validate_papyr_document(value)\n if envelope.ok {\n (envelope.document, [])\n } else {\n (None, document_validation_diagnostics(envelope.diagnostics))\n }\n }\n None => (None, [])\n }\n}\n\n///|\nfn last_action(\n name : String,\n at : String,\n status : String,\n summary : String,\n) -> LastActionState {\n { name, at, status, summary }\n}\n\n///|\nfn workspace_summary(\n workspace : AuthoringWorkspace,\n document_count : Int,\n) -> WorkspaceSummary {\n {\n id: workspace.id,\n name: workspace.name,\n document_count,\n updated_at: workspace.updated_at,\n }\n}\n\n///|\nfn refresh_workspace_summaries(\n snapshot : AuthoringSessionSnapshot,\n) -> Array[WorkspaceSummary] {\n let summaries = []\n let mut found_current = false\n for summary in snapshot.workspace_summaries {\n if summary.id == snapshot.workspace.id {\n summaries.push(\n workspace_summary(snapshot.workspace, snapshot.documents.length()),\n )\n found_current = true\n } else {\n summaries.push(summary)\n }\n }\n if !found_current {\n summaries.push(\n workspace_summary(snapshot.workspace, snapshot.documents.length()),\n )\n }\n summaries\n}\n\n///|\nfn recompute_publish_state(snapshot : AuthoringSessionSnapshot) -> PublishState {\n let reasons = []\n if snapshot.workspace.publish_target is None {\n reasons.push(\"publish target is not configured\")\n }\n if snapshot.documents.length() == 0 {\n reasons.push(\"workspace has no documents\")\n }\n {\n ready: reasons.length() == 0,\n blocking_reasons: reasons,\n target: snapshot.workspace.publish_target,\n last_result: snapshot.publish.last_result,\n }\n}\n\n///|\nfn rebuild_snapshot(\n snapshot : AuthoringSessionSnapshot,\n workspace? : AuthoringWorkspace = snapshot.workspace,\n documents? : Array[AuthoringDocumentRecord] = snapshot.documents,\n publications? : Array[AuthoringPublicationRecord] = snapshot.publications,\n selection? : AuthoringSelectionState = snapshot.selection,\n preview? : PreviewState = snapshot.preview,\n search? : SearchState = snapshot.search,\n diagnostics? : Array[AuthoringDiagnostic] = snapshot.diagnostics,\n last_action? : LastActionState? = snapshot.last_action,\n) -> AuthoringSessionSnapshot {\n let next = {\n schema_version: snapshot.schema_version,\n workspace,\n workspace_summaries: snapshot.workspace_summaries,\n documents,\n publications,\n selection,\n preview,\n search,\n publish: snapshot.publish,\n diagnostics,\n last_action,\n }\n let with_publish = {\n schema_version: next.schema_version,\n workspace: next.workspace,\n workspace_summaries: next.workspace_summaries,\n documents: next.documents,\n publications: next.publications,\n selection: next.selection,\n preview: next.preview,\n search: next.search,\n publish: recompute_publish_state(next),\n diagnostics: next.diagnostics,\n last_action: next.last_action,\n }\n {\n schema_version: with_publish.schema_version,\n workspace: with_publish.workspace,\n workspace_summaries: refresh_workspace_summaries(with_publish),\n documents: with_publish.documents,\n publications: with_publish.publications,\n selection: with_publish.selection,\n preview: with_publish.preview,\n search: with_publish.search,\n publish: with_publish.publish,\n diagnostics: with_publish.diagnostics,\n last_action: with_publish.last_action,\n }\n}\n\n///|\nfn find_document(\n snapshot : AuthoringSessionSnapshot,\n document_id : String,\n) -> AuthoringDocumentRecord? {\n for document in snapshot.documents {\n if document.id == document_id {\n return Some(document)\n }\n }\n None\n}\n\n///|\nfn find_publication(\n snapshot : AuthoringSessionSnapshot,\n publication_id : String,\n) -> AuthoringPublicationRecord? {\n for publication in snapshot.publications {\n if publication.id == publication_id {\n return Some(publication)\n }\n }\n None\n}\n\n///|\nfn document_ids(snapshot : AuthoringSessionSnapshot) -> Array[String] {\n let ids = []\n for document in snapshot.documents {\n ids.push(document.id)\n }\n ids\n}\n\n///|\nfn has_workspace(\n snapshot : AuthoringSessionSnapshot,\n workspace_id : String,\n) -> Bool {\n if snapshot.workspace.id == workspace_id {\n return true\n }\n for summary in snapshot.workspace_summaries {\n if summary.id == workspace_id {\n return true\n }\n }\n false\n}\n\n///|\nfn publication_matches_query(\n publication : AuthoringPublicationRecord,\n query : String,\n) -> Bool {\n query == \"\" ||\n publication.title.contains(query[:]) ||\n publication.slug.contains(query[:]) ||\n publication.summary.contains(query[:])\n}\n\n///|\nfn publication_matches_section(\n publication : AuthoringPublicationRecord,\n section : String,\n) -> Bool {\n section == \"all\" || publication.section == section\n}\n\n///|\npub fn app_server_get_session_snapshot(\n snapshot : AuthoringSessionSnapshot,\n) -> AuthoringToolEnvelope {\n {\n ok: true,\n tool: \"get_session_snapshot\",\n snapshot: Some(snapshot),\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_get_workspaces(\n snapshot : AuthoringSessionSnapshot,\n) -> WorkspacesReadEnvelope {\n {\n ok: true,\n tool: \"get_workspaces\",\n workspace: snapshot.workspace,\n workspaces: snapshot.workspace_summaries,\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_get_publications(\n snapshot : AuthoringSessionSnapshot,\n) -> PublicationsReadEnvelope {\n {\n ok: true,\n tool: \"get_publications\",\n publications: snapshot.publications,\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_get_documents(\n snapshot : AuthoringSessionSnapshot,\n) -> DocumentsReadEnvelope {\n {\n ok: true,\n tool: \"get_documents\",\n documents: snapshot.documents,\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_get_document(\n snapshot : AuthoringSessionSnapshot,\n document_id : String,\n) -> DocumentReadEnvelope {\n match find_document(snapshot, document_id) {\n Some(document) =>\n {\n ok: true,\n tool: \"get_document\",\n document: Some(document),\n diagnostics: [],\n }\n None => {\n let diagnostic = authoring_diagnostic(\n \"document_not_found\",\n \"documents.\\{document_id}\",\n \"Document \\{document_id} was not found\",\n hint=Some(\"Create the document first or refresh the session snapshot.\"),\n )\n {\n ok: false,\n tool: \"get_document\",\n document: None,\n diagnostics: [diagnostic],\n }\n }\n }\n}\n\n///|\npub fn app_server_get_preview(\n snapshot : AuthoringSessionSnapshot,\n) -> PreviewReadEnvelope {\n { ok: true, tool: \"get_preview\", preview: snapshot.preview, diagnostics: [] }\n}\n\n///|\npub fn app_server_get_search(\n snapshot : AuthoringSessionSnapshot,\n) -> SearchReadEnvelope {\n { ok: true, tool: \"get_search\", search: snapshot.search, diagnostics: [] }\n}\n\n///|\npub fn app_server_search_publications(\n snapshot : AuthoringSessionSnapshot,\n query? : String = snapshot.search.query,\n section? : String = snapshot.search.section,\n limit? : Int = snapshot.search.limit,\n) -> PublicationSearchEnvelope {\n if limit <= 0 {\n let diagnostic = authoring_diagnostic(\n \"invalid_search_limit\", \"search.limit\", \"Search limit must be greater than zero\",\n )\n {\n ok: false,\n tool: \"search_publications\",\n query,\n section,\n limit,\n results: [],\n diagnostics: [diagnostic],\n }\n } else {\n let results = []\n for publication in snapshot.publications {\n if results.length() < limit &&\n publication_matches_section(publication, section) &&\n publication_matches_query(publication, query) {\n results.push(publication)\n }\n }\n {\n ok: true,\n tool: \"search_publications\",\n query,\n section,\n limit,\n results,\n diagnostics: [],\n }\n }\n}\n\n///|\npub fn app_server_get_diagnostics(\n snapshot : AuthoringSessionSnapshot,\n) -> DiagnosticsReadEnvelope {\n { ok: true, tool: \"get_diagnostics\", diagnostics: snapshot.diagnostics }\n}\n\n///|\npub fn app_server_get_publish_readiness(\n snapshot : AuthoringSessionSnapshot,\n) -> PublishReadinessEnvelope {\n let publish = recompute_publish_state(snapshot)\n {\n ok: true,\n tool: \"get_publish_readiness\",\n ready: publish.ready,\n blocking_reasons: publish.blocking_reasons,\n diagnostics: snapshot.diagnostics,\n }\n}\n\n///|\npub fn app_server_open_workspace(\n snapshot : AuthoringSessionSnapshot,\n workspace_id : String,\n at~ : String,\n) -> AuthoringToolEnvelope {\n if has_workspace(snapshot, workspace_id) {\n let next = rebuild_snapshot(\n snapshot,\n selection={\n workspace_id,\n document_id: snapshot.selection.document_id,\n publication_id: snapshot.selection.publication_id,\n panel: \"workspace\",\n },\n last_action=Some(\n last_action(\n \"open_workspace\",\n at,\n \"ok\",\n \"opened workspace \\{workspace_id}\",\n ),\n ),\n )\n { ok: true, tool: \"open_workspace\", snapshot: Some(next), diagnostics: [] }\n } else {\n let diagnostic = authoring_diagnostic(\n \"workspace_not_found\",\n \"workspace.\\{workspace_id}\",\n \"Workspace \\{workspace_id} was not found\",\n )\n {\n ok: false,\n tool: \"open_workspace\",\n snapshot: Some(rebuild_snapshot(snapshot, diagnostics=[diagnostic])),\n diagnostics: [diagnostic],\n }\n }\n}\n\n///|\npub fn app_server_rename_workspace(\n snapshot : AuthoringSessionSnapshot,\n name : String,\n at~ : String,\n) -> AuthoringToolEnvelope {\n if name == \"\" {\n let diagnostic = authoring_diagnostic(\n \"invalid_workspace_name\", \"workspace.name\", \"Workspace name cannot be empty\",\n )\n {\n ok: false,\n tool: \"rename_workspace\",\n snapshot: Some(rebuild_snapshot(snapshot, diagnostics=[diagnostic])),\n diagnostics: [diagnostic],\n }\n } else {\n let workspace = {\n id: snapshot.workspace.id,\n name,\n updated_at: at,\n publish_target: snapshot.workspace.publish_target,\n }\n let next = rebuild_snapshot(\n snapshot,\n workspace~,\n last_action=Some(\n last_action(\"rename_workspace\", at, \"ok\", \"renamed workspace\"),\n ),\n )\n {\n ok: true,\n tool: \"rename_workspace\",\n snapshot: Some(next),\n diagnostics: [],\n }\n }\n}\n\n///|\npub fn app_server_create_document(\n snapshot : AuthoringSessionSnapshot,\n document_id : String,\n title : String,\n kind : String,\n source : String,\n document? : PapyrDocument? = None,\n at~ : String,\n) -> AuthoringToolEnvelope {\n if find_document(snapshot, document_id) is Some(_) {\n let diagnostic = authoring_diagnostic(\n \"document_already_exists\",\n \"documents.\\{document_id}\",\n \"Document \\{document_id} already exists\",\n )\n {\n ok: false,\n tool: \"create_document\",\n snapshot: Some(rebuild_snapshot(snapshot, diagnostics=[diagnostic])),\n diagnostics: [diagnostic],\n }\n } else {\n let (validated_document, validation_diagnostics) = validate_optional_document_payload(\n document,\n )\n if validation_diagnostics.length() > 0 {\n return {\n ok: false,\n tool: \"create_document\",\n snapshot: Some(\n rebuild_snapshot(snapshot, diagnostics=validation_diagnostics),\n ),\n diagnostics: validation_diagnostics,\n }\n }\n let documents = []\n for existing in snapshot.documents {\n documents.push(existing)\n }\n documents.push({\n id: document_id,\n title,\n kind,\n source,\n updated_at: at,\n document: validated_document,\n })\n let next = rebuild_snapshot(\n snapshot,\n documents~,\n selection={\n workspace_id: snapshot.workspace.id,\n document_id: Some(document_id),\n publication_id: snapshot.selection.publication_id,\n panel: \"editor\",\n },\n last_action=Some(\n last_action(\n \"create_document\",\n at,\n \"ok\",\n \"created document \\{document_id}\",\n ),\n ),\n )\n { ok: true, tool: \"create_document\", snapshot: Some(next), diagnostics: [] }\n }\n}\n\n///|\npub fn app_server_update_document(\n snapshot : AuthoringSessionSnapshot,\n document_id : String,\n title? : String? = None,\n kind? : String? = None,\n source? : String? = None,\n document? : PapyrDocument? = None,\n clear_document? : Bool = false,\n at~ : String,\n) -> AuthoringToolEnvelope {\n let documents = []\n let mut found = false\n for existing in snapshot.documents {\n if existing.id == document_id {\n found = true\n let mut validated_document = document\n if !clear_document {\n let (validated, validation_diagnostics) = validate_optional_document_payload(\n document,\n )\n if validation_diagnostics.length() > 0 {\n return {\n ok: false,\n tool: \"update_document\",\n snapshot: Some(\n rebuild_snapshot(snapshot, diagnostics=validation_diagnostics),\n ),\n diagnostics: validation_diagnostics,\n }\n }\n validated_document = validated\n }\n documents.push({\n id: existing.id,\n title: title.unwrap_or(existing.title),\n kind: kind.unwrap_or(existing.kind),\n source: source.unwrap_or(existing.source),\n updated_at: at,\n document: if clear_document {\n None\n } else {\n match validated_document {\n Some(value) => Some(value)\n None => existing.document\n }\n },\n })\n } else {\n documents.push(existing)\n }\n }\n if found {\n let next = rebuild_snapshot(\n snapshot,\n documents~,\n selection={\n workspace_id: snapshot.workspace.id,\n document_id: Some(document_id),\n publication_id: snapshot.selection.publication_id,\n panel: \"editor\",\n },\n last_action=Some(\n last_action(\n \"update_document\",\n at,\n \"ok\",\n \"updated document \\{document_id}\",\n ),\n ),\n )\n { ok: true, tool: \"update_document\", snapshot: Some(next), diagnostics: [] }\n } else {\n let diagnostic = authoring_diagnostic(\n \"document_not_found\",\n \"documents.\\{document_id}\",\n \"Document \\{document_id} was not found\",\n )\n {\n ok: false,\n tool: \"update_document\",\n snapshot: Some(rebuild_snapshot(snapshot, diagnostics=[diagnostic])),\n diagnostics: [diagnostic],\n }\n }\n}\n\n///|\npub fn app_server_delete_document(\n snapshot : AuthoringSessionSnapshot,\n document_id : String,\n) -> ApprovalProposalEnvelope {\n match find_document(snapshot, document_id) {\n Some(_) =>\n {\n ok: true,\n tool: \"delete_document\",\n proposal: Some({\n kind: \"delete_document\",\n approval_required: true,\n summary: \"Delete document \\{document_id}\",\n workspace_id: Some(snapshot.workspace.id),\n target_endpoint: None,\n document_count: snapshot.documents.length(),\n changed_document_ids: [document_id],\n document_id: Some(document_id),\n publish_target: None,\n snapshot,\n diagnostics: [],\n }),\n diagnostics: [],\n }\n None => {\n let diagnostic = authoring_diagnostic(\n \"document_not_found\",\n \"documents.\\{document_id}\",\n \"Document \\{document_id} was not found\",\n )\n {\n ok: false,\n tool: \"delete_document\",\n proposal: None,\n diagnostics: [diagnostic],\n }\n }\n }\n}\n\n///|\npub fn app_server_set_preview_route(\n snapshot : AuthoringSessionSnapshot,\n route : PreviewRoute,\n mode? : String = snapshot.preview.mode,\n at~ : String,\n) -> AuthoringToolEnvelope {\n let next = rebuild_snapshot(\n snapshot,\n preview={ route, mode },\n last_action=Some(\n last_action(\"set_preview_route\", at, \"ok\", \"changed preview route\"),\n ),\n )\n { ok: true, tool: \"set_preview_route\", snapshot: Some(next), diagnostics: [] }\n}\n\n///|\npub fn app_server_set_search_state(\n snapshot : AuthoringSessionSnapshot,\n query : String,\n section? : String = snapshot.search.section,\n limit? : Int = snapshot.search.limit,\n at~ : String,\n) -> AuthoringToolEnvelope {\n if limit <= 0 {\n let diagnostic = authoring_diagnostic(\n \"invalid_search_limit\", \"search.limit\", \"Search limit must be greater than zero\",\n )\n {\n ok: false,\n tool: \"set_search_state\",\n snapshot: Some(rebuild_snapshot(snapshot, diagnostics=[diagnostic])),\n diagnostics: [diagnostic],\n }\n } else {\n let next = rebuild_snapshot(\n snapshot,\n search={ query, section, limit },\n last_action=Some(\n last_action(\"set_search_state\", at, \"ok\", \"changed search state\"),\n ),\n )\n {\n ok: true,\n tool: \"set_search_state\",\n snapshot: Some(next),\n diagnostics: [],\n }\n }\n}\n\n///|\npub fn app_server_set_publish_target(\n snapshot : AuthoringSessionSnapshot,\n target : PublishTarget?,\n at~ : String,\n) -> AuthoringToolEnvelope {\n let workspace = {\n id: snapshot.workspace.id,\n name: snapshot.workspace.name,\n updated_at: at,\n publish_target: target,\n }\n let next = rebuild_snapshot(\n snapshot,\n workspace~,\n last_action=Some(\n last_action(\"set_publish_target\", at, \"ok\", \"changed publish target\"),\n ),\n )\n {\n ok: true,\n tool: \"set_publish_target\",\n snapshot: Some(next),\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_publish_workspace(\n snapshot : AuthoringSessionSnapshot,\n) -> ApprovalProposalEnvelope {\n let publish = recompute_publish_state(snapshot)\n if publish.ready {\n let target = snapshot.workspace.publish_target.unwrap()\n {\n ok: true,\n tool: \"publish_workspace\",\n proposal: Some({\n kind: \"publish_workspace\",\n approval_required: true,\n summary: \"Publish \\{snapshot.documents.length()} document(s) from workspace \\{snapshot.workspace.id} to \\{target.endpoint}\",\n workspace_id: Some(snapshot.workspace.id),\n target_endpoint: Some(target.endpoint),\n document_count: snapshot.documents.length(),\n changed_document_ids: document_ids(snapshot),\n document_id: None,\n publish_target: Some(target),\n snapshot,\n diagnostics: [],\n }),\n diagnostics: [],\n }\n } else {\n let diagnostic = authoring_diagnostic(\n \"publish_not_ready\",\n \"publish\",\n \"Workspace is not ready to publish\",\n hint=Some(publish.blocking_reasons.join(\", \")),\n )\n {\n ok: false,\n tool: \"publish_workspace\",\n proposal: None,\n diagnostics: [diagnostic],\n }\n }\n}\n\n///|\npub fn app_server_export_workspace_source(\n snapshot : AuthoringSessionSnapshot,\n at~ : String,\n) -> WorkspaceExportEnvelope {\n {\n ok: true,\n tool: \"export_workspace_source\",\n schema_version: app_server_artifact_schema_version,\n artifact_kind: \"workspace_source\",\n workspace_id: snapshot.workspace.id,\n generated_at: at,\n bundle: Some({\n workspace: snapshot.workspace,\n documents: snapshot.documents,\n publications: snapshot.publications,\n selection: snapshot.selection,\n preview: snapshot.preview,\n search: snapshot.search,\n publish: recompute_publish_state(snapshot),\n exported_at: at,\n }),\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_export_publication_payload(\n snapshot : AuthoringSessionSnapshot,\n publication_id : String,\n at~ : String,\n) -> PublicationPayloadEnvelope {\n match find_publication(snapshot, publication_id) {\n Some(publication) =>\n {\n ok: true,\n tool: \"export_publication_payload\",\n schema_version: app_server_artifact_schema_version,\n artifact_kind: \"publication_payload\",\n workspace_id: snapshot.workspace.id,\n publication_id,\n generated_at: at,\n bundle: Some({\n workspace_id: snapshot.workspace.id,\n publication,\n document: find_document(snapshot, publication.document_id),\n target: snapshot.workspace.publish_target,\n generated_at: at,\n }),\n diagnostics: [],\n }\n None => {\n let diagnostic = authoring_diagnostic(\n \"publication_not_found\",\n \"publications.\\{publication_id}\",\n \"Publication \\{publication_id} was not found\",\n )\n {\n ok: false,\n tool: \"export_publication_payload\",\n schema_version: app_server_artifact_schema_version,\n artifact_kind: \"publication_payload\",\n workspace_id: snapshot.workspace.id,\n publication_id,\n generated_at: at,\n bundle: None,\n diagnostics: [diagnostic],\n }\n }\n }\n}\n\n///|\npub fn app_server_export_preview_artifact(\n snapshot : AuthoringSessionSnapshot,\n at~ : String,\n) -> PreviewArtifactEnvelope {\n let document = match snapshot.selection.document_id {\n Some(document_id) => find_document(snapshot, document_id)\n None => None\n }\n let publication = match snapshot.selection.publication_id {\n Some(publication_id) => find_publication(snapshot, publication_id)\n None => None\n }\n {\n ok: true,\n tool: \"export_preview_artifact\",\n schema_version: app_server_artifact_schema_version,\n artifact_kind: \"preview_artifact\",\n workspace_id: snapshot.workspace.id,\n generated_at: at,\n bundle: Some({\n workspace_id: snapshot.workspace.id,\n preview: snapshot.preview,\n document,\n publication,\n generated_at: at,\n }),\n diagnostics: [],\n }\n}\n\n///|\npub fn app_server_export_diagnostic_report(\n snapshot : AuthoringSessionSnapshot,\n at~ : String,\n) -> DiagnosticReportEnvelope {\n {\n ok: true,\n tool: \"export_diagnostic_report\",\n schema_version: app_server_artifact_schema_version,\n artifact_kind: \"diagnostic_report\",\n workspace_id: snapshot.workspace.id,\n generated_at: at,\n bundle: Some({\n workspace_id: snapshot.workspace.id,\n diagnostics: snapshot.diagnostics,\n generated_at: at,\n }),\n diagnostics: [],\n }\n}\n","///|\nstruct TableMarkdownPayload {\n columns : Array[@core.TableColumn]\n rows : Array[Array[@core.TableCell]]\n caption : String?\n} derive(ToJson, @json.FromJson)\n\n///|\nstruct ExcalidrawMarkdownPayload {\n elements : Array[Json]\n app_state : Map[String, Json]?\n files : Map[String, Json]?\n svg : String?\n caption : String?\n} derive(ToJson, @json.FromJson)\n\n///|\npub fn document_to_markdown(doc : @core.PapyrDocument) -> String {\n let parts : Array[String] = []\n for block in doc.blocks {\n parts.push(block_to_markdown(block))\n }\n join_blocks(parts)\n}\n\n///|\nfn block_to_markdown(block : @core.Block) -> String {\n match block {\n @core.Block::Heading(level~, content~, ..) =>\n repeat_hash(level) + \" \" + inline_text(content)\n @core.Block::Paragraph(content~, ..) => inline_text(content)\n @core.Block::List(ordered~, items~, ..) => list_to_markdown(ordered, items)\n @core.Block::Code(language~, source~, ..) => {\n let lang = language.unwrap_or(\"\")\n \"```\" + lang + \"\\n\" + source + \"\\n```\"\n }\n @core.Block::Table(columns~, rows~, caption~, ..) =>\n if can_serialize_gfm_table(columns, rows, caption) {\n gfm_table_to_markdown(columns, rows)\n } else {\n \"```papyr-table\\n\" +\n ({ columns, rows, caption } : TableMarkdownPayload)\n .to_json()\n .stringify(indent=2) +\n \"\\n```\"\n }\n @core.Block::Mermaid(source~, ..) => \"```mermaid\\n\" + source + \"\\n```\"\n @core.Block::Excalidraw(elements~, app_state~, files~, svg~, caption~, ..) =>\n \"```papyr-excalidraw\\n\" +\n ({ elements, app_state, files, svg, caption } : ExcalidrawMarkdownPayload)\n .to_json()\n .stringify(indent=2) +\n \"\\n```\"\n }\n}\n\n///|\nfn list_to_markdown(ordered : Bool, items : Array[@core.ListItem]) -> String {\n let lines : Array[String] = []\n for i, item in items {\n let text = if item.blocks.length() == 0 {\n \"\"\n } else {\n match item.blocks[0] {\n @core.Block::Paragraph(content~, ..) => inline_text(content)\n _ => block_to_markdown(item.blocks[0])\n }\n }\n let marker = if ordered { \"\\{i + 1}. \" } else { \"- \" }\n lines.push(marker + text)\n }\n join_lines(lines)\n}\n\n///|\nfn can_serialize_gfm_table(\n columns : Array[@core.TableColumn],\n rows : Array[Array[@core.TableCell]],\n caption : String?,\n) -> Bool {\n if caption is Some(_) || columns.length() == 0 {\n return false\n }\n let used : Array[String] = []\n for i, column in columns {\n if column.width is Some(_) || column.key != unique_column_key(column.header, i, used) {\n return false\n }\n }\n for row in rows {\n if row.length() != columns.length() {\n return false\n }\n for cell in row {\n if cell.colspan is Some(_) || cell.rowspan is Some(_) {\n return false\n }\n }\n }\n true\n}\n\n///|\nfn gfm_table_to_markdown(\n columns : Array[@core.TableColumn],\n rows : Array[Array[@core.TableCell]],\n) -> String {\n let lines : Array[String] = []\n lines.push(\"| \" + join_table_cells(columns.map(fn(c) { c.header })) + \" |\")\n lines.push(\"| \" + join_table_cells(columns.map(fn(c) { align_marker(c.align) })) + \" |\")\n for row in rows {\n lines.push(\"| \" + join_table_cells(row.map(fn(c) { c.text })) + \" |\")\n }\n join_lines(lines)\n}\n\n///|\nfn align_marker(align : String?) -> String {\n match align {\n Some(\"left\") => \":---\"\n Some(\"center\") => \":---:\"\n Some(\"right\") => \"---:\"\n _ => \"---\"\n }\n}\n\n///|\nfn join_table_cells(parts : Array[String]) -> String {\n let sb = StringBuilder::new()\n for i, part in parts {\n if i > 0 {\n sb.write_string(\" | \")\n }\n sb.write_string(part)\n }\n sb.to_string()\n}\n\n///|\nfn unique_column_key(header : String, index : Int, used : Array[String]) -> String {\n let base = normalize_column_key(header)\n let root = if base == \"\" { \"column-\\{index + 1}\" } else { base }\n let mut key = root\n let mut suffix = 2\n while used.contains(key) {\n key = root + \"-\\{suffix}\"\n suffix = suffix + 1\n }\n used.push(key)\n key\n}\n\n///|\nfn normalize_column_key(value : String) -> String {\n // Keep this intentionally smaller than JavaScript NFKC normalization: the\n // MoonBit bridge only needs deterministic keys for the supported table\n // subset and preserves non-ASCII letters as-is.\n let sb = StringBuilder::new()\n let mut previous_dash = false\n for ch in value.trim() {\n if (ch >= 'A' && ch <= 'Z') {\n if previous_dash && sb.to_string().length() == 0 {\n previous_dash = false\n }\n sb.write_char(Char::from_int(ch.to_int() + 32))\n previous_dash = false\n } else if (ch >= 'a' && ch <= 'z') ||\n (ch >= '0' && ch <= '9') ||\n ch > '~' {\n sb.write_char(ch)\n previous_dash = false\n } else if !previous_dash && sb.to_string().length() > 0 {\n sb.write_char('-')\n previous_dash = true\n }\n }\n let result = sb.to_string()\n if result.has_suffix(\"-\"[:]) {\n result[:result.length() - 1].to_owned()\n } else {\n result\n }\n}\n\n///|\nfn inline_text(runs : Array[@core.InlineRun]) -> String {\n let sb = StringBuilder::new()\n for run in runs {\n sb.write_string(run_to_markdown(run))\n }\n sb.to_string()\n}\n\n///|\nfn run_to_markdown(run : @core.InlineRun) -> String {\n let mut text = run.text\n for mark in run.marks {\n if mark == \"code\" {\n text = \"`\" + text + \"`\"\n } else if mark == \"bold\" {\n text = \"**\" + text + \"**\"\n } else if mark == \"italic\" {\n text = \"*\" + text + \"*\"\n } else if mark == \"strike\" {\n text = \"~~\" + text + \"~~\"\n }\n }\n match run.href {\n Some(href) => \"[\" + text + \"](\" + href + \")\"\n None => text\n }\n}\n\n///|\nfn repeat_hash(level : Int) -> String {\n let sb = StringBuilder::new()\n for _ in 0..<level {\n sb.write_char('#')\n }\n sb.to_string()\n}\n\n///|\nfn join_blocks(parts : Array[String]) -> String {\n let sb = StringBuilder::new()\n for i, part in parts {\n if i > 0 {\n sb.write_string(\"\\n\\n\")\n }\n sb.write_string(part)\n }\n sb.to_string()\n}\n\n///|\nfn join_lines(parts : Array[String]) -> String {\n let sb = StringBuilder::new()\n for i, part in parts {\n if i > 0 {\n sb.write_char('\\n')\n }\n sb.write_string(part)\n }\n sb.to_string()\n}\n\n///|\npub fn document_from_json(\n source : String,\n) -> Result[@core.PapyrDocument, String] {\n let envelope = @core.parse_papyr_document_json(source)\n match envelope.document {\n Some(doc) if envelope.ok => Ok(doc)\n _ =>\n if envelope.diagnostics.length() == 0 {\n Err(\"Invalid PapyrDocument JSON\")\n } else {\n Err(\"Invalid PapyrDocument JSON: \\{envelope.diagnostics[0].message}\")\n }\n }\n}\n","///|\nfn block_id(index : Int) -> String {\n \"b\\{index}\"\n}\n","///|\npub fn format_markdown(source : String) -> String {\n @markdown.document_to_markdown(@markdown.parse_markdown(source))\n}\n\n///|\npub fn format_document(doc : @core.PapyrDocument) -> String {\n @markdown.document_to_markdown(doc)\n}\n","///|\nstruct MarkdownParseRequest {\n markdown : String\n id : String?\n} derive(@json.FromJson)\n\n///|\nstruct AuthoringToolRequest {\n tool : String\n snapshot : @core.AuthoringSessionSnapshot\n input : Json?\n at : String?\n} derive(@json.FromJson)\n\n///|\nstruct CreateDocumentInput {\n id : String\n title : String\n kind : String\n source : String\n document : @core.PapyrDocument?\n} derive(@json.FromJson)\n\n///|\nstruct UpdateDocumentInput {\n id : String\n title : String?\n kind : String?\n source : String?\n document : @core.PapyrDocument?\n clear_document : Bool?\n} derive(@json.FromJson)\n\n///|\nstruct DocumentIdInput {\n id : String\n} derive(@json.FromJson)\n\n///|\nstruct DocumentStackToolRequest {\n tool : String\n input : Json?\n at : String?\n} derive(@json.FromJson)\n\n///|\nstruct ValidateDocumentInput {\n document : @core.PapyrDocument\n} derive(@json.FromJson)\n\n///|\nstruct DocumentUtilityInput {\n document : @core.PapyrDocument\n} derive(@json.FromJson)\n\n///|\nstruct DocumentBlockOperationInput {\n document : @core.PapyrDocument\n block_id : String\n block : @core.Block?\n} derive(@json.FromJson)\n\n///|\nstruct MarkdownToDocumentInput {\n markdown : String\n id : String?\n} derive(@json.FromJson)\n\n///|\nstruct DocumentToMarkdownInput {\n document : @core.PapyrDocument\n} derive(@json.FromJson)\n\n///|\nstruct FormatMarkdownInput {\n markdown : String\n} derive(@json.FromJson)\n\n///|\nstruct PreviewDocumentInput {\n document : @core.PapyrDocument\n mode : String?\n} derive(@json.FromJson)\n\n///|\nstruct PdfLayoutResolveInput {\n document : @core.PdfLayoutDocument\n data : @core.PdfLayoutData?\n mode : String?\n} derive(ToJson, @json.FromJson)\n\n///|\nstruct SearchDocumentsInput {\n documents : Array[@core.PapyrDocument]\n query : String\n limit : Int?\n} derive(@json.FromJson)\n\n///|\nstruct ExportPublicationInput {\n documents : Array[@core.PapyrDocument]\n publication_id : String\n generated_at : String?\n} derive(@json.FromJson)\n\n///|\nstruct ExportWorkspaceInput {\n documents : Array[@core.PapyrDocument]\n generated_at : String?\n} derive(@json.FromJson)\n\n///|\nstruct ExportPapyrBundleInput {\n documents : Array[@core.PapyrDocument]\n generated_at : String?\n} derive(@json.FromJson)\n\n///|\nstruct SerializeDocumentEnvelope {\n ok : Bool\n tool : String\n markdown : String\n diagnostics : Array[@core.Diagnostic]\n} derive(ToJson)\n\n///|\nfn document_bridge_diagnostic(message : String) -> @core.Diagnostic {\n {\n kind: \"parse\",\n code: \"bridge_error\",\n path: \"\",\n message,\n expected: Some(\"valid bridge request\"),\n received: Some(\"invalid request\"),\n }\n}\n\n///|\nfn document_bridge_error(tool : String, message : String) -> String {\n let envelope : @core.PapyrDocumentEnvelope = {\n ok: false,\n tool,\n document: None,\n diagnostics: [document_bridge_diagnostic(message)],\n }\n envelope.to_json().stringify()\n}\n\n///|\nfn serialize_bridge_error(tool : String, message : String) -> String {\n let envelope : SerializeDocumentEnvelope = {\n ok: false,\n tool,\n markdown: \"\",\n diagnostics: [document_bridge_diagnostic(message)],\n }\n envelope.to_json().stringify()\n}\n\n///|\nfn authoring_bridge_error(tool : String, message : String) -> String {\n @core.app_server_bridge_error(tool, message).to_json().stringify()\n}\n\n///|\nfn document_stack_bridge_error(tool : String, message : String) -> String {\n @core.document_stack_error(\n tool,\n \"bridge_error\",\n \"request\",\n message,\n expected=Some(\"valid document stack tool request\"),\n received=Some(\"invalid request\"),\n )\n .to_json()\n .stringify()\n}\n\n///|\nfn tool_input_json(request : DocumentStackToolRequest) -> Json {\n request.input.unwrap_or(Json::object(Map::new()))\n}\n\n///|\nfn markdown_result(tool : String, markdown : String) -> String {\n let result : Map[String, Json] = { \"markdown\": markdown.to_json() }\n @core.document_stack_success(tool, Json::object(result)).to_json().stringify()\n}\n\n///|\nfn markdown_mirrors(\n documents : Array[@core.PapyrDocument],\n) -> Array[@core.DocumentMarkdownMirror] {\n let mirrors : Array[@core.DocumentMarkdownMirror] = []\n for document in documents {\n mirrors.push({\n document_id: document.id,\n markdown: @markdown.document_to_markdown(document),\n })\n }\n mirrors\n}\n\n///|\npub fn papyr_validate_document_json(source : String) -> String {\n @core.parse_papyr_document_json(source).to_json().stringify()\n}\n\n///|\npub fn papyr_document_title_json(source : String) -> String {\n try {\n let input : DocumentUtilityInput = @json.from_json(@json.parse(source))\n @core.document_stack_success(\n \"document_title_json\",\n @core.document_title(input.document).to_json(),\n )\n .to_json()\n .stringify()\n } catch {\n e => document_stack_bridge_error(\"document_title_json\", \"Invalid document title request: \\{e}\")\n }\n}\n\n///|\npub fn papyr_document_plain_text_json(source : String) -> String {\n try {\n let input : DocumentUtilityInput = @json.from_json(@json.parse(source))\n @core.document_stack_success(\n \"document_plain_text_json\",\n @core.document_text(input.document).to_json(),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n document_stack_bridge_error(\n \"document_plain_text_json\",\n \"Invalid document plain text request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_collect_document_headings_json(source : String) -> String {\n try {\n let input : DocumentUtilityInput = @json.from_json(@json.parse(source))\n @core.document_stack_success(\n \"collect_document_headings_json\",\n @core.collect_document_headings(input.document).to_json(),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n document_stack_bridge_error(\n \"collect_document_headings_json\",\n \"Invalid collect document headings request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_visit_document_blocks_json(source : String) -> String {\n try {\n let input : DocumentUtilityInput = @json.from_json(@json.parse(source))\n @core.document_stack_success(\n \"visit_document_blocks_json\",\n @core.visit_document_blocks(input.document).to_json(),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n document_stack_bridge_error(\n \"visit_document_blocks_json\",\n \"Invalid visit document blocks request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_replace_document_block_json(source : String) -> String {\n try {\n let input : DocumentBlockOperationInput = @json.from_json(@json.parse(source))\n match input.block {\n Some(block) =>\n @core.document_stack_success(\n \"replace_document_block_json\",\n @core.replace_document_block(input.document, input.block_id, block)\n .to_json(),\n )\n .to_json()\n .stringify()\n None =>\n document_stack_bridge_error(\n \"replace_document_block_json\",\n \"Missing replacement block\",\n )\n }\n } catch {\n e =>\n document_stack_bridge_error(\n \"replace_document_block_json\",\n \"Invalid replace document block request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_insert_document_block_after_json(source : String) -> String {\n try {\n let input : DocumentBlockOperationInput = @json.from_json(@json.parse(source))\n match input.block {\n Some(block) =>\n @core.document_stack_success(\n \"insert_document_block_after_json\",\n @core.insert_document_block_after(input.document, input.block_id, block)\n .to_json(),\n )\n .to_json()\n .stringify()\n None =>\n document_stack_bridge_error(\n \"insert_document_block_after_json\",\n \"Missing inserted block\",\n )\n }\n } catch {\n e =>\n document_stack_bridge_error(\n \"insert_document_block_after_json\",\n \"Invalid insert document block request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_remove_document_block_json(source : String) -> String {\n try {\n let input : DocumentBlockOperationInput = @json.from_json(@json.parse(source))\n @core.document_stack_success(\n \"remove_document_block_json\",\n @core.remove_document_block(input.document, input.block_id).to_json(),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n document_stack_bridge_error(\n \"remove_document_block_json\",\n \"Invalid remove document block request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_resolve_pdf_layout_json(source : String) -> String {\n try {\n let input : PdfLayoutResolveInput = @json.from_json(@json.parse(source))\n @core.resolve_pdf_layout_document(\n input.document,\n input.data.unwrap_or(@core.pdf_layout_empty_data()),\n @core.pdf_layout_resolve_mode_from_string(input.mode.unwrap_or(\"pdf\")),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n @core.pdf_layout_resolve_error(\"Invalid PDF layout resolve request: \\{e}\")\n .to_json()\n .stringify()\n }\n}\n\n///|\npub fn papyr_parse_markdown_json(source : String) -> String {\n try {\n let request : MarkdownParseRequest = @json.from_json(@json.parse(source))\n @core.validate_papyr_document(\n @markdown.parse_markdown(\n request.markdown,\n id=request.id.unwrap_or(\"untitled\"),\n ),\n )\n .to_json()\n .stringify()\n } catch {\n e =>\n document_bridge_error(\n \"parse_markdown_json\",\n \"Invalid parse markdown request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_serialize_document_json(source : String) -> String {\n match @markdown.document_from_json(source) {\n Ok(doc) => {\n let envelope : SerializeDocumentEnvelope = {\n ok: true,\n tool: \"serialize_document_json\",\n markdown: @markdown.document_to_markdown(doc),\n diagnostics: [],\n }\n envelope.to_json().stringify()\n }\n Err(message) => serialize_bridge_error(\"serialize_document_json\", message)\n }\n}\n\n///|\npub fn papyr_document_tool_json(source : String) -> String {\n try {\n let request : DocumentStackToolRequest = @json.from_json(\n @json.parse(source),\n )\n match request.tool {\n \"validate_document\" => {\n let input : ValidateDocumentInput = @json.from_json(\n tool_input_json(request),\n )\n @core.document_stack_validate_document(input.document)\n .to_json()\n .stringify()\n }\n \"markdown_to_document\" => {\n let input : MarkdownToDocumentInput = @json.from_json(\n tool_input_json(request),\n )\n let document = @markdown.parse_markdown(\n input.markdown,\n id=input.id.unwrap_or(\"untitled\"),\n )\n let envelope = @core.validate_papyr_document(document)\n if envelope.ok {\n @core.document_stack_success(\n \"markdown_to_document\",\n document.to_json(),\n )\n .to_json()\n .stringify()\n } else {\n @core.document_stack_failure(\n \"markdown_to_document\",\n envelope.diagnostics,\n )\n .to_json()\n .stringify()\n }\n }\n \"document_to_markdown\" => {\n let input : DocumentToMarkdownInput = @json.from_json(\n tool_input_json(request),\n )\n let envelope = @core.validate_papyr_document(input.document)\n if envelope.ok {\n markdown_result(\n \"document_to_markdown\",\n @markdown.document_to_markdown(input.document),\n )\n } else {\n @core.document_stack_failure(\n \"document_to_markdown\",\n envelope.diagnostics,\n )\n .to_json()\n .stringify()\n }\n }\n \"format_markdown\" => {\n let input : FormatMarkdownInput = @json.from_json(\n tool_input_json(request),\n )\n markdown_result(\n \"format_markdown\",\n @formatter.format_markdown(input.markdown),\n )\n }\n \"preview_document\" => {\n let input : PreviewDocumentInput = @json.from_json(\n tool_input_json(request),\n )\n @core.document_stack_preview_document(\n input.document,\n mode=input.mode.unwrap_or(\"document\"),\n )\n .to_json()\n .stringify()\n }\n \"search_documents\" => {\n let input : SearchDocumentsInput = @json.from_json(\n tool_input_json(request),\n )\n @core.document_stack_search_documents(\n input.documents,\n input.query,\n limit=input.limit.unwrap_or(20),\n )\n .to_json()\n .stringify()\n }\n \"export_publication\" => {\n let input : ExportPublicationInput = @json.from_json(\n tool_input_json(request),\n )\n let generated_at = match input.generated_at {\n Some(value) => value\n None => request.at.unwrap_or(\"\")\n }\n @core.document_stack_export_publication(\n input.documents,\n input.publication_id,\n generated_at~,\n )\n .to_json()\n .stringify()\n }\n \"export_workspace\" => {\n let input : ExportWorkspaceInput = @json.from_json(\n tool_input_json(request),\n )\n let generated_at = match input.generated_at {\n Some(value) => value\n None => request.at.unwrap_or(\"\")\n }\n @core.document_stack_export_workspace(input.documents, generated_at~)\n .to_json()\n .stringify()\n }\n \"export_papyr_bundle\" => {\n let input : ExportPapyrBundleInput = @json.from_json(\n tool_input_json(request),\n )\n let generated_at = match input.generated_at {\n Some(value) => value\n None => request.at.unwrap_or(\"\")\n }\n @core.document_stack_export_papyr_bundle(\n input.documents,\n markdown_mirrors(input.documents),\n generated_at~,\n )\n .to_json()\n .stringify()\n }\n _ =>\n document_stack_bridge_error(\n request.tool,\n \"Unsupported document stack tool: \\{request.tool}\",\n )\n }\n } catch {\n e =>\n document_stack_bridge_error(\n \"document_tool_json\",\n \"Invalid document stack tool request: \\{e}\",\n )\n }\n}\n\n///|\npub fn papyr_authoring_tool_json(source : String) -> String {\n try {\n let request : AuthoringToolRequest = @json.from_json(@json.parse(source))\n let at = request.at.unwrap_or(\"\")\n match request.tool {\n \"get_session_snapshot\" =>\n @core.app_server_get_session_snapshot(request.snapshot)\n .to_json()\n .stringify()\n \"get_documents\" =>\n @core.app_server_get_documents(request.snapshot).to_json().stringify()\n \"get_document\" => {\n let input : DocumentIdInput = @json.from_json(\n request.input.unwrap_or(Json::object(Map::new())),\n )\n @core.app_server_get_document(request.snapshot, input.id)\n .to_json()\n .stringify()\n }\n \"create_document\" => {\n let input : CreateDocumentInput = @json.from_json(\n request.input.unwrap_or(Json::object(Map::new())),\n )\n @core.app_server_create_document(\n request.snapshot,\n input.id,\n input.title,\n input.kind,\n input.source,\n document=input.document,\n at~,\n )\n .to_json()\n .stringify()\n }\n \"update_document\" => {\n let input : UpdateDocumentInput = @json.from_json(\n request.input.unwrap_or(Json::object(Map::new())),\n )\n @core.app_server_update_document(\n request.snapshot,\n input.id,\n title=input.title,\n kind=input.kind,\n source=input.source,\n document=input.document,\n clear_document=input.clear_document.unwrap_or(false),\n at~,\n )\n .to_json()\n .stringify()\n }\n _ =>\n authoring_bridge_error(\n request.tool,\n \"Unsupported authoring tool: \\{request.tool}\",\n )\n }\n } catch {\n e =>\n authoring_bridge_error(\n \"authoring_tool_json\",\n \"Invalid authoring tool request: \\{e}\",\n )\n }\n}\n"],"names":["$i64_reinterpret_f64","moonbitlang/core/internal/strconv/FloatInfo","@moonbitlang/core/internal/strconv.left_shift_cheats.tuple","@moonbitlang/core/builtin.random_seed","$panic","moonbitlang/core/builtin/Json.Array","array","moonbitlang/core/builtin/Json.String","self","Show::output","obj","x","r","Math","@moonbitlang/core/builtin.rotl","input","Hasher::consume4","value","moonbitlang/core/builtin/StringBuilder","String","ch","Compare::op_ge","Compare::op_le","leading","trailing","c1","index","UInt16::is_leading_surrogate","c2","@moonbitlang/core/builtin.code_point_of_surrogate_pair","UInt16::unsafe_to_char","that","i","Byte::to_char","Add::add","Sub::sub","StringBuilder::StringBuilder.inner","Byte::to_hex.to_hex_digit","Div::div","b","Mod::mod","StringBuilder::to_string","*self","str_len","abs_end","*end","abs_start","start","UInt16::is_trailing_surrogate","moonbitlang/core/string/StringView","str","Number","BigInt","$compare_int","moonbitlang/core/builtin/Json.Number","number","repr","Hash::hash_combine","y","Compare::compare","acc","Hasher::avalanche","moonbitlang/core/builtin/Hasher","seed","h","Hasher::new","Hasher::combine","Hasher::finalize","show","@.moonbitlang/core/builtin/StringBuilder$as$@moonbitlang/core/builtin.Logger","len","end","Logger::write_view","String::sub.inner","logger","Show::to_string","*func","*bind","Iter::next.constr","*n","@moonbitlang/core/builtin.int_to_string_js","radix","size_hint","Iter::new.constr","moonbitlang/core/builtin/Iter[(String, moonbitlang/core/builtin/Json)]","f","moonbitlang/core/builtin/Iter[Char]","end_offset","StringView::length","start_offset","@moonbitlang/core/abort.abort","moonbitlang/core/builtin/MutLocal[Int]","Iter::new","Iter2::new.constr","moonbitlang/core/builtin/Iter[(Int, Char)]","char_index","Iter2::new","result","count","_tmp","utf16_offset","char_count","n","c","String::offset_of_nth_char_forward","String::offset_of_nth_char_backward","StringView::to_owned","haystack_len","haystack","needle_len","needle","skip_table","$make_array_len_and_init","StringView::unsafe_get","$bound_check","j","Eq::not_equal","@moonbitlang/core/builtin.boyer_moore_horspool_find.constr","needle_first","forward_len","@moonbitlang/core/builtin.brute_force_find.constr","@moonbitlang/core/builtin.brute_force_find","@moonbitlang/core/builtin.boyer_moore_horspool_find","StringView::find","total","buf","_","Logger::write_string","Iter2::next","*it","pred","*c","*i","StringView::find_by","@moonbitlang/core/builtin.brute_force_rev_find","@moonbitlang/core/builtin.boyer_moore_horspool_rev_find","StringView::rev_find","StringView::has_suffix","StringView::has_prefix","JSArray::push","StringView::contains","adj","high","low","StringView::contains_char","Iter::next","chars","StringView::contains_any","*x","StringView::trim_end.inner","StringView::trim_start.inner","StringView::trim.inner","moonbitlang/core/builtin/Iter[moonbitlang/core/string/StringView]","*Some","sep_len","sep","Iter::map","StringView::iter","String::view.inner","remaining","moonbitlang/core/builtin/MutLocal[moonbitlang/core/string/StringView?]","*view","StringView::view.inner","StringView::split","String::find_by","Char::is_ascii_uppercase","head","*idx","Logger::write_substring","StringView::data","StringView::start_offset","Logger::write_char","idx","next","*elem","Iter::iter2","String::iter","Int::to_string.inner","*t","capacity","Int::next_power_of_two","@moonbitlang/core/builtin.calc_grow_threshold","moonbitlang/core/builtin/Map[String, moonbitlang/core/builtin/Json]","length","other","entry","Option::unwrap","new_idx","*next","psl","Map::set_entry","*curr_entry","hash","Map::grow","moonbitlang/core/builtin/Entry[String, moonbitlang/core/builtin/Json]","key","Map::add_entry_to_tail","Map::push_away","old_head","new_capacity","Map::set_with_hash","*key","*value","*hash","Hash::hash","ArrayView::length","arr","@moonbitlang/core/builtin.capacity_for_length","Int::max","*capacity","m","@moonbitlang/core/builtin.new_map","Map::set","e","*entry","curr_entry","moonbitlang/core/builtin/MutLocal[moonbitlang/core/builtin/Entry[String, moonbitlang/core/builtin/Json]?]","Map::iter","string","boolean","moonbitlang/core/builtin/Json.True","moonbitlang/core/builtin/Json.False","moonbitlang/core/builtin/Json.Object","object","Json::boolean","Json::number","Array","v","Array::map","ToJson::to_json","Map::Map","moonbitlang/core/builtin/ArrayView[(String, moonbitlang/core/builtin/Json)]","*k","*v","Hasher::combine_uint","Hasher::combine_string","hasher","code","char","Byte::to_hex","Char::is_control","Int::is_surrogate","quote","Char::is_printable","Char::to_hex","Char::escape_to.inner","JSArray::pop","Array::is_empty","Array::unsafe_pop","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PapyrDocument], moonbitlang/core/json/JsonDecodeError].Ok","*ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/Block], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/InlineRun], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/ListItem], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/TableColumn], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/TableCell]], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[moonbitlang/core/builtin/Json], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfTextBinding], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfImageBinding], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfNumberBinding], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfBoolBinding], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfDataListBinding], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/WorkspaceSummary], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDocumentRecord], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringPublicationRecord], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDiagnostic], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/TableCell], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfLayoutPage], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[String], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfLayoutNode], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfDataRow], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfTableColumn], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfTextSource]], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfDataTableColumn], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfTextSource], moonbitlang/core/json/JsonDecodeError].Ok","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PdfConditionExpression], moonbitlang/core/json/JsonDecodeError].Ok","@Error.to_string","moonbitlang/core/result/Result[Unit, moonbitlang/core/builtin/Failure].Err","moonbitlang/core/error/Error.moonbitlang/core/builtin.Failure.Failure","@moonbitlang/core/internal/strconv.range_err_str","moonbitlang/core/result/Result[Double, moonbitlang/core/builtin/Failure].Err","@moonbitlang/core/internal/strconv.syntax_err_str","moonbitlang/core/result/Result[moonbitlang/core/internal/strconv/Number?, moonbitlang/core/builtin/Failure].Err","moonbitlang/core/result/Result[moonbitlang/core/string/StringView, moonbitlang/core/builtin/Failure].Err","*ch","ret","StringView::fold_digits","s","digit","@moonbitlang/core/internal/strconv.min_19digit_int","neg_exp","rest","@moonbitlang/core/internal/strconv.parse_scientific.exp_num","exp_num","*s","*exp_num","StringView::is_empty","moonbitlang/core/result/Result[moonbitlang/core/internal/strconv/Number?, moonbitlang/core/error/Error].Ok","@moonbitlang/core/internal/strconv.parse_digits","mantissa","*new_s","*new_mantissa","n_after_dot","*consumed_digit","exponent","n_digits","@moonbitlang/core/internal/strconv.parse_scientific","*exp_number","moonbitlang/core/internal/strconv/Number","negative","many_digits","@moonbitlang/core/internal/strconv.try_parse_19digits","String::char_length_ge.inner","String::offset_of_nth_char.inner","@moonbitlang/core/internal/strconv.parse_number.exp_number","@moonbitlang/core/internal/strconv.syntax_err","pos","moonbitlang/core/result/Result[Double, moonbitlang/core/error/Error].Ok","@moonbitlang/core/double.infinity","@moonbitlang/core/double.neg_infinity","a","@moonbitlang/core/internal/strconv.checked_mul.constr","$i64_clz","quotient","hex","follow_underscore","moonbitlang/core/internal/strconv/Decimal","$makebytes","Default::default","Eq::equal","d","@moonbitlang/core/internal/strconv.Decimal::new_priv","has_dp","has_digits","exp_sign","exp_limit","exp","@moonbitlang/core/internal/strconv.Decimal::trim","moonbitlang/core/result/Result[moonbitlang/core/internal/strconv/Decimal, moonbitlang/core/error/Error].Ok","@moonbitlang/core/internal/strconv.parse_decimal_from_view","biased_exp","@moonbitlang/core/internal/strconv.double_info","exp_bits","bits","Byte::to_int64","@moonbitlang/core/internal/strconv.Decimal::should_round_up","new_digits","ReadOnlyArray::at","@moonbitlang/core/internal/strconv.left_shift_cheats","cheat_num","less","@moonbitlang/core/internal/strconv.Decimal::new_digits","read_index","quo","rem","write_index","mask","out","UInt64::to_byte","@moonbitlang/core/internal/strconv.Decimal::left_shift","@moonbitlang/core/internal/strconv.Decimal::right_shift","@moonbitlang/core/internal/strconv.assemble_bits","@moonbitlang/core/internal/strconv.range_err","ReadOnlyArray::length","@moonbitlang/core/internal/strconv.powtab","@moonbitlang/core/internal/strconv.Decimal::shift_priv","@moonbitlang/core/internal/strconv.Decimal::rounded_integer","@moonbitlang/core/internal/strconv.table","@moonbitlang/core/internal/strconv.min_exponent_fast_path","@moonbitlang/core/internal/strconv.max_exponent_disguised_fast_path","@moonbitlang/core/internal/strconv.max_mantissa_fast_path","@moonbitlang/core/internal/strconv.Number::is_fast_path","@moonbitlang/core/internal/strconv.max_exponent_fast_path","$f64_convert_i64_u","@moonbitlang/core/internal/strconv.pow10_fast_path","shift","@moonbitlang/core/internal/strconv.checked_mul","@moonbitlang/core/internal/strconv.int_pow10","moonbitlang/core/option/Option[Double].None","moonbitlang/core/option/Option[Double].Some","@moonbitlang/core/internal/strconv.check_underscore","@moonbitlang/core/internal/strconv.parse_number","@moonbitlang/core/internal/strconv.parse_inf_nan","*num","@moonbitlang/core/internal/strconv.Number::try_fast_path","@moonbitlang/core/internal/strconv.parse_decimal_priv","@moonbitlang/core/internal/strconv.Decimal::to_double_priv","line","column","moonbitlang/core/json/Position","offset","ctx","moonbitlang/core/result/Result[moonbitlang/core/builtin/Json, moonbitlang/core/json/ParseError].Err","moonbitlang/core/error/Error.moonbitlang/core/json.ParseError.InvalidChar","@moonbitlang/core/json.offset_to_position","Option::unwrap_or","StringView::get_char","moonbitlang/core/result/Result[Unit, moonbitlang/core/json/ParseError].Err","Char::escape.inner","Logger::write_object","*line","*column","moonbitlang/core/result/Result[String, moonbitlang/core/json/JsonDecodeError].Err","moonbitlang/core/error/Error.moonbitlang/core/json.JsonDecodeError.JsonDecodeError","path","msg","moonbitlang/core/result/Result[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/PapyrDocument], moonbitlang/core/json/JsonDecodeError].Err","moonbitlang/core/result/Result[Int, moonbitlang/core/json/JsonDecodeError].Err","moonbitlang/core/result/Result[Unit, moonbitlang/core/json/JsonDecodeError].Err","moonbitlang/core/result/Result[Bool, moonbitlang/core/json/JsonDecodeError].Err","moonbitlang/core/json/JsonPath.Index","moonbitlang/core/json/ParseContext","max_nesting_depth","@moonbitlang/core/json.ParseContext::invalid_char.inner","moonbitlang/core/result/Result[Unit, moonbitlang/core/json/ParseError].Ok","moonbitlang/core/error/Error.moonbitlang/core/json.ParseError.InvalidEof","@moonbitlang/core/json.checked_mul.constr","@moonbitlang/core/json.pow10_table","@moonbitlang/core/json.json_pow10_fast_path","@moonbitlang/core/json.checked_mul","@moonbitlang/core/json.int_pow10_table","number_start","$f64_convert_i64","has_exponent","exponent_part","next_exponent","has_decimal","fractional_digits","seen_nonzero","significant_digits","exponent_negative","moonbitlang/core/json/JsonNumberScan","scan","@moonbitlang/core/json.ParseContext::scan_json_number","@moonbitlang/core/json.ParseContext::lex_integer_end","@moonbitlang/core/json.JsonNumberScan::try_fast_double","*d","parsed_double","@moonbitlang/core/internal/strconv.parse_double","*err","*try_err","c3","@moonbitlang/core/json.ParseContext::read_char","@moonbitlang/core/json.ParseContext::lex_number_end","moonbitlang/core/result/Result[(Double, moonbitlang/core/string/StringView?), moonbitlang/core/json/ParseError].Err","moonbitlang/core/result/Result[(Double, moonbitlang/core/string/StringView?), moonbitlang/core/json/ParseError].Ok","@moonbitlang/core/json.ParseContext::lex_decimal_exponent_integer","@moonbitlang/core/json.ParseContext::lex_decimal_exponent_sign","@moonbitlang/core/json.ParseContext::lex_decimal_exponent","@moonbitlang/core/json.ParseContext::lex_decimal_fraction","@moonbitlang/core/json.ParseContext::lex_decimal_point","moonbitlang/core/result/Result[Int, moonbitlang/core/json/ParseError].Err","StringView::sub.inner","*env","moonbitlang/core/result/Result[String, moonbitlang/core/json/ParseError].Err","@moonbitlang/core/json.ParseContext::lex_string_slow.flush","@moonbitlang/core/json.ParseContext::lex_hex_digits","string_start","moonbitlang/core/result/Result[String, moonbitlang/core/json/ParseError].Ok","@moonbitlang/core/json.ParseContext::lex_string_slow","@moonbitlang/core/json.ParseContext::lex_skip_whitespace","moonbitlang/core/result/Result[moonbitlang/core/json/Token, moonbitlang/core/json/ParseError].Err","moonbitlang/core/result/Result[moonbitlang/core/json/Token, moonbitlang/core/json/ParseError].Ok","moonbitlang/core/json/Token.LBrace","moonbitlang/core/json/Token.LBracket","allow_rbracket","moonbitlang/core/json/Token.RBracket","@moonbitlang/core/json.ParseContext::expect_ascii_char","moonbitlang/core/json/Token.Null","moonbitlang/core/json/Token.True","moonbitlang/core/json/Token.False","@moonbitlang/core/json.ParseContext::lex_zero","moonbitlang/core/json/Token.Number","Option::map","*repr","@moonbitlang/core/json.ParseContext::lex_decimal_integer","@moonbitlang/core/json.ParseContext::lex_string","moonbitlang/core/json/Token.String","Char::utf16_len","@moonbitlang/core/json.ParseContext::lex_value","tok","@moonbitlang/core/json.ParseContext::parse_value2","Json::string","@moonbitlang/core/json.ParseContext::parse_object","@moonbitlang/core/json.ParseContext::parse_array","moonbitlang/core/error/Error.moonbitlang/core/json.ParseError.DepthLimitExceeded","vec","Json::array","Array::push","@moonbitlang/core/json.ParseContext::lex_after_array_value","tok2","map","@moonbitlang/core/json.ParseContext::lex_property_name","Json::object","@moonbitlang/core/json.ParseContext::lex_after_property_name","@moonbitlang/core/json.ParseContext::parse_value","*name","@moonbitlang/core/json.ParseContext::lex_after_object_value","@moonbitlang/core/json.ParseContext::lex_property_name2","@moonbitlang/core/json.ParseContext::make","val","moonbitlang/core/result/Result[moonbitlang/core/builtin/Json, moonbitlang/core/json/ParseError].Ok","escape_slash","indent","spaces","level","String::repeat","stack","*arr","element","Array::at","*Array","@moonbitlang/core/json.indent_str","depth","Array::pop","*iterator","*replacer","v2","*first","@moonbitlang/core/json.escape","*Object","Map::is_empty","*members","moonbitlang/core/json/WriteFrame.Object","moonbitlang/core/json/WriteFrame.Array","StringBuilder::write_object","*r","moonbitlang/core/json/JsonPath.Key","Show::output.build_path","*parent","String::contains_any","Show::output.*bind","*index","@moonbitlang/core/json.FromJson::from_json","json","moonbitlang/core/result/Result[Bool, moonbitlang/core/json/JsonDecodeError].Ok","@moonbitlang/core/json.decode_error","moonbitlang/core/result/Result[Int, moonbitlang/core/json/JsonDecodeError].Ok","Double::to_int","Array::mapi","*a","*Index","res","*Key","base","segment","f4ah6o/papyr/core/Diagnostic","@f4ah6o/papyr/core.path_join","field","expected","received","f4ah6o/papyr/core/PdfLayoutData","all_pages","pages","page","mode","page_index","target","text","image","table","shape","group","frame","diagnostics","@f4ah6o/papyr/core.missing_field","@f4ah6o/papyr/core.string_array_contains","seen_ids","@f4ah6o/papyr/core.invalid_value","@f4ah6o/papyr/core.validate_pdf_layout_node","node","@f4ah6o/papyr/core.index_path","@f4ah6o/papyr/core.pdf_layout_node_frame","@f4ah6o/papyr/core.validate_pdf_node_frame","@f4ah6o/papyr/core.validate_pdf_layout_nodes","@f4ah6o/papyr/core.pdf_layout_page_path","seen_page_ids","document","@f4ah6o/papyr/core.pdf_layout_pages_to_array","@f4ah6o/papyr/core.validate_pdf_layout_page","f4ah6o/papyr/core/PdfLayoutValidationResult","operator","actual","suffix","prefix","String::contains","@f4ah6o/papyr/core.string_starts_with","@f4ah6o/papyr/core.string_ends_with","data","binding","@f4ah6o/papyr/core.evaluate_pdf_condition","condition","@f4ah6o/papyr/core.evaluate_pdf_string_condition","@f4ah6o/papyr/core.lookup_pdf_text","field_key","@f4ah6o/papyr/core.evaluate_pdf_number_condition","@f4ah6o/papyr/core.lookup_pdf_number","@f4ah6o/papyr/core.evaluate_pdf_bool_condition","@f4ah6o/papyr/core.lookup_pdf_bool","@f4ah6o/papyr/core.evaluate_pdf_condition_group","headers","row","cell","collection_key","resolved_rows","@f4ah6o/papyr/core.lookup_pdf_data_list","placeholder_row","columns","@f4ah6o/papyr/core.missing_pdf_binding_text","@f4ah6o/papyr/core.pdf_data_table_binding_key","list","resolved_row","@f4ah6o/papyr/core.lookup_pdf_row_text","@f4ah6o/papyr/core.lookup_pdf_image","@f4ah6o/papyr/core.resolve_pdf_text_source","resolved","@f4ah6o/papyr/core.resolve_pdf_layout_node","@f4ah6o/papyr/core.pdf_node_is_visible","f4ah6o/papyr/core/PdfResolvedNode","@f4ah6o/papyr/core.pdf_layout_node_type","@f4ah6o/papyr/core.resolve_pdf_layout_node_content","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedText","source","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedImage","@f4ah6o/papyr/core.resolve_pdf_image_source","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedStaticTable","@f4ah6o/papyr/core.resolve_pdf_table_headers","@f4ah6o/papyr/core.resolve_pdf_static_table_rows","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedDataTable","@f4ah6o/papyr/core.resolve_pdf_data_table_headers","@f4ah6o/papyr/core.resolve_pdf_data_table_rows","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedShape","f4ah6o/papyr/core/PdfResolvedNodeContent.PdfResolvedGroup","@f4ah6o/papyr/core.resolve_pdf_layout_nodes","validation","@f4ah6o/papyr/core.validate_pdf_layout_document","f4ah6o/papyr/core/PdfLayoutResolveResult","@f4ah6o/papyr/core.pdf_layout_resolve_mode_name","f4ah6o/papyr/core/PdfResolvedPage","message","f4ah6o/papyr/core/DocumentStackToolEnvelope","tool","@f4ah6o/papyr/core.document_stack_failure","has_link","moonbitlang/core/builtin/MutLocal[Bool]","run","mark","@f4ah6o/papyr/core.validate_inline_run","@f4ah6o/papyr/core.validate_block","block","@f4ah6o/papyr/core.validate_inline_runs","content","@f4ah6o/papyr/core.validate_list_item","item","@f4ah6o/papyr/core.validate_blocks","doc","f4ah6o/papyr/core/PapyrDocumentEnvelope","envelope","@f4ah6o/papyr/core.validate_papyr_document","@f4ah6o/papyr/core.document_stack_success","sb","previous_space","String::trim","@f4ah6o/papyr/core.collapse_whitespace","separator","part","@f4ah6o/papyr/core.document_inline_text","parts","child_parts","@f4ah6o/papyr/core.document_block_text","child","@f4ah6o/papyr/core.join_with","caption","visits","index_path","@f4ah6o/papyr/core.append_index","base_path","f4ah6o/papyr/core/DocumentBlockVisit","parent_list_item","item_path","item_index","@f4ah6o/papyr/core.visit_blocks","visit","headings","@f4ah6o/papyr/core.visit_document_blocks","f4ah6o/papyr/core/DocumentHeading","id","normalized","title","@f4ah6o/papyr/core.collect_document_headings","heading","moonbitlang/core/builtin/MutLocal[String]","@f4ah6o/papyr/core.html_escape","href","tag","@f4ah6o/papyr/core.render_inline_html","ordered","@f4ah6o/papyr/core.render_block_html","class_attr","language","f4ah6o/papyr/core/DocumentPreviewResult","@f4ah6o/papyr/core.document_title","@f4ah6o/papyr/core.document_text","@f4ah6o/papyr/core.render_document_html","query","score","String::to_lower","body","first","fallback","@f4ah6o/papyr/core.first_non_empty","limit","@f4ah6o/papyr/core.document_stack_error.inner","hits","normalized_query","diagnostic","@f4ah6o/papyr/core.search_score","f4ah6o/papyr/core/DocumentSearchHit","@f4ah6o/papyr/core.search_snippet","limited","hit","f4ah6o/papyr/core/DocumentSearchResult","f4ah6o/papyr/core/DocumentWorkspaceExport","@f4ah6o/papyr/core.document_stack_schema_version","generated_at","documents","workspace","@f4ah6o/papyr/core.document_stack_export_workspace","publication_id","f4ah6o/papyr/core/DocumentPublicationExport","blocks","*Heading","*content","slides","current","moonbitlang/core/builtin/MutLocal[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/Block]]","@f4ah6o/papyr/core.is_slide_boundary","slide_blocks","@f4ah6o/papyr/core.split_document_into_slides","slide_id","slide_document","f4ah6o/papyr/core/PapyrDocument","@f4ah6o/papyr/core.resolve_slide_title","f4ah6o/papyr/core/DocumentSlideArtifact","markdown_mirrors","mirror","@f4ah6o/papyr/core.validate_documents_for_tool","mirror_diagnostics","@f4ah6o/papyr/core.validate_markdown_mirrors","preview_html","f4ah6o/papyr/core/DocumentPreviewHtml","@f4ah6o/papyr/core.build_document_slides","slide","f4ah6o/papyr/core/PapyrBundleExport","@f4ah6o/papyr/core.papyr_bundle_artifact_kind","@moonbitlang/core/json.from_json","@f4ah6o/papyr/core.expected_type","@moonbitlang/core/json.parse.inner","@f4ah6o/papyr/core.validate_papyr_document_json","@f4ah6o/papyr/core.parse_error","changed","@f4ah6o/papyr/core.block_id","target_id","replacement","@f4ah6o/papyr/core.replace_list_items_by_id","items","items_changed","f4ah6o/papyr/core/Block.List","next_items","@f4ah6o/papyr/core.replace_blocks_by_id","blocks_changed","f4ah6o/papyr/core/ListItem","block_id","@f4ah6o/papyr/core.insert_list_items_after_id","insert","@f4ah6o/papyr/core.insert_block_after_id","@f4ah6o/papyr/core.remove_list_items_by_id","@f4ah6o/papyr/core.remove_block_by_id","Map::new","f4ah6o/papyr/core/AuthoringDiagnostic","hint","@f4ah6o/papyr/core.empty_authoring_context","f4ah6o/papyr/core/AuthoringToolEnvelope","@f4ah6o/papyr/core.authoring_diagnostic","moonbitlang/core/option/Option[String?].None","context","@f4ah6o/papyr/core.document_validation_diagnostics","f4ah6o/papyr/core/LastActionState","name","at","status","summary","f4ah6o/papyr/core/WorkspaceSummary","document_count","summaries","found_current","snapshot","@f4ah6o/papyr/core.workspace_summary","reasons","f4ah6o/papyr/core/PublishState","f4ah6o/papyr/core/AuthoringSessionSnapshot","publications","selection","preview","search","last_action","with_publish","@f4ah6o/papyr/core.recompute_publish_state","@f4ah6o/papyr/core.refresh_workspace_summaries","document_id","f4ah6o/papyr/core/DocumentsReadEnvelope","@f4ah6o/papyr/core.find_document","@f4ah6o/papyr/core.authoring_diagnostic.inner","f4ah6o/papyr/core/DocumentReadEnvelope","@f4ah6o/papyr/core.validate_optional_document_payload","validation_diagnostics","@f4ah6o/papyr/core.rebuild_snapshot","moonbitlang/core/option/Option[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDocumentRecord]].None","moonbitlang/core/option/Option[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringPublicationRecord]].None","moonbitlang/core/option/Option[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDiagnostic]].Some","moonbitlang/core/option/Option[f4ah6o/papyr/core/LastActionState?].None","existing","f4ah6o/papyr/core/AuthoringDocumentRecord","kind","validated_document","moonbitlang/core/option/Option[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDocumentRecord]].Some","f4ah6o/papyr/core/AuthoringSelectionState","moonbitlang/core/option/Option[moonbitlang/core/builtin/Array[f4ah6o/papyr/core/AuthoringDiagnostic]].None","moonbitlang/core/option/Option[f4ah6o/papyr/core/LastActionState?].Some","@f4ah6o/papyr/core.last_action","found","moonbitlang/core/builtin/MutLocal[f4ah6o/papyr/core/PapyrDocument?]","clear_document","validated","*validated","*validation_diagnostics","previous_dash","String::has_suffix","@f4ah6o/papyr/markdown.normalize_column_key","header","root","Array::contains","used","@f4ah6o/papyr/markdown.unique_column_key","align","lines","@f4ah6o/papyr/markdown.join_table_cells","@f4ah6o/papyr/markdown.align_marker","@f4ah6o/papyr/markdown.join_lines","@f4ah6o/papyr/markdown.run_to_markdown","@f4ah6o/papyr/markdown.repeat_hash","@f4ah6o/papyr/markdown.inline_text","@f4ah6o/papyr/markdown.list_to_markdown","lang","@f4ah6o/papyr/markdown.can_serialize_gfm_table","rows","@f4ah6o/papyr/markdown.gfm_table_to_markdown","Json::stringify.inner","f4ah6o/papyr/markdown/TableMarkdownPayload","f4ah6o/papyr/markdown/ExcalidrawMarkdownPayload","elements","app_state","files","svg","*Paragraph","@f4ah6o/papyr/markdown.block_to_markdown","marker","@f4ah6o/papyr/markdown.join_blocks","@f4ah6o/papyr/core.parse_papyr_document_json","*doc","moonbitlang/core/result/Result[f4ah6o/papyr/core/PapyrDocument, String].Ok","moonbitlang/core/result/Result[f4ah6o/papyr/core/PapyrDocument, String].Err","trimmed","String::has_prefix","opener","StringView::trim","body_lines","@f4ah6o/papyr/markdown.is_closing_fence","@f4ah6o/papyr/markdown.join_with_newline","tail","String::find","label","label_end","url_tail","url_end","f4ah6o/papyr/core/InlineRun","delimiter","inner","close","@f4ah6o/papyr/markdown.is_ascii_word_char","@f4ah6o/papyr/markdown.is_word_char_at","@f4ah6o/papyr/markdown.is_underscore_boundary","@f4ah6o/papyr/markdown.find_closing_underscore","@f4ah6o/papyr/markdown.consume_mark","@f4ah6o/papyr/markdown.consume_underscore_mark","@f4ah6o/papyr/markdown.consume_link","skipped","@f4ah6o/papyr/markdown.find_allowed_underscore","best_pos","moonbitlang/core/builtin/MutLocal[Int?]","best_marker","moonbitlang/core/builtin/MutLocal[f4ah6o/papyr/markdown/InlineMarker?]","candidates","@f4ah6o/papyr/markdown.find_inline_marker_position","*current","runs","@f4ah6o/papyr/markdown.next_inline_marker","@f4ah6o/papyr/markdown.consume_inline_marker","@f4ah6o/papyr/markdown.first_char","@f4ah6o/papyr/markdown.drop_first_char","next_rest","view","*pos","@f4ah6o/papyr/markdown.all_digits","consumed_ids","@f4ah6o/papyr/markdown.parse_list_item","@f4ah6o/papyr/markdown.ListKind::same_as","*item_kind","item_kind","*text","f4ah6o/papyr/core/Block.Paragraph","@f4ah6o/papyr/markdown.block_id","first_child_id","@f4ah6o/papyr/markdown.parse_inlines","cells","String::split","@f4ah6o/papyr/markdown.looks_like_table_row","@f4ah6o/papyr/markdown.split_table_row","@f4ah6o/papyr/markdown.looks_like_table_separator","@f4ah6o/papyr/markdown.is_blank","@f4ah6o/papyr/markdown.is_fence","@f4ah6o/papyr/markdown.is_table_start","@f4ah6o/papyr/markdown.parse_heading","@f4ah6o/papyr/markdown.join_with_space","left","right","aligns","f4ah6o/papyr/core/TableCell","f4ah6o/papyr/core/TableColumn","@f4ah6o/papyr/markdown.table_align","f4ah6o/papyr/core/Block.Table","payload","f4ah6o/papyr/core/Block.Excalidraw","f4ah6o/papyr/core/Block.Mermaid","f4ah6o/papyr/core/Block.Code","line_view","@f4ah6o/papyr/markdown.split_lines","next_id","next_i","@f4ah6o/papyr/markdown.consume_fence","*language","*body","*next_i","@f4ah6o/papyr/markdown.fence_block","@f4ah6o/papyr/markdown.consume_table","*table","f4ah6o/papyr/core/Block.Heading","@f4ah6o/papyr/markdown.consume_list","@f4ah6o/papyr/markdown.ListKind::is_ordered","@f4ah6o/papyr/markdown.consume_paragraph","paragraph","@f4ah6o/papyr/markdown.first_heading","@f4ah6o/papyr/markdown.document_to_markdown","@f4ah6o/papyr/markdown.parse_markdown.inner","document_bridge_diagnostic","f4ah6o/papyr/bridge/SerializeDocumentEnvelope","@f4ah6o/papyr/core.app_server_bridge_error","request","markdown","mirrors","f4ah6o/papyr/core/DocumentMarkdownMirror","document_stack_bridge_error","@f4ah6o/papyr/core.replace_document_block","@f4ah6o/papyr/core.insert_document_block_after","@f4ah6o/papyr/core.remove_document_block","@f4ah6o/papyr/core.resolve_pdf_layout_document","@f4ah6o/papyr/core.pdf_layout_empty_data","@f4ah6o/papyr/core.pdf_layout_resolve_mode_from_string","@f4ah6o/papyr/core.pdf_layout_resolve_error","document_bridge_error","@f4ah6o/papyr/markdown.document_from_json","serialize_bridge_error","tool_input_json","@f4ah6o/papyr/core.document_stack_validate_document","markdown_result","@f4ah6o/papyr/formatter.format_markdown","@f4ah6o/papyr/core.document_stack_preview_document.inner","@f4ah6o/papyr/core.document_stack_search_documents.inner","@f4ah6o/papyr/core.document_stack_export_publication","@f4ah6o/papyr/core.document_stack_export_papyr_bundle","@f4ah6o/papyr/core.app_server_get_session_snapshot","@f4ah6o/papyr/core.app_server_get_documents","@f4ah6o/papyr/core.app_server_get_document","@f4ah6o/papyr/core.app_server_create_document.inner","@f4ah6o/papyr/core.app_server_update_document.inner","authoring_bridge_error"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAg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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}