@@ -7,9 +7,11 @@ export type i31ref = ref_i31 | null;
77export type structref = ref_struct | null ;
88export type arrayref = ref_array | null ;
99export type stringref = ref_string | null ;
10- export type stringview_wtf8 = ref_stringview_wtf8 | null ;
11- export type stringview_wtf16 = ref_stringview_wtf16 | null ;
12- export type stringview_iter = ref_stringview_iter | null ;
10+
11+ // TODO: Conflict with the instruction namespaces
12+ // export type stringview_wtf8 = ref_stringview_wtf8 | null;
13+ // export type stringview_wtf16 = ref_stringview_wtf16 | null;
14+ // export type stringview_iter = ref_stringview_iter | null;
1315
1416@unmanaged
1517abstract class Ref {
@@ -43,6 +45,142 @@ export abstract class RefStruct extends Ref {
4345export abstract class RefArray extends Ref {
4446}
4547
48+ import { E_INDEXOUTOFRANGE } from "util/error" ;
49+
4650@final @unmanaged
4751export abstract class RefString extends Ref {
52+
53+ @lazy static readonly MAX_LENGTH : i32 = ( 1 << 30 ) - 1 ;
54+
55+ static fromCharCode ( unit : i32 , surr : i32 = - 1 ) : ref_string {
56+ if ( ~ surr ) unit = 0x10000 + ( ( unit & 0x3FF ) << 10 ) | ( surr & 0x3FF ) ;
57+ return string . from_code_point ( unit ) ;
58+ }
59+
60+ static fromCodePoint ( cp : i32 ) : ref_string {
61+ if ( < u32 > cp > 0x10ffff ) throw new Error ( "Invalid code point" ) ;
62+ return string . from_code_point ( cp ) ;
63+ }
64+
65+ // @ts -ignore: this on getter
66+ get length ( this : ref_string ) : i32 {
67+ return string . measure_wtf16 ( this ) ;
68+ }
69+
70+ at ( this : ref_string , pos : i32 ) : stringref {
71+ let len = string . measure_wtf16 ( this ) ;
72+ pos += select ( 0 , len , pos >= 0 ) ;
73+ if ( < u32 > pos >= < u32 > len ) throw new RangeError ( E_INDEXOUTOFRANGE ) ;
74+ return string . from_code_point ( stringview_wtf16 . get_codeunit ( string . as_wtf16 ( this ) , pos ) ) ;
75+ }
76+
77+ @operator ( "[]" ) charAt ( this : ref_string , pos : i32 ) : stringref {
78+ if ( < u32 > pos >= < u32 > string . measure_wtf16 ( this ) ) return "" ;
79+ return string . from_code_point ( stringview_wtf16 . get_codeunit ( string . as_wtf16 ( this ) , pos ) ) ;
80+ }
81+
82+ charCodeAt ( this : ref_string , pos : i32 ) : i32 {
83+ if ( < u32 > pos >= < u32 > string . measure_wtf16 ( this ) ) return - 1 ; // (NaN)
84+ return stringview_wtf16 . get_codeunit ( string . as_wtf16 ( this ) , pos ) ;
85+ }
86+
87+ codePointAt ( this : ref_string , pos : i32 ) : i32 {
88+ let len = string . measure_wtf16 ( this ) ;
89+ if ( < u32 > pos >= < u32 > len ) return - 1 ; // (undefined)
90+ let view = string . as_wtf16 ( this ) ;
91+ let first = < i32 > stringview_wtf16 . get_codeunit ( view , pos ) ;
92+ if ( ( first & 0xFC00 ) != 0xD800 || pos + 1 == len ) return first ;
93+ let second = < i32 > stringview_wtf16 . get_codeunit ( view , pos + 1 ) ;
94+ if ( ( second & 0xFC00 ) != 0xDC00 ) return first ;
95+ return ( first - 0xD800 << 10 ) + ( second - 0xDC00 ) + 0x10000 ;
96+ }
97+
98+ @operator ( "+" )
99+ concat ( this : ref_string , other : ref_string ) : ref_string {
100+ return string . concat ( this , other ) ;
101+ }
102+
103+ endsWith ( this : ref_string , search : ref_string , end : i32 = RefString . MAX_LENGTH ) : bool {
104+ end = min ( max ( end , 0 ) , string . measure_wtf16 ( this ) ) ;
105+ let searchLength = string . measure_wtf16 ( search ) ;
106+ let searchStart = end - searchLength ;
107+ if ( searchStart < 0 ) return false ;
108+ return string . eq (
109+ stringview_wtf16 . slice ( string . as_wtf16 ( this ) , searchStart , searchStart + searchLength ) ,
110+ search
111+ ) ;
112+ }
113+
114+ @operator ( "==" ) private static __eq ( left : ref_string | null , right : ref_string | null ) : bool {
115+ return string . eq ( left , right ) ;
116+ }
117+
118+ @operator . prefix ( "!" )
119+ private static __not ( str : ref_string | null ) : bool {
120+ return str == null ;
121+ }
122+
123+ @operator ( "!=" )
124+ private static __ne ( left : ref_string | null , right : ref_string | null ) : bool {
125+ return ! string . eq ( left , right ) ;
126+ }
127+
128+ @operator ( ">" ) private static __gt ( left : ref_string , right : ref_string ) : bool {
129+ return string . compare ( left , right ) > 0 ;
130+ }
131+
132+ @operator ( ">=" ) private static __gte ( left : ref_string , right : ref_string ) : bool {
133+ return string . compare ( left , right ) >= 0 ;
134+ }
135+
136+ @operator ( "<" ) private static __lt ( left : ref_string , right : ref_string ) : bool {
137+ return string . compare ( left , right ) < 0 ;
138+ }
139+
140+ @operator ( "<=" ) private static __lte ( left : ref_string , right : ref_string ) : bool {
141+ return string . compare ( left , right ) <= 0 ;
142+ }
143+
144+ includes ( this : ref_string , search : ref_string , start : i32 = 0 ) : bool {
145+ return this . indexOf ( search , start ) != - 1 ;
146+ }
147+
148+ indexOf ( this : ref_string , search : ref_string , start : i32 = 0 ) : i32 {
149+ let searchLen = string . measure_wtf16 ( search ) ;
150+ if ( ! searchLen ) return 0 ;
151+ let len = string . measure_wtf16 ( this ) ;
152+ if ( ! len ) return - 1 ;
153+ let searchStart = min ( max ( start , 0 ) , len ) ;
154+ let view = string . as_wtf16 ( this ) ;
155+ for ( len -= searchLen ; searchStart <= len ; ++ searchStart ) {
156+ // FIXME: slice is suboptimal
157+ if ( string . eq (
158+ stringview_wtf16 . slice ( view , searchStart , searchStart + searchLen ) ,
159+ search
160+ ) ) {
161+ return searchStart ;
162+ }
163+ }
164+ return - 1 ;
165+ }
166+
167+ lastIndexOf ( this : ref_string , search : ref_string , start : i32 = i32 . MAX_VALUE ) : i32 {
168+ let searchLen = string . measure_wtf16 ( search ) ;
169+ if ( ! searchLen ) return string . measure_wtf16 ( this ) ;
170+ let len = string . measure_wtf16 ( this ) ;
171+ if ( ! len ) return - 1 ;
172+ let searchStart = min ( max ( start , 0 ) , len - searchLen ) ;
173+ for ( ; searchStart >= 0 ; -- searchStart ) {
174+ // FIXME: slice is suboptimal
175+ if ( string . eq (
176+ stringview_wtf16 . slice ( string . as_wtf16 ( this ) , searchStart , searchStart + searchLen ) ,
177+ search
178+ ) ) {
179+ return searchStart ;
180+ }
181+ }
182+ return - 1 ;
183+ }
184+
185+ // TODO: port more
48186}
0 commit comments