@@ -7,9 +7,11 @@ export type i31ref = ref_i31 | null;
7
7
export type structref = ref_struct | null ;
8
8
export type arrayref = ref_array | null ;
9
9
export 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;
13
15
14
16
@unmanaged
15
17
abstract class Ref {
@@ -43,6 +45,142 @@ export abstract class RefStruct extends Ref {
43
45
export abstract class RefArray extends Ref {
44
46
}
45
47
48
+ import { E_INDEXOUTOFRANGE } from "util/error" ;
49
+
46
50
@final @unmanaged
47
51
export 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
48
186
}
0 commit comments