Backed out 2 changesets (bug 1816628) for causing OS X mochitests-plain failures...
[gecko.git] / netwerk / base / ArrayBufferInputStream.cpp
blobb8c26d03ef84564000d818df47c1b3b197d9a086
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include <algorithm>
7 #include "ArrayBufferInputStream.h"
8 #include "nsStreamUtils.h"
9 #include "js/ArrayBuffer.h" // JS::{GetArrayBuffer{ByteLength,Data},IsArrayBufferObject}
10 #include "js/RootingAPI.h" // JS::{Handle,Rooted}
11 #include "js/Value.h" // JS::Value
12 #include "mozilla/Span.h"
13 #include "mozilla/UniquePtrExtensions.h"
14 #include "mozilla/dom/ScriptSettings.h"
16 using mozilla::dom::RootingCx;
18 NS_IMPL_ISUPPORTS(ArrayBufferInputStream, nsIArrayBufferInputStream,
19 nsIInputStream);
21 NS_IMETHODIMP
22 ArrayBufferInputStream::SetDataFromJS(JS::Handle<JS::Value> aBuffer,
23 uint64_t aByteOffset, uint64_t aLength) {
24 NS_ASSERT_OWNINGTHREAD(ArrayBufferInputStream);
26 if (!aBuffer.isObject()) {
27 return NS_ERROR_FAILURE;
29 JS::Rooted<JSObject*> arrayBuffer(RootingCx(), &aBuffer.toObject());
30 if (!JS::IsArrayBufferObject(arrayBuffer)) {
31 return NS_ERROR_FAILURE;
34 uint64_t buflen = JS::GetArrayBufferByteLength(arrayBuffer);
35 uint64_t offset = std::min(buflen, aByteOffset);
36 uint64_t bufferLength = std::min(buflen - offset, aLength);
38 // Prevent truncation.
39 if (bufferLength > UINT32_MAX) {
40 return NS_ERROR_INVALID_ARG;
43 mArrayBuffer = mozilla::MakeUniqueFallible<uint8_t[]>(bufferLength);
44 if (!mArrayBuffer) {
45 return NS_ERROR_OUT_OF_MEMORY;
48 mBufferLength = bufferLength;
50 JS::AutoCheckCannotGC nogc;
51 bool isShared;
52 uint8_t* src = JS::GetArrayBufferData(arrayBuffer, &isShared, nogc) + offset;
53 memcpy(&mArrayBuffer[0], src, mBufferLength);
54 return NS_OK;
57 nsresult ArrayBufferInputStream::SetData(mozilla::UniquePtr<uint8_t[]> aBytes,
58 uint64_t aByteLen) {
59 mArrayBuffer = std::move(aBytes);
60 mBufferLength = aByteLen;
61 return NS_OK;
64 NS_IMETHODIMP
65 ArrayBufferInputStream::Close() {
66 mClosed = true;
67 return NS_OK;
70 NS_IMETHODIMP
71 ArrayBufferInputStream::Available(uint64_t* aCount) {
72 if (mClosed) {
73 return NS_BASE_STREAM_CLOSED;
75 if (mArrayBuffer) {
76 *aCount = mBufferLength ? mBufferLength - mPos : 0;
77 } else {
78 *aCount = 0;
80 return NS_OK;
83 NS_IMETHODIMP
84 ArrayBufferInputStream::StreamStatus() {
85 return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
88 NS_IMETHODIMP
89 ArrayBufferInputStream::Read(char* aBuf, uint32_t aCount,
90 uint32_t* aReadCount) {
91 return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount);
94 NS_IMETHODIMP
95 ArrayBufferInputStream::ReadSegments(nsWriteSegmentFun writer, void* closure,
96 uint32_t aCount, uint32_t* result) {
97 NS_ASSERTION(result, "null ptr");
98 NS_ASSERTION(mBufferLength >= mPos, "bad stream state");
100 if (mClosed) {
101 return NS_BASE_STREAM_CLOSED;
104 MOZ_ASSERT(mArrayBuffer || (mPos == mBufferLength),
105 "stream inited incorrectly");
107 *result = 0;
108 while (mPos < mBufferLength) {
109 uint32_t remaining = mBufferLength - mPos;
110 MOZ_ASSERT(mArrayBuffer);
112 uint32_t count = std::min(aCount, remaining);
113 if (count == 0) {
114 break;
117 uint32_t written;
118 nsresult rv = writer(this, closure, (char*)&mArrayBuffer[0] + mPos, *result,
119 count, &written);
120 if (NS_FAILED(rv)) {
121 // InputStreams do not propagate errors to caller.
122 return NS_OK;
125 NS_ASSERTION(written <= count,
126 "writer should not write more than we asked it to write");
127 mPos += written;
128 *result += written;
129 aCount -= written;
132 return NS_OK;
135 NS_IMETHODIMP
136 ArrayBufferInputStream::IsNonBlocking(bool* aNonBlocking) {
137 *aNonBlocking = true;
138 return NS_OK;