summaryrefslogtreecommitdiffstats
path: root/toolkit/components/uniffi-js/OwnedRustBuffer.cpp
blob: 96d9dc1fd7b4028c329c9a025e8689232f6f2c37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsString.h"
#include "mozilla/dom/OwnedRustBuffer.h"

namespace mozilla::uniffi {

using dom::ArrayBuffer;

OwnedRustBuffer::OwnedRustBuffer(const RustBuffer& aBuf) {
  mBuf = aBuf;
  MOZ_ASSERT(IsValid());
}

Result<OwnedRustBuffer, nsCString> OwnedRustBuffer::FromArrayBuffer(
    const ArrayBuffer& aArrayBuffer) {
  if (aArrayBuffer.Length() > INT32_MAX) {
    return Err("Input ArrayBuffer is too large"_ns);
  }

  RustCallStatus status{};
  RustBuffer buf = uniffi_rustbuffer_alloc(
      static_cast<int32_t>(aArrayBuffer.Length()), &status);
  buf.len = aArrayBuffer.Length();
  if (status.code != 0) {
    if (status.error_buf.data) {
      auto message = nsCString("uniffi_rustbuffer_alloc: ");
      message.Append(
          nsDependentCSubstring(reinterpret_cast<char*>(status.error_buf.data),
                                status.error_buf.len));
      RustCallStatus status2{};
      uniffi_rustbuffer_free(status.error_buf, &status2);
      MOZ_RELEASE_ASSERT(status2.code == 0,
                         "Freeing a rustbuffer should never fail");
      return Err(message);

    } else {
      return Err("Unknown error allocating rust buffer"_ns);
    }
  }

  memcpy(buf.data, aArrayBuffer.Data(), buf.len);
  return OwnedRustBuffer(buf);
}

OwnedRustBuffer::OwnedRustBuffer(OwnedRustBuffer&& aOther) : mBuf(aOther.mBuf) {
  aOther.mBuf = RustBuffer{0};
}

OwnedRustBuffer& OwnedRustBuffer::operator=(OwnedRustBuffer&& aOther) {
  if (&aOther != this) {
    FreeData();
  }
  mBuf = aOther.mBuf;
  aOther.mBuf = RustBuffer{0};
  return *this;
}

void OwnedRustBuffer::FreeData() {
  if (IsValid()) {
    RustCallStatus status{};
    uniffi_rustbuffer_free(mBuf, &status);
    MOZ_RELEASE_ASSERT(status.code == 0,
                       "Freeing a rustbuffer should never fail");
    mBuf = {0};
  }
}

OwnedRustBuffer::~OwnedRustBuffer() { FreeData(); }

RustBuffer OwnedRustBuffer::IntoRustBuffer() {
  RustBuffer rv = mBuf;
  mBuf = {};
  return rv;
}

JSObject* OwnedRustBuffer::IntoArrayBuffer(JSContext* cx) {
  int32_t len = mBuf.len;
  void* data = mBuf.data;
  auto userData = MakeUnique<OwnedRustBuffer>(std::move(*this));
  return JS::NewExternalArrayBuffer(cx, len, data, &ArrayBufferFreeFunc,
                                    userData.release());
}

void OwnedRustBuffer::ArrayBufferFreeFunc(void* contents, void* userData) {
  UniquePtr<OwnedRustBuffer> buf{reinterpret_cast<OwnedRustBuffer*>(userData)};
}
}  // namespace mozilla::uniffi