react-native-ultra-base64 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,147 @@
1
+ //
2
+ // react-native-ultra-base64.cpp
3
+ // react-native-ultra-base64
4
+ //
5
+ // Created by Oleksandr Shumihin on 7/2/26.
6
+ //
7
+
8
+ #include "react-native-ultra-base64.h"
9
+ #include "simdutf.h"
10
+ #include <algorithm>
11
+ #include <cstdint>
12
+ #include <cstring>
13
+ #include <memory>
14
+ #include <stdexcept>
15
+ #include <string>
16
+ #include <vector>
17
+
18
+ using namespace facebook;
19
+
20
+ class DecodedRawBuffer final : public jsi::MutableBuffer {
21
+ public:
22
+ explicit DecodedRawBuffer(const size_t capacity)
23
+ : data_(std::make_unique<uint8_t[]>(capacity)), size_(capacity) {}
24
+
25
+ size_t size() const override { return size_; }
26
+
27
+ uint8_t *data() override { return data_.get(); }
28
+
29
+ void resize(const size_t size) { size_ = size; }
30
+
31
+ private:
32
+ std::unique_ptr<uint8_t[]> data_;
33
+ size_t size_;
34
+ };
35
+
36
+ void rnub_base64::install(facebook::jsi::Runtime *runtime) {
37
+
38
+ jsi::Runtime &rt = *runtime;
39
+
40
+ auto decodeNameId =
41
+ jsi::PropNameID::forAscii(rt, "decodeBase64ToArrayBuffer");
42
+ auto encodeNameId =
43
+ jsi::PropNameID::forAscii(rt, "encodeBase64FromArrayBuffer");
44
+
45
+ auto decode = jsi::Function::createFromHostFunction(
46
+ rt, decodeNameId, 2,
47
+ [](jsi::Runtime &runtime, const jsi::Value &, const jsi::Value *arguments,
48
+ size_t count) -> jsi::Value {
49
+ try {
50
+ jsi::String b64 = arguments[0].asString(runtime);
51
+ bool removeLinebreaks = arguments[1].asBool();
52
+
53
+ const char *buffer = nullptr;
54
+ size_t size = 0;
55
+
56
+ auto cb = [&buffer, &size](const bool ascii, const void *const data,
57
+ const size_t num) {
58
+ if (!ascii) [[unlikely]] {
59
+ throw std::invalid_argument("Input must be ASCII base64 string");
60
+ }
61
+ buffer = static_cast<const char *>(data);
62
+ size = num;
63
+ };
64
+
65
+ b64.getStringData(runtime, cb);
66
+
67
+ std::string_view input{buffer, size};
68
+
69
+ const bool hasNewline = std::memchr(buffer, '\n', size) != nullptr;
70
+ std::string cleaned;
71
+
72
+ if (removeLinebreaks && hasNewline) {
73
+ cleaned.reserve(size);
74
+
75
+ for (size_t i = 0; i < size; ++i) {
76
+ const char c = buffer[i];
77
+ if (c != '\n') {
78
+ cleaned.push_back(c);
79
+ }
80
+ }
81
+
82
+ input = std::string_view{cleaned.data(), cleaned.size()};
83
+ } else if (hasNewline) [[unlikely]] {
84
+ throw std::runtime_error("Input is not valid base64-encoded data");
85
+ }
86
+
87
+ const char *const inputData = input.data();
88
+ size_t inputSize = input.size();
89
+
90
+ const size_t maxLen =
91
+ simdutf::maximal_binary_length_from_base64(inputData, inputSize);
92
+
93
+ auto result = std::make_shared<DecodedRawBuffer>(maxLen);
94
+
95
+ size_t outLen = maxLen;
96
+
97
+ const auto r = simdutf::base64_to_binary_safe(
98
+ inputData, inputSize, reinterpret_cast<char *>(result->data()),
99
+ outLen, simdutf::base64_default_or_url,
100
+ simdutf::last_chunk_handling_options::loose, false);
101
+
102
+ if (r.error != simdutf::error_code::SUCCESS) [[unlikely]] {
103
+ throw std::runtime_error("Input is not valid base64-encoded data");
104
+ }
105
+
106
+ result->resize(outLen);
107
+
108
+ return jsi::ArrayBuffer(runtime, std::move(result));
109
+ } catch (const std::exception &e) {
110
+ throw jsi::JSError(runtime, e.what());
111
+ } catch (...) {
112
+ throw jsi::JSError(runtime, "unknown decoding error");
113
+ }
114
+ });
115
+
116
+ auto encode = jsi::Function::createFromHostFunction(
117
+ rt, encodeNameId, 2,
118
+ [](jsi::Runtime &runtime, const jsi::Value &, const jsi::Value *arguments,
119
+ size_t count) -> jsi::Value {
120
+ try {
121
+ jsi::Object buf = arguments[0].asObject(runtime);
122
+ bool urlSafe = arguments[1].asBool();
123
+
124
+ auto arrayBuffer = buf.getArrayBuffer(runtime);
125
+ const size_t inLen = arrayBuffer.size(runtime);
126
+ const auto *input =
127
+ reinterpret_cast<const char *>(arrayBuffer.data(runtime));
128
+
129
+ const auto opts = static_cast<simdutf::base64_options>(
130
+ static_cast<uint64_t>(urlSafe));
131
+
132
+ std::string encoded(simdutf::base64_length_from_binary(inLen, opts),
133
+ '\0');
134
+
135
+ simdutf::binary_to_base64(input, inLen, encoded.data(), opts);
136
+ return jsi::String::createFromAscii(runtime, encoded.data(),
137
+ encoded.size());
138
+ } catch (const std::runtime_error &e) {
139
+ throw jsi::JSError(runtime, e.what());
140
+ } catch (...) {
141
+ throw jsi::JSError(runtime, "unknown encoding error");
142
+ }
143
+ });
144
+
145
+ rt.global().setProperty(rt, decodeNameId, std::move(decode));
146
+ rt.global().setProperty(rt, encodeNameId, std::move(encode));
147
+ }
@@ -0,0 +1,13 @@
1
+ //
2
+ // react-native-ultra-base64.hpp
3
+ // react-native-ultra-base64
4
+ //
5
+ // Created by Oleksandr Shumihin on 7/2/26.
6
+ //
7
+ #pragma once
8
+
9
+ #include <jsi/jsi.h>
10
+
11
+ namespace rnub_base64 {
12
+ void install(facebook::jsi::Runtime* rt);
13
+ }