From f95d75c9742bf57f907b5461b171ba36ea2425b5 Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Sun, 9 Jun 2024 22:55:25 +0200 Subject: [PATCH] Fix: don't return the trailing zero --- spec/compiler/macro/macro_methods_spec.cr | 4 ++-- src/compiler/crystal/macros/methods.cr | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 028b137dacb9..a41068be40d0 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -592,8 +592,8 @@ module Crystal end it "executes to_utf16" do - assert_macro %({{"hello".to_utf16}}), "::Slice(::UInt16).literal(104_u16, 101_u16, 108_u16, 108_u16, 111_u16, 0_u16)" - assert_macro %({{"TEST 😐🐙 ±∀ の".to_utf16}}), "::Slice(::UInt16).literal(84_u16, 69_u16, 83_u16, 84_u16, 32_u16, 55357_u16, 56848_u16, 55357_u16, 56345_u16, 32_u16, 177_u16, 8704_u16, 32_u16, 12398_u16, 0_u16)" + assert_macro %({{"hello".to_utf16}}), "(::Slice(::UInt16).literal(104_u16, 101_u16, 108_u16, 108_u16, 111_u16, 0_u16))[0, 5]" + assert_macro %({{"TEST 😐🐙 ±∀ の".to_utf16}}), "(::Slice(::UInt16).literal(84_u16, 69_u16, 83_u16, 84_u16, 32_u16, 55357_u16, 56848_u16, 55357_u16, 56345_u16, 32_u16, 177_u16, 8704_u16, 32_u16, 12398_u16, 0_u16))[0, 14]" end it "executes to_i" do diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index a9319074a743..2b6ac1c1d25b 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -823,12 +823,17 @@ module Crystal when "to_utf16" interpret_check_args do slice = @value.to_utf16 + # include the trailing zero that isn't counted in the slice but was # generated by String#to_utf16 so the literal can be passed to C # functions that expect a null terminated UInt16* - slice = Slice(UInt16).new(slice.to_unsafe, slice.size + 1) - args = slice.to_a { |codepoint| NumberLiteral.new(codepoint).as(ASTNode) } - Call.new(Generic.new(Path.global("Slice"), [Path.global("UInt16")] of ASTNode), "literal", args) + args = Slice(UInt16).new(slice.to_unsafe, slice.size + 1).to_a do |codepoint| + NumberLiteral.new(codepoint).as(ASTNode) + end + literal_node = Call.new(Generic.new(Path.global("Slice"), [Path.global("UInt16")] of ASTNode), "literal", args) + + # but keep the trailing zero hidden in the exposed slice + Call.new(literal_node, "[]", [NumberLiteral.new("0", :i32), NumberLiteral.new(slice.size)] of ASTNode) end when "tr" interpret_check_args do |first, second|