Skip to content
File

Blob: src/workerd/api/encoding-legacy.c++

2.2 KB
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#include "encoding-legacy.h"
6 
7#include <kj-rs/convert.h>
8#include <rust/cxx.h>
9 
10#include <kj/common.h>
11 
12namespace workerd::api {
13 
14namespace {
15 
16// Map workerd::api::Encoding to the Rust-side RustEncoding enum.
17::workerd::rust::encoding::Encoding toRustEncoding(Encoding encoding) {
18 using RE = ::workerd::rust::encoding::Encoding;
19 switch (encoding) {
20 case Encoding::Big5:
21 return RE::Big5;
22 case Encoding::Euc_Jp:
23 return RE::EucJp;
24 case Encoding::Euc_Kr:
25 return RE::EucKr;
26 case Encoding::Gb18030:
27 return RE::Gb18030;
28 case Encoding::Gbk:
29 return RE::Gbk;
30 case Encoding::Iso2022_Jp:
31 return RE::Iso2022Jp;
32 case Encoding::Shift_Jis:
33 return RE::ShiftJis;
34 case Encoding::Windows_1252:
35 return RE::Windows1252;
36 case Encoding::X_User_Defined:
37 return RE::XUserDefined;
38 default:
39 KJ_UNREACHABLE;
40 }
41}
42 
43} // namespace
44 
45LegacyDecoder::LegacyDecoder(Encoding encoding, DecoderFatal fatal)
46 : encoding(encoding),
47 fatal(fatal),
48 state(::workerd::rust::encoding::new_decoder(toRustEncoding(encoding))) {}
49 
50void LegacyDecoder::reset() {
51 ::workerd::rust::encoding::reset(*state);
52}
53 
54kj::Maybe<jsg::JsString> LegacyDecoder::decode(
55 jsg::Lock& js, kj::ArrayPtr<const kj::byte> buffer, bool flush) {
56 if (!flush && buffer.size() == 0) {
57 // Avoid encoding_rs empty-chunk streaming bug:
58 // https://github.com/hsivonen/encoding_rs/issues/126#issuecomment-3677642122
59 return js.str();
60 }
61 
62 ::workerd::rust::encoding::DecodeOptions options{.flush = flush, .fatal = fatal.toBool()};
63 // Decode into the Rust-side reusable buffer. The Rust decoder handles
64 // lazy reset internally when a previous call used flush=true.
65 auto result =
66 ::workerd::rust::encoding::decode(*state, buffer.as<kj_rs::RustMutable>(), kj::mv(options));
67 
68 if (fatal.toBool() && result.had_error) {
69 return kj::none;
70 }
71 
72 // Zero-copy view of the UTF-16 output slice from the Rust-owned buffer.
73 return js.str(kj::from<kj_rs::Rust>(result.output));
74}
75 
76} // namespace workerd::api