| 195 | } |
| 196 | |
| 197 | GJS_JSAPI_RETURN_CONVENTION |
| 198 | static JSString* gjs_decode_from_uint8array_slow(JSContext* cx, |
| 199 | const uint8_t* input, |
| 200 | size_t input_len, |
| 201 | const char* encoding, |
| 202 | bool fatal) { |
| 203 | // If the decoding is not fatal we use the lossy decoder. |
| 204 | if (!fatal) |
| 205 | return gjs_lossy_decode_from_uint8array_slow(cx, input, input_len, |
| 206 | encoding); |
| 207 | |
| 208 | // g_convert only handles up to SSIZE_MAX bytes, but we may have SIZE_MAX |
| 209 | if (G_UNLIKELY(input_len > SSIZE_MAX)) { |
| 210 | gjs_throw(cx, "Array too big to decode: %zu bytes", input_len); |
| 211 | return nullptr; |
| 212 | } |
| 213 | |
| 214 | size_t bytes_written, bytes_read; |
| 215 | Gjs::AutoError error; |
| 216 | |
| 217 | Gjs::AutoChar bytes{g_convert(reinterpret_cast<const char*>(input), |
| 218 | input_len, UTF16_CODESET, encoding, |
| 219 | &bytes_read, &bytes_written, &error)}; |
| 220 | |
| 221 | if (error) |
| 222 | return gjs_throw_type_error_from_gerror(cx, error); |
| 223 | |
| 224 | // bytes_written should be bytes in a UTF-16 string so should be a |
| 225 | // multiple of 2 |
| 226 | g_assert((bytes_written % 2) == 0); |
| 227 | |
| 228 | // Cast g_convert's output to char16_t and copy the data. |
| 229 | const char16_t* unicode_bytes = reinterpret_cast<char16_t*>(bytes.get()); |
| 230 | return JS_NewUCStringCopyN(cx, unicode_bytes, bytes_written / 2); |
| 231 | } |
| 232 | |
| 233 | [[nodiscard]] |
| 234 | static bool is_utf8_label(const char* encoding) { |
no test coverage detected