diff options
author | 2023-01-11 02:43:58 +0000 | |
---|---|---|
committer | 2023-01-10 18:43:58 -0800 | |
commit | f1e6ea22541fba2e7354b8440f6efe0f3292c546 (patch) | |
tree | 55c77187daec7d50809accb655987d4df4aabd3c /src/bun.js | |
parent | 56a6cf716e3c7c0613245ceb67492b9a2aaf4912 (diff) | |
download | bun-f1e6ea22541fba2e7354b8440f6efe0f3292c546.tar.gz bun-f1e6ea22541fba2e7354b8440f6efe0f3292c546.tar.zst bun-f1e6ea22541fba2e7354b8440f6efe0f3292c546.zip |
Implement Buffer swap16, swap32, swap64 (#1659)
* Implement Buffer swap16, swap32, swap64
* Initial incorporation of feedback
- Use constexpr
- Clean up the indexing
- Check for detached
- Use suggested text for exception text
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 623c67bcb..a89492359 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -1114,17 +1114,99 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_lastIndexOfBody(JSC: static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap16Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); - return JSC::JSValue::encode(jsUndefined()); + auto scope = DECLARE_THROW_SCOPE(vm); + + constexpr int elemSize = 2; + int64_t length = static_cast<int64_t>(castedThis->byteLength()); + if (length % elemSize != 0) { + throwRangeError(lexicalGlobalObject, scope, "Buffer size must be a multiple of 16-bits"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + if (UNLIKELY(castedThis->isDetached())) { + throwVMTypeError(lexicalGlobalObject, scope, "Buffer is detached"_s); + return JSValue::encode(jsUndefined()); + } + + uint8_t* typedVector = castedThis->typedVector(); + + for (size_t elem = 0; elem < length; elem += elemSize) { + const size_t right = elem + 1; + + uint8_t temp = typedVector[elem]; + typedVector[elem] = typedVector[right]; + typedVector[right] = temp; + } + + return JSC::JSValue::encode(castedThis); } static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap32Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); - return JSC::JSValue::encode(jsUndefined()); + auto scope = DECLARE_THROW_SCOPE(vm); + + constexpr int elemSize = 4; + int64_t length = static_cast<int64_t>(castedThis->byteLength()); + if (length % elemSize != 0) { + throwRangeError(lexicalGlobalObject, scope, "Buffer size must be a multiple of 32-bits"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + if (UNLIKELY(castedThis->isDetached())) { + throwVMTypeError(lexicalGlobalObject, scope, "Buffer is detached"_s); + return JSValue::encode(jsUndefined()); + } + + uint8_t* typedVector = castedThis->typedVector(); + + constexpr size_t swaps = elemSize/2; + for (size_t elem = 0; elem < length; elem += elemSize) { + const size_t right = elem + elemSize - 1; + for (size_t k = 0; k < swaps; k++) { + const size_t i = right - k; + const size_t j = elem + k; + + uint8_t temp = typedVector[i]; + typedVector[i] = typedVector[j]; + typedVector[j] = temp; + } + } + + return JSC::JSValue::encode(castedThis); } static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap64Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); - return JSC::JSValue::encode(jsUndefined()); + auto scope = DECLARE_THROW_SCOPE(vm); + + constexpr size_t elemSize = 8; + int64_t length = static_cast<int64_t>(castedThis->byteLength()); + if (length % elemSize != 0) { + throwRangeError(lexicalGlobalObject, scope, "Buffer size must be a multiple of 64-bits"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + if (UNLIKELY(castedThis->isDetached())) { + throwVMTypeError(lexicalGlobalObject, scope, "Buffer is detached"_s); + return JSValue::encode(jsUndefined()); + } + + uint8_t* typedVector = castedThis->typedVector(); + + constexpr size_t swaps = elemSize/2; + for (size_t elem = 0; elem < length; elem += elemSize) { + const size_t right = elem + elemSize - 1; + for (size_t k = 0; k < swaps; k++) { + const size_t i = right - k; + const size_t j = elem + k; + + uint8_t temp = typedVector[i]; + typedVector[i] = typedVector[j]; + typedVector[j] = temp; + } + } + + return JSC::JSValue::encode(castedThis); } static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis) |