Bug 1851845 - Update vendored Application Services dependencies. r=markh,adw

This commit vendors the latest changes to the Suggest and Remote
Settings Rust components.

1. From the `application-services` source tree, I ran
   `./tools/update-moz-central-vendoring.py ../m-c` to update the
   revisions in the m-c source tree.
2. I added the Remote Settings component UDL file to
   `toolkit/components/uniffi-bindgen-gecko-js/mach_commands.py`, and
   updated `toolkit/components/uniffi-bindgen-gecko-js/config.toml` to
   call the `RemoteSettings` constructor on the main thread. The
   Suggest component uses the `RemoteSettingsConfig` type in its
   public API, so we must generate bindings for the Remote Settings
   component.
3. From the m-c source tree, I ran `./mach uniffi generate` to update
   the generated UniFFI bindings.

Differential Revision: https://phabricator.services.mozilla.com/D187559
This commit is contained in:
Lina Butler 2023-09-07 05:40:28 +00:00
parent 9e56d64a80
commit 1466383668
39 changed files with 3175 additions and 1393 deletions

View file

@ -70,9 +70,9 @@ git = "https://github.com/mozilla-spidermonkey/jsparagus"
rev = "64ba08e24749616de2344112f226d1ef4ba893ae"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a"]
[source."git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a"]
git = "https://github.com/mozilla/application-services"
rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a"
rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/audioipc?rev=0b51291d2483a17dce3e300c7784b369e02bee73"]

24
Cargo.lock generated
View file

@ -1530,7 +1530,7 @@ dependencies = [
[[package]]
name = "error-support"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"error-support-macros",
"lazy_static",
@ -1542,7 +1542,7 @@ dependencies = [
[[package]]
name = "error-support-macros"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"proc-macro2",
"quote",
@ -2762,7 +2762,7 @@ dependencies = [
[[package]]
name = "interrupt-support"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"lazy_static",
"parking_lot",
@ -3918,7 +3918,7 @@ dependencies = [
[[package]]
name = "nss_build_common"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
[[package]]
name = "nsstring"
@ -4578,7 +4578,7 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "remote_settings"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"parking_lot",
"serde",
@ -5095,7 +5095,7 @@ dependencies = [
[[package]]
name = "sql-support"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"ffi-support",
"interrupt-support",
@ -5275,7 +5275,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "suggest"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"anyhow",
"interrupt-support",
@ -5320,7 +5320,7 @@ dependencies = [
[[package]]
name = "sync-guid"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"base64 0.13.999",
"rand",
@ -5331,7 +5331,7 @@ dependencies = [
[[package]]
name = "sync15"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"anyhow",
"error-support",
@ -5363,7 +5363,7 @@ dependencies = [
[[package]]
name = "tabs"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"anyhow",
"error-support",
@ -6003,7 +6003,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "viaduct"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"ffi-support",
"log",
@ -6159,7 +6159,7 @@ dependencies = [
[[package]]
name = "webext-storage"
version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=25972c388a4cf3a6d8256504f3a09b711db2fc6a#25972c388a4cf3a6d8256504f3a09b711db2fc6a"
source = "git+https://github.com/mozilla/application-services?rev=1a59041d0c7d36ef1abc713a48304c5333e45a1a#1a59041d0c7d36ef1abc713a48304c5333e45a1a"
dependencies = [
"anyhow",
"error-support",

View file

@ -202,13 +202,13 @@ warp = { git = "https://github.com/glandium/warp", rev = "4af45fae95bc98b0eba1ef
malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" }
# application-services overrides to make updating them all simpler.
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
sql-support = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
suggest = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
sync15 = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
tabs = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
viaduct = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "25972c388a4cf3a6d8256504f3a09b711db2fc6a" }
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
sql-support = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
suggest = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
sync15 = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
tabs = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
viaduct = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "1a59041d0c7d36ef1abc713a48304c5333e45a1a" }
# ICU4X 1.2 with synstructure 0.13.x / syn 2.x. When updating to next version, this should be removed.
diplomat = { git = "https://github.com/rust-diplomat/diplomat", rev = "8d125999893fedfdf30595e97334c21ec4b18da9" }

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"c13413955e0ab4939e98e7c0a3eda6d3015734d4764ffa3bc794faf7c975193d","android/build.gradle":"fb6aa2191f1545a92dbcb27552d3da09c19df6612bfa9ae1b70c7d241c50f65b","android/src/main/AndroidManifest.xml":"4c8c9223ad43961108867cf0940b39253c5d4e11ec39c0839a2f137f43ed482a","android/src/test/java/org/mozilla/appservices/remotesettings/RemoteSettingsTest.kt":"d27a6d70cb40607f21c23453d5a53055815ae77c35e59231ee0279787e8932e0","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/client.rs":"a411e87b485dd3a66202d96c1ef195ba5bdc42fa12d91f9960a64bef2ee5da31","src/config.rs":"7bb678addfae3b4ed5f2892d32263e5b33cc05e5a12a250f664150e78211f94a","src/error.rs":"719a83fb653a8a9a63b26aea7e5fa5210f8a4633d560de92b2b55640715002b2","src/lib.rs":"1daf4dc8265919374b83958f2aa431d44974de44a3ccd926b04d3b0ec207a2cf","src/remote_settings.udl":"06428a5749b04d4f70d704ee561cf30c7f0ad074559b7de0960051a575010b71","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null}
{"files":{"Cargo.toml":"c74e3df90cd82fb4ee00dd38d7e39cd7a0142ad601b8b63ae214978a28fbe1ac","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/client.rs":"3d87162e6913a81cc6f5178a7ca791e262d0d029e7dedf3df4fe2f66e5501185","src/config.rs":"7bb678addfae3b4ed5f2892d32263e5b33cc05e5a12a250f664150e78211f94a","src/error.rs":"192ca42af7c6b882f3129378c23b45dab8a0d2b179e23a8813a335ffd56b21dc","src/lib.rs":"416e99894e152f6cea7418ad2fabfd94bc3d907efd9f33fbd2a83fb99452b2df","src/remote_settings.udl":"e38758592ca75adbebb8fe688b10520d9931a5f3292d94f229cba05310756a43","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null}

View file

@ -17,6 +17,7 @@ authors = [
"The Android Mobile Team <firefox-android-team@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
]
exclude = ["/android"]
description = "A Remote Settings client intended for application layer platforms."
license = "MPL-2.0"
@ -32,6 +33,7 @@ url = "2.1"
path = "../viaduct"
[dev-dependencies]
expect-test = "1.4"
mockito = "0.31"
[dev-dependencies.viaduct-reqwest]

View file

@ -1,11 +0,0 @@
apply from: "$rootDir/build-scripts/component-common.gradle"
apply from: "$rootDir/publish.gradle"
ext.configureUniFFIBindgen("../src/remote_settings.udl")
ext.dependsOnTheMegazord()
ext.configurePublish()
dependencies {
testImplementation("org.mozilla.components:concept-fetch:$android_components_version")
testImplementation project(":httpconfig")
}

View file

@ -1,2 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mozilla.appservices.remotesettings" />

View file

@ -1,168 +0,0 @@
/* 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/. */
package org.mozilla.appservices.remotesettings
import mozilla.appservices.httpconfig.RustHttpConfig
import mozilla.appservices.remotesettings.RemoteSettings
import mozilla.appservices.remotesettings.RemoteSettingsConfig
import mozilla.components.concept.fetch.Client
import mozilla.components.concept.fetch.Headers
import mozilla.components.concept.fetch.MutableHeaders
import mozilla.components.concept.fetch.Request
import mozilla.components.concept.fetch.Response
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import java.io.File
import java.io.InputStream
@RunWith(RobolectricTestRunner::class)
class RemoteSettingsTest {
@Rule @JvmField
val tempDir = TemporaryFolder()
private var fakeUrl = ""
private var fakeStatus = 200
private var fakeHeaders: Headers = MutableHeaders("etag" to "1000")
private var fakeBodyStream = "".byteInputStream()
private var fakeContentType = ""
private var fakeBody = Response.Body(fakeBodyStream, fakeContentType)
private var doFetch: (Request) -> Response = {
Response(fakeUrl, fakeStatus, fakeHeaders, fakeBody)
}
@Before
fun setup() {
RustHttpConfig.setClient(
lazyOf(object : Client() {
override fun fetch(request: Request): Response = doFetch(request)
}),
)
}
@Test
fun `test setting up, fetching records, and attachment downloading`() {
val config = RemoteSettingsConfig(
serverUrl = "http://localhost:8888",
bucketName = "the-bucket",
collectionName = "the-collection",
)
// Setup the client
val client = RemoteSettings(config)
// Fetch the records
setupRecordResponse(config, responseBodyStream = recordJson.byteInputStream())
val response = client.getRecords()
val records = response.records
assertEquals(records[0].fields.getString("title"), recordTitle)
// Download an attachment
val attachmentLocation = records[0].attachment!!.location
val localAttachmentPath = "${tempDir.root}/path.jpg"
setupAttachmentResponses(config, attachmentLocation)
client.downloadAttachmentToPath(attachmentLocation, localAttachmentPath)
val downloadedFile = File(localAttachmentPath)
assertTrue(downloadedFile.exists())
assertEquals(csv, downloadedFile.readText())
}
private fun setupAttachmentResponses(
config: RemoteSettingsConfig,
attachmentLocation: String,
) {
val topUrl = config.serverUrl
val attachmentUrl = "${config.serverUrl}/attachments/$attachmentLocation"
doFetch = { req ->
when (req.url) {
"$topUrl/" -> {
Response(
url = req.url,
status = 200,
headers = fakeHeaders,
body = Response.Body(
stream = attachmentsInfoJson(topUrl!!).byteInputStream(),
null,
),
)
}
attachmentUrl -> {
Response(
url = attachmentUrl,
status = 200,
headers = fakeHeaders,
body = Response.Body(
stream = csv.byteInputStream(),
null,
),
)
}
else -> error("unexpected url")
}
}
}
private fun setupRecordResponse(
config: RemoteSettingsConfig,
responseBodyStream: InputStream = recordJson.byteInputStream(),
) {
fakeUrl = "${config.serverUrl}/v1/buckets/${config.bucketName}/collections/${config.collectionName}/records"
fakeBody = Response.Body(responseBodyStream, null)
}
private fun attachmentsInfoJson(baseUrl: String) = """
{
"capabilities": {
"admin": {
"description": "Serves the admin console.",
"url": "https://github.com/Kinto/kinto-admin/",
"version": "2.0.0"
},
"attachments": {
"description": "Add file attachments to records",
"url": "https://github.com/Kinto/kinto-attachment/",
"version": "6.3.1",
"base_url": "$baseUrl/attachments/"
}
}
}
""".trimIndent()
private val recordTitle = "with-txt-attachment"
private val recordJson = """
{
"data": [
{
"title": "$recordTitle",
"content": "content",
"attachment": {
"filename": "text-attachment.csv",
"location": "the-bucket/the-collection/d3a5eccc-f0ca-42c3-b0bb-c0d4408c21c9.jpg",
"hash": "2cbd593f3fd5f1585f92265433a6696a863bc98726f03e7222135ff0d8e83543",
"mimetype": "text/csv",
"size": 1374325
},
"schema": 1677694447771,
"id": "7403c6f9-79be-4e0c-a37a-8f2b5bd7ad58",
"last_modified": 1677694455368
}
]
}
""".trimIndent()
private val csv = """
John,Doe,120 jefferson st.,Riverside, NJ, 08075
Jack,McGinnis,220 hobo Av.,Phila, PA,09119
"John ""Da Man""${'"'},Repici,120 Jefferson St.,Riverside, NJ,08075
Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234
,Blankman,,SomeTown, SD, 00298
"Joan ""the bone"", Anne",Jet,"9th, at Terrace plc",Desert City,CO,00123
""".trimIndent()
}

View file

@ -15,6 +15,7 @@ use url::Url;
use viaduct::{Request, Response};
const HEADER_BACKOFF: &str = "Backoff";
const HEADER_ETAG: &str = "ETag";
const HEADER_RETRY_AFTER: &str = "Retry-After";
/// A simple HTTP client that can retrieve Remote Settings data using the properties by [ClientConfig].
@ -48,16 +49,7 @@ impl Client {
/// bucket, and collection defined by the [ClientConfig] used to generate
/// this [Client].
pub fn get_records(&self) -> Result<RemoteSettingsResponse> {
let resp = self.get_records_raw()?;
let records = resp.json::<RecordsResponse>()?.data;
let last_modified = resp
.headers
.get_as("etag")
.ok_or_else(|| RemoteSettingsError::ResponseError("no etag header".into()))??;
Ok(RemoteSettingsResponse {
records,
last_modified,
})
self.get_records_with_options(&GetItemsOptions::new())
}
/// Fetches all records for a collection that can be found in the server,
@ -71,14 +63,31 @@ impl Client {
/// for a collection that can be found in the server, bucket, and
/// collection defined by the [ClientConfig] used to generate this [Client].
pub fn get_records_since(&self, timestamp: u64) -> Result<RemoteSettingsResponse> {
let resp = self.get_records_raw_with_options(
self.get_records_with_options(
GetItemsOptions::new().gt("last_modified", timestamp.to_string()),
)?;
)
}
/// Fetches records from this client's collection with the given options.
pub fn get_records_with_options(
&self,
options: &GetItemsOptions,
) -> Result<RemoteSettingsResponse> {
let resp = self.get_records_raw_with_options(options)?;
let records = resp.json::<RecordsResponse>()?.data;
let last_modified = resp
let etag = resp
.headers
.get_as("etag")
.ok_or_else(|| RemoteSettingsError::ResponseError("no etag header".into()))??;
.get(HEADER_ETAG)
.ok_or_else(|| RemoteSettingsError::ResponseError("no etag header".into()))?;
// Per https://docs.kinto-storage.org/en/stable/api/1.x/timestamps.html,
// the `ETag` header value is a quoted integer. Trim the quotes before
// parsing.
let last_modified = etag.trim_matches('"').parse().map_err(|_| {
RemoteSettingsError::ResponseError(format!(
"expected quoted integer in etag header; got `{}`",
etag
))
})?;
Ok(RemoteSettingsResponse {
records,
last_modified,
@ -102,22 +111,32 @@ impl Client {
/// Downloads an attachment from [attachment_location]. NOTE: there are no
/// guarantees about a maximum size, so use care when fetching potentially
/// large attachments.
pub fn get_attachment(&self, attachment_location: &str) -> Result<Response> {
let mut current_remote_state = self.remote_state.lock();
self.ensure_no_backoff(&mut current_remote_state.backoff)?;
let attachments_base_url = match &current_remote_state.attachments_base_url {
Some(url) => url.clone(),
pub fn get_attachment(&self, attachment_location: &str) -> Result<Vec<u8>> {
Ok(self.get_attachment_raw(attachment_location)?.body)
}
/// Fetches a raw network [Response] for an attachment.
pub fn get_attachment_raw(&self, attachment_location: &str) -> Result<Response> {
// Important: We use a `let` binding here to ensure that the mutex is
// unlocked immediately after cloning the URL. If we matched directly on
// the `.lock()` expression, the mutex would stay locked until the end
// of the `match`, causing a deadlock.
let maybe_attachments_base_url = self.remote_state.lock().attachments_base_url.clone();
let attachments_base_url = match maybe_attachments_base_url {
Some(attachments_base_url) => attachments_base_url,
None => {
let req = Request::get(self.base_url.clone());
let server_info = req.send()?.json::<ServerInfo>()?;
match server_info.capabilities.attachments {
let server_info = self
.make_request(self.base_url.clone())?
.json::<ServerInfo>()?;
let attachments_base_url = match server_info.capabilities.attachments {
Some(capability) => Url::parse(&capability.base_url)?,
None => Err(RemoteSettingsError::AttachmentsUnsupportedError)?,
}
};
self.remote_state.lock().attachments_base_url = Some(attachments_base_url.clone());
attachments_base_url
}
};
current_remote_state.attachments_base_url = Some(attachments_base_url.clone());
drop(current_remote_state);
self.make_request(attachments_base_url.join(attachment_location)?)
}
@ -187,6 +206,7 @@ impl Client {
/// Data structure representing the top-level response from the Remote Settings.
/// [last_modified] will be extracted from the etag header of the response.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RemoteSettingsResponse {
pub records: Vec<RemoteSettingsRecord>,
pub last_modified: u64,
@ -203,6 +223,8 @@ struct RecordsResponse {
pub struct RemoteSettingsRecord {
pub id: String,
pub last_modified: u64,
#[serde(default)]
pub deleted: bool,
pub attachment: Option<Attachment>,
#[serde(flatten)]
pub fields: RsJsonObject,
@ -485,6 +507,7 @@ impl Sort {
#[cfg(test)]
mod test {
use super::*;
use expect_test::expect;
use mockito::{mock, Matcher};
#[test]
fn test_defaults() {
@ -528,11 +551,13 @@ mod test {
};
let client = Client::new(config).unwrap();
let resp = client.get_attachment(attachment_location).unwrap();
let first_resp = client.get_attachment(attachment_location).unwrap();
let second_resp = client.get_attachment(attachment_location).unwrap();
server_info_m.expect(1).assert();
attachment_m.expect(1).assert();
assert_eq!(resp.body, attachment_bytes);
attachment_m.expect(2).assert();
assert_eq!(first_resp, attachment_bytes);
assert_eq!(second_resp, attachment_bytes);
}
#[test]
@ -582,7 +607,7 @@ mod test {
.with_status(200)
.with_header("content-type", "application/json")
.with_header("Backoff", "60")
.with_header("etag", "1000")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
@ -651,7 +676,7 @@ mod test {
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "1000")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
@ -659,9 +684,8 @@ mod test {
bucket_name: Some(String::from("the-bucket")),
};
let http_client = Client::new(config).unwrap();
assert!(http_client
.get_records_raw_with_options(
GetItemsOptions::new()
let mut options = GetItemsOptions::new();
options
.field("a")
.field("c")
.field("b")
@ -677,10 +701,93 @@ mod test {
.contains("n", "o")
.sort("b", SortOrder::Descending)
.sort("a", SortOrder::Ascending)
.limit(3)
)
.is_ok());
m.expect(1).assert();
.limit(3);
assert!(http_client.get_records_raw_with_options(&options).is_ok());
expect![[r#"
RemoteSettingsResponse {
records: [
RemoteSettingsRecord {
id: "c5dcd1da-7126-4abb-846b-ec85b0d4d0d7",
last_modified: 1677694949407,
deleted: false,
attachment: Some(
Attachment {
filename: "jgp-attachment.jpg",
mimetype: "image/jpeg",
location: "the-bucket/the-collection/d3a5eccc-f0ca-42c3-b0bb-c0d4408c21c9.jpg",
hash: "2cbd593f3fd5f1585f92265433a6696a863bc98726f03e7222135ff0d8e83543",
size: 1374325,
},
),
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"jpg-attachment",
),
},
},
RemoteSettingsRecord {
id: "ff301910-6bf5-4cfe-bc4c-5c80308661a5",
last_modified: 1677694470354,
deleted: false,
attachment: Some(
Attachment {
filename: "pdf-attachment.pdf",
mimetype: "application/pdf",
location: "the-bucket/the-collection/5f7347c2-af92-411d-a65b-f794f9b5084c.pdf",
hash: "de1cde3571ef3faa77ea0493276de9231acaa6f6651602e93aa1036f51181e9b",
size: 157,
},
),
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"with-attachment",
),
},
},
RemoteSettingsRecord {
id: "7403c6f9-79be-4e0c-a37a-8f2b5bd7ad58",
last_modified: 1677694455368,
deleted: false,
attachment: None,
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"no-attachment",
),
},
},
RemoteSettingsRecord {
id: "9320f53c-0a39-4997-9120-62ff597ffb26",
last_modified: 1690921847416,
deleted: true,
attachment: None,
fields: {},
},
],
last_modified: 1000,
}
"#]].assert_debug_eq(&http_client
.get_records_with_options(&options)
.unwrap());
m.expect(2).assert();
}
#[test]
@ -693,7 +800,7 @@ mod test {
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "1000")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
@ -723,6 +830,166 @@ mod test {
m.expect(1).assert();
}
#[test]
fn test_record_fields() {
viaduct_reqwest::use_reqwest_backend();
let m = mock(
"GET",
"/v1/buckets/the-bucket/collections/the-collection/records",
)
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
let http_client = Client::new(config).unwrap();
let response = http_client.get_records().unwrap();
expect![[r#"
RemoteSettingsResponse {
records: [
RemoteSettingsRecord {
id: "c5dcd1da-7126-4abb-846b-ec85b0d4d0d7",
last_modified: 1677694949407,
deleted: false,
attachment: Some(
Attachment {
filename: "jgp-attachment.jpg",
mimetype: "image/jpeg",
location: "the-bucket/the-collection/d3a5eccc-f0ca-42c3-b0bb-c0d4408c21c9.jpg",
hash: "2cbd593f3fd5f1585f92265433a6696a863bc98726f03e7222135ff0d8e83543",
size: 1374325,
},
),
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"jpg-attachment",
),
},
},
RemoteSettingsRecord {
id: "ff301910-6bf5-4cfe-bc4c-5c80308661a5",
last_modified: 1677694470354,
deleted: false,
attachment: Some(
Attachment {
filename: "pdf-attachment.pdf",
mimetype: "application/pdf",
location: "the-bucket/the-collection/5f7347c2-af92-411d-a65b-f794f9b5084c.pdf",
hash: "de1cde3571ef3faa77ea0493276de9231acaa6f6651602e93aa1036f51181e9b",
size: 157,
},
),
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"with-attachment",
),
},
},
RemoteSettingsRecord {
id: "7403c6f9-79be-4e0c-a37a-8f2b5bd7ad58",
last_modified: 1677694455368,
deleted: false,
attachment: None,
fields: {
"content": String(
"content",
),
"schema": Number(
1677694447771,
),
"title": String(
"no-attachment",
),
},
},
RemoteSettingsRecord {
id: "9320f53c-0a39-4997-9120-62ff597ffb26",
last_modified: 1690921847416,
deleted: true,
attachment: None,
fields: {},
},
],
last_modified: 1000,
}
"#]].assert_debug_eq(&response);
m.expect(1).assert();
}
#[test]
fn test_missing_etag() {
viaduct_reqwest::use_reqwest_backend();
let m = mock(
"GET",
"/v1/buckets/the-bucket/collections/the-collection/records",
)
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
let client = Client::new(config).unwrap();
let err = client.get_records().unwrap_err();
assert!(
matches!(err, RemoteSettingsError::ResponseError(_)),
"Want response error for missing `ETag`; got {}",
err
);
m.expect(1).assert();
}
#[test]
fn test_invalid_etag() {
viaduct_reqwest::use_reqwest_backend();
let m = mock(
"GET",
"/v1/buckets/the-bucket/collections/the-collection/records",
)
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "bad!")
.create();
let config = RemoteSettingsConfig {
server_url: Some(mockito::server_url()),
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
let client = Client::new(config).unwrap();
let err = client.get_records().unwrap_err();
assert!(
matches!(err, RemoteSettingsError::ResponseError(_)),
"Want response error for invalid `ETag`; got {}",
err
);
m.expect(1).assert();
}
fn attachment_metadata(base_url: String) -> String {
format!(
r#"
@ -763,12 +1030,13 @@ mod test {
r#"
{{
"data": [
{},
{},
{},
{}
]
}}"#,
JPG_ATTACHMENT, PDF_ATTACHMENT, NO_ATTACHMENT
JPG_ATTACHMENT, PDF_ATTACHMENT, NO_ATTACHMENT, TOMBSTONE
)
}
@ -815,4 +1083,12 @@ mod test {
"last_modified": 1677694455368
}
"#;
const TOMBSTONE: &str = r#"
{
"id": "9320f53c-0a39-4997-9120-62ff597ffb26",
"last_modified": 1690921847416,
"deleted": true
}
"#;
}

View file

@ -8,8 +8,6 @@ pub enum RemoteSettingsError {
JSONError(#[from] serde_json::Error),
#[error("Error writing downloaded attachment: {0}")]
FileError(#[from] std::io::Error),
#[error("ParseIntError: {0}")]
ParseIntError(#[from] std::num::ParseIntError),
/// An error has occured while sending a request.
#[error("Error sending request: {0}")]
RequestError(#[from] viaduct::Error),

View file

@ -45,7 +45,7 @@ impl RemoteSettings {
) -> Result<()> {
let resp = self.client.get_attachment(&attachment_location)?;
let mut file = File::create(path)?;
file.write_all(&resp.body)?;
file.write_all(&resp)?;
Ok(())
}
}
@ -66,7 +66,7 @@ mod test {
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "1000")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
@ -94,7 +94,7 @@ mod test {
.with_body(response_body())
.with_status(200)
.with_header("content-type", "application/json")
.with_header("etag", "1000")
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {

View file

@ -21,6 +21,7 @@ dictionary RemoteSettingsResponse {
dictionary RemoteSettingsRecord {
string id;
u64 last_modified;
boolean deleted;
Attachment? attachment;
RsJsonObject fields;
};
@ -37,7 +38,6 @@ dictionary Attachment {
enum RemoteSettingsError {
"JSONError",
"FileError",
"ParseIntError",
"RequestError",
"UrlParsingError",
"BackoffError",

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"e679992b7cf7d42cdbc5d6350c512ca448a273767003db600ef8099c7182bd99","build.rs":"d89f20669c2e243652630ce025199d187d2a128be6a626a02e0679bd74a2ad5a","src/conn_ext.rs":"e48e862e47c000c545dcc766fc1889498a8709bee00e240ed68d247b0fbef577","src/debug_tools.rs":"bece2bc3d35379b81ea2f942a0a3e909e0ab0553656505904745548eacaf402a","src/each_chunk.rs":"8aaba842e43b002fbc0fee95d14ce08faa7187b1979c765b2e270cd4802607a5","src/lib.rs":"af704ec04beb6c2c388d4566710e1167b18fb64acb248ccf37a67679daffddb6","src/maybe_cached.rs":"0b18425595055883a98807fbd62ff27a79c18af34e7cb3439f8c3438463ef2dd","src/open_database.rs":"dcc7140095f9ba20442b5e6294d8af924d54588837cf2ce019dff013fa198783","src/repeat.rs":"b4c5ff5d083afba7f9f153f54aba2e6859b78b85c82d48dbd6bd58f67da9e6b9"},"package":null}
{"files":{"Cargo.toml":"e679992b7cf7d42cdbc5d6350c512ca448a273767003db600ef8099c7182bd99","build.rs":"d89f20669c2e243652630ce025199d187d2a128be6a626a02e0679bd74a2ad5a","src/conn_ext.rs":"e48e862e47c000c545dcc766fc1889498a8709bee00e240ed68d247b0fbef577","src/debug_tools.rs":"bece2bc3d35379b81ea2f942a0a3e909e0ab0553656505904745548eacaf402a","src/each_chunk.rs":"8aaba842e43b002fbc0fee95d14ce08faa7187b1979c765b2e270cd4802607a5","src/lib.rs":"af704ec04beb6c2c388d4566710e1167b18fb64acb248ccf37a67679daffddb6","src/maybe_cached.rs":"0b18425595055883a98807fbd62ff27a79c18af34e7cb3439f8c3438463ef2dd","src/open_database.rs":"40ad2da7d5559f0e5180e35d403c307ce230fe9d0d2a3fec7c9481ce13acda64","src/repeat.rs":"b4c5ff5d083afba7f9f153f54aba2e6859b78b85c82d48dbd6bd58f67da9e6b9"},"package":null}

View file

@ -22,6 +22,8 @@
/// it and call prepare(), upgrade_from() for each upgrade that needs to be applied, then
/// finish(). As above, a read-only connection will panic if upgrades are necessary, so
/// you should ensure the first connection opened is writable.
/// - If the database file is corrupt, or upgrade_from() returns [`Error::Corrupt`], the
/// database file will be removed and replaced with a new DB.
/// - If the connection is not writable, `finish()` will be called (ie, `finish()`, like
/// `prepare()`, is called for all connections)
///
@ -38,11 +40,25 @@ use thiserror::Error;
pub enum Error {
#[error("Incompatible database version: {0}")]
IncompatibleVersion(u32),
#[error("Database is corrupt")]
Corrupt,
#[error("Error executing SQL: {0}")]
SqlError(#[from] rusqlite::Error),
// `.0` is the original `Error` in string form.
#[error("Failed to recover a corrupt database ('{0}') due to an error deleting the file: {1}")]
RecoveryError(String, std::io::Error),
SqlError(rusqlite::Error),
#[error("Failed to recover a corrupt database due to an error deleting the file: {0}")]
RecoveryError(std::io::Error),
}
impl From<rusqlite::Error> for Error {
fn from(value: rusqlite::Error) -> Self {
match value {
RusqliteError::SqliteFailure(e, _)
if matches!(e.code, ErrorCode::DatabaseCorrupt | ErrorCode::NotADatabase) =>
{
Self::Corrupt
}
_ => Self::SqlError(value),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
@ -189,12 +205,7 @@ fn try_handle_db_failure<CI: ConnectionInitializer, P: AsRef<Path>>(
return Err(err);
}
let delete = match err {
Error::SqlError(RusqliteError::SqliteFailure(e, _)) => {
matches!(e.code, ErrorCode::DatabaseCorrupt | ErrorCode::NotADatabase)
}
_ => false,
};
let delete = matches!(err, Error::Corrupt);
if delete {
log::info!(
"{}: the database is fatally damaged; deleting and starting fresh",
@ -204,7 +215,7 @@ fn try_handle_db_failure<CI: ConnectionInitializer, P: AsRef<Path>>(
// identify any value there - actually getting our hands on the file from a mobile device
// is tricky and it would just take up disk space forever.
if let Err(io_err) = std::fs::remove_file(path) {
return Err(Error::RecoveryError(err.to_string(), io_err));
return Err(Error::RecoveryError(io_err));
}
Ok(())
} else {
@ -364,6 +375,12 @@ mod test {
fn upgrade_from(&self, conn: &Transaction<'_>, version: u32) -> Result<()> {
match version {
// This upgrade forces the database to be replaced by returning
// `Error::Corrupt`.
1 => {
self.push_call("upgrade_from_v1");
Err(Error::Corrupt)
}
2 => {
self.push_call("upgrade_from_v2");
conn.execute_batch(
@ -404,6 +421,13 @@ mod test {
}
}
// A special schema used to test the upgrade that forces the database to be
// replaced.
static INIT_V1: &str = "
CREATE TABLE prep_table(col);
PRAGMA user_version=1;
";
// Initialize the database to v2 to test upgrading from there
static INIT_V2: &str = "
CREATE TABLE prep_table(col);
@ -533,4 +557,18 @@ mod test {
// just check the file is no longer what it was before.
assert_ne!(metadata.len(), 7);
}
#[test]
fn test_force_replace() {
let db_file = MigratedDatabaseFile::new(TestConnectionInitializer::new(), INIT_V1);
let conn = open_database(db_file.path.clone(), &db_file.connection_initializer).unwrap();
check_final_data(&conn);
db_file.connection_initializer.check_calls(vec![
"prep",
"upgrade_from_v1",
"prep",
"init",
"finish",
]);
}
}

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"2a7334dc6420c7f7d1c14affaee132fb355e96ae94463153db72d7d5a316efd7","README.md":"8d7457893194e255b87e5a2667ee25c87bd470f5338d7078506f866a67a3fdbd","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","src/db.rs":"9ad7fe53861ccfa01ccda1aa2132154a7967f7ef729709a52c940a4ea9ab2539","src/error.rs":"f47763a1a5d228b446eb8f718433e49fdb1c7b304de1255891215144dddd7a43","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"831fd8e3881be06c560d502357188d143a2774e19b371cc40c40c2378810297b","src/rs.rs":"9e8e937306615c1e173143083d4a5b526a1c0c2b28092305ecd4dfe6c665f851","src/schema.rs":"962b9f5916089d6656de77afcc81e51cb81310f8dbcb9bbaa248b26a1d087332","src/store.rs":"d04edba77295f3a96af18668a1851fd1b4afe5ae449b8b1a14cd47e25151fd51","src/suggest.udl":"8035e6261e55d5e37366f219f5806b842cc2f91dffd39e3ba9bfa9484e22fd6c","uniffi.toml":"fb8add80c2f660e4eacf95ec3f0b1d0f6a92ab5dbcf607782350442814ee26a7"},"package":null}
{"files":{"Cargo.toml":"7c19ff48428dd00ea709c254f1aa44627dd5d0f30d0741285f27a6f4a6200e1f","README.md":"8d7457893194e255b87e5a2667ee25c87bd470f5338d7078506f866a67a3fdbd","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","src/db.rs":"f40754ac33ff111b5165ed271064de8248acd2d39ac67aed92cbbda2826f45fe","src/error.rs":"f47763a1a5d228b446eb8f718433e49fdb1c7b304de1255891215144dddd7a43","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"1294435de3ed1de26f7fe7e9a5760bcb1fe06c9c51f308c1f63666f96ba59ae5","src/provider.rs":"8aa8e41dfc64bb0adc24ed7f07a2687130bc59710cece2bd981a8b9e4e4a3594","src/rs.rs":"474fee04323c5c2881e679f57bea318c9ba2faa1873ce8f24abc4d92775dd7b4","src/schema.rs":"9e383221bdb11d84f4d1f2e7a7034983154917c92c5ed25b75fce5f5bf8fd159","src/store.rs":"7affafe7d9396821ff6bd19321837d1cb2e4ecc009880804e704d8cfcfca898f","src/suggest.udl":"d7a5ba8edf0f56affa8ac5be0b6111736840a56e1057cd7125c996da21e3d984","src/suggestion.rs":"053637820aaae3869005e5906bd29edb002f2e9b18172ee271e0c2aec35cd028","uniffi.toml":"fb8add80c2f660e4eacf95ec3f0b1d0f6a92ab5dbcf607782350442814ee26a7"},"package":null}

View file

@ -48,11 +48,15 @@ path = "../support/sql"
[dev-dependencies]
expect-test = "1.4"
hex = "0.4"
[dev-dependencies.env_logger]
version = "0.7"
default-features = false
[dev-dependencies.rc_crypto]
path = "../support/rc_crypto"
[build-dependencies.uniffi]
version = "0.24.1"
features = ["build"]

View file

@ -16,7 +16,8 @@ use sql_support::{open_database::open_database_with_flags, ConnExt};
use crate::{
keyword::full_keyword,
rs::{DownloadedSuggestion, SuggestRecordId},
provider::SuggestionProvider,
rs::{DownloadedAmpWikipediaSuggestion, SuggestRecordId},
schema::SuggestConnectionInitializer,
Result, Suggestion,
};
@ -25,10 +26,6 @@ use crate::{
/// from the Suggest Remote Settings collection.
pub const LAST_INGEST_META_KEY: &str = "last_quicksuggest_ingest";
/// A list of [`Suggestion::iab_category`] values used to distinguish
/// non-sponsored suggestions.
pub const NONSPONSORED_IAB_CATEGORIES: &[&str] = &["5 - Education"];
/// The database connection type.
#[derive(Clone, Copy)]
pub(crate) enum ConnectionType {
@ -122,9 +119,7 @@ impl<'a> SuggestDao<'a> {
/// Fetches suggestions that match the given keyword from the database.
pub fn fetch_by_keyword(&self, keyword: &str) -> Result<Vec<Suggestion>> {
self.conn.query_rows_and_then_cached(
"SELECT s.id, k.rank, s.block_id, s.advertiser, s.iab_category,
s.title, s.url, s.impression_url, s.click_url,
(SELECT i.data FROM icons i WHERE i.id = s.icon_id) AS icon
"SELECT s.id, k.rank, s.title, s.url, s.provider
FROM suggestions s
JOIN keywords k ON k.suggestion_id = s.id
WHERE k.keyword = :keyword
@ -132,83 +127,157 @@ impl<'a> SuggestDao<'a> {
named_params! {
":keyword": keyword,
},
|row| -> Result<Suggestion> {
let keywords: Vec<String> = self.conn.query_rows_and_then(
|row| -> Result<Suggestion>{
let suggestion_id: i64 = row.get("id")?;
let title = row.get("title")?;
let url = row.get("url")?;
let provider = row.get("provider")?;
let keywords: Vec<String> = self.conn.query_rows_and_then_cached(
"SELECT keyword FROM keywords
WHERE suggestion_id = :suggestion_id AND rank >= :rank
ORDER BY rank ASC",
named_params! {
":suggestion_id": row.get::<_, i64>("id")?,
":suggestion_id": suggestion_id,
":rank": row.get::<_, i64>("rank")?,
},
|row| row.get(0),
)?;
let iab_category = row.get::<_, String>("iab_category")?;
let is_sponsored = !NONSPONSORED_IAB_CATEGORIES.contains(&iab_category.as_str());
Ok(Suggestion {
match provider {
SuggestionProvider::Amp => {
self.conn.query_row_and_then(
"SELECT amp.advertiser, amp.block_id, amp.iab_category, amp.impression_url, amp.click_url,
(SELECT i.data FROM icons i WHERE i.id = amp.icon_id) AS icon
FROM amp_custom_details amp
WHERE amp.suggestion_id = :suggestion_id",
named_params! {
":suggestion_id": suggestion_id
},
|row| {
Ok(Suggestion::Amp {
block_id: row.get("block_id")?,
advertiser: row.get("advertiser")?,
iab_category,
is_sponsored,
title: row.get("title")?,
url: row.get("url")?,
iab_category: row.get("iab_category")?,
title,
url,
full_keyword: full_keyword(keyword, &keywords),
icon: row.get("icon")?,
impression_url: row.get("impression_url")?,
click_url: row.get("click_url")?,
})
}
)
},
SuggestionProvider::Wikipedia => {
let icon = self.conn.try_query_one(
"SELECT i.data
FROM icons i
JOIN wikipedia_custom_details s ON s.icon_id = i.id
WHERE s.suggestion_id = :suggestion_id",
named_params! {
":suggestion_id": suggestion_id
},
true,
)?;
Ok(Suggestion::Wikipedia {
title,
url,
full_keyword: full_keyword(keyword, &keywords),
icon,
})
}
}
},
)
}
/// Inserts all suggestions associated with a Remote Settings record into
/// Inserts all suggestions from a downloaded AMP-Wikipedia attachment into
/// the database.
pub fn insert_suggestions(
pub fn insert_amp_wikipedia_suggestions(
&mut self,
record_id: &SuggestRecordId,
suggestions: &[DownloadedSuggestion],
suggestions: &[DownloadedAmpWikipediaSuggestion],
) -> Result<()> {
for suggestion in suggestions {
self.scope.err_if_interrupted()?;
let common_details = suggestion.common_details();
let provider = suggestion.provider();
let suggestion_id: i64 = self.conn.query_row_and_then_cachable(
"INSERT INTO suggestions(
record_id,
block_id,
advertiser,
iab_category,
provider,
title,
url,
icon_id,
impression_url,
click_url
url
)
VALUES(
:record_id,
:block_id,
:advertiser,
:iab_category,
:provider,
:title,
:url,
:icon_id,
:impression_url,
:click_url
:url
)
RETURNING id",
RETURNING id
",
named_params! {
":record_id": record_id.as_str(),
":block_id": suggestion.block_id,
":advertiser": suggestion.advertiser,
":iab_category": suggestion.iab_category,
":title": suggestion.title,
":url": suggestion.url,
":icon_id": suggestion.icon_id,
":impression_url": suggestion.impression_url,
":click_url": suggestion.click_url,
":provider": &provider,
":title": common_details.title,
":url": common_details.url,
},
|row| row.get(0),
true,
)?;
for (index, keyword) in suggestion.keywords.iter().enumerate() {
match suggestion {
DownloadedAmpWikipediaSuggestion::Amp(amp) => {
self.conn.execute(
"INSERT INTO amp_custom_details(
suggestion_id,
advertiser,
block_id,
iab_category,
impression_url,
click_url,
icon_id
)
VALUES(
:suggestion_id,
:advertiser,
:block_id,
:iab_category,
:impression_url,
:click_url,
:icon_id
)",
named_params! {
":suggestion_id": suggestion_id,
":advertiser": amp.advertiser,
":block_id": amp.block_id,
":iab_category": amp.iab_category,
":impression_url": amp.impression_url,
":click_url": amp.click_url,
":icon_id": amp.icon_id,
},
)?;
}
DownloadedAmpWikipediaSuggestion::Wikipedia(wikipedia) => {
self.conn.execute(
"INSERT INTO wikipedia_custom_details(
suggestion_id,
icon_id
)
VALUES(
:suggestion_id,
:icon_id
)",
named_params! {
":suggestion_id": suggestion_id,
":icon_id": wikipedia.icon_id,
},
)?;
}
}
for (index, keyword) in common_details.keywords.iter().enumerate() {
self.conn.execute(
"INSERT INTO keywords(
keyword,
@ -231,10 +300,10 @@ impl<'a> SuggestDao<'a> {
Ok(())
}
/// Inserts an icon for a suggestion into the database.
pub fn insert_icon(&mut self, icon_id: &str, data: &[u8]) -> Result<()> {
/// Inserts or replaces an icon for a suggestion into the database.
pub fn put_icon(&mut self, icon_id: &str, data: &[u8]) -> Result<()> {
self.conn.execute(
"INSERT INTO icons(
"INSERT OR REPLACE INTO icons(
id,
data
)
@ -291,7 +360,7 @@ impl<'a> SuggestDao<'a> {
/// Sets the value for a metadata key.
pub fn put_meta(&mut self, key: &str, value: impl ToSql) -> Result<()> {
self.conn.execute_cached(
"REPLACE INTO meta(key, value) VALUES(:key, :value)",
"INSERT OR REPLACE INTO meta(key, value) VALUES(:key, :value)",
named_params! { ":key": key, ":value": value },
)?;
Ok(())

View file

@ -4,35 +4,23 @@
*/
use remote_settings::RemoteSettingsConfig;
mod db;
mod error;
mod keyword;
mod provider;
mod rs;
mod schema;
mod store;
mod suggestion;
pub use error::SuggestApiError;
pub use provider::SuggestionProvider;
pub use store::{SuggestIngestionConstraints, SuggestStore};
pub use suggestion::Suggestion;
pub(crate) type Result<T> = std::result::Result<T, error::Error>;
pub type SuggestApiResult<T> = std::result::Result<T, error::SuggestApiError>;
/// A suggestion from the database to show in the address bar.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Suggestion {
pub block_id: i64,
pub advertiser: String,
pub iab_category: String,
pub is_sponsored: bool,
pub full_keyword: String,
pub title: String,
pub url: String,
pub icon: Option<Vec<u8>>,
pub impression_url: Option<String>,
pub click_url: Option<String>,
}
/// A query for suggestions to show in the address bar.
#[derive(Debug, Default)]
pub struct SuggestionQuery {

View file

@ -0,0 +1,44 @@
/* 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/.
*/
use rusqlite::{
types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef},
Result as RusqliteResult,
};
/// A provider is a source of search suggestions.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[repr(u8)]
pub enum SuggestionProvider {
Amp = 1,
Wikipedia = 2,
}
impl FromSql for SuggestionProvider {
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
let v = value.as_i64()?;
u8::try_from(v)
.ok()
.and_then(SuggestionProvider::from_u8)
.ok_or_else(|| FromSqlError::OutOfRange(v))
}
}
impl SuggestionProvider {
#[inline]
pub(crate) fn from_u8(v: u8) -> Option<Self> {
match v {
1 => Some(SuggestionProvider::Amp),
2 => Some(SuggestionProvider::Wikipedia),
_ => None,
}
}
}
impl ToSql for SuggestionProvider {
fn to_sql(&self) -> RusqliteResult<ToSqlOutput<'_>> {
Ok(ToSqlOutput::from(*self as u8))
}
}

View file

@ -1,9 +1,40 @@
use std::ops::Deref;
/* 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/.
*/
use remote_settings::{Attachment, GetItemsOptions};
use serde::Deserialize;
//! Crate-internal types for interacting with Remote Settings (`rs`). Types in
//! this module describe records and attachments in the Suggest Remote Settings
//! collection.
//!
//! To add a new suggestion `T` to this component, you'll generally need to:
//!
//! 1. Add a variant named `T` to [`SuggestRecord`]. The variant must have a
//! `#[serde(rename)]` attribute that matches the suggestion record's
//! `type` field.
//! 2. Define a `DownloadedTSuggestion` type with the new suggestion's fields,
//! matching their attachment's schema. Your new type must derive or
//! implement [`serde::Deserialize`].
//! 3. Update the database schema in the [`schema`] module to store the new
//! suggestion.
//! 4. Add an `insert_t_suggestions()` method to [`db::SuggestDao`] that
//! inserts `DownloadedTSuggestion`s into the database.
//! 5. Update [`store::SuggestStoreInner::ingest()`] to download, deserialize,
//! and store the new suggestion.
//! 6. Add a variant named `T` to [`suggestion::Suggestion`], with the fields
//! that you'd like to expose to the application. These can be the same
//! fields as `DownloadedTSuggestion`, or slightly different, depending on
//! what the application needs to show the suggestion.
//! 7. Update any [`db::SuggestDao`] methods that query the database to include
//! the new suggestion in their results, and return `Suggestion::T` variants
//! as needed.
use crate::Result;
use std::borrow::Cow;
use remote_settings::{GetItemsOptions, RemoteSettingsResponse};
use serde::{Deserialize, Deserializer};
use crate::{provider::SuggestionProvider, Result};
/// The Suggest Remote Settings collection name.
pub(crate) const REMOTE_SETTINGS_COLLECTION: &str = "quicksuggest";
@ -19,119 +50,72 @@ pub(crate) const SUGGESTIONS_PER_ATTACHMENT: u64 = 200;
/// This trait lets tests use a mock client.
pub(crate) trait SuggestRemoteSettingsClient {
/// Fetches records from the Suggest Remote Settings collection.
fn get_records_with_options(
&self,
options: &GetItemsOptions,
) -> Result<SuggestRemoteSettingsRecords>;
fn get_records_with_options(&self, options: &GetItemsOptions)
-> Result<RemoteSettingsResponse>;
/// Fetches a data attachment with suggestions to ingest from the Suggest
/// Remote Settings collection.
fn get_data_attachment(&self, location: &str) -> Result<DownloadedSuggestDataAttachment>;
/// Fetches an icon attachment from the Suggest Remote Settings collection.
fn get_icon_attachment(&self, location: &str) -> Result<Vec<u8>>;
/// Fetches a record's attachment from the Suggest Remote Settings
/// collection.
fn get_attachment(&self, location: &str) -> Result<Vec<u8>>;
}
impl SuggestRemoteSettingsClient for remote_settings::Client {
fn get_records_with_options(
&self,
options: &GetItemsOptions,
) -> Result<SuggestRemoteSettingsRecords> {
Ok(self.get_records_raw_with_options(options)?.json()?)
) -> Result<RemoteSettingsResponse> {
Ok(remote_settings::Client::get_records_with_options(
self, options,
)?)
}
fn get_data_attachment(&self, location: &str) -> Result<DownloadedSuggestDataAttachment> {
Ok(self.get_attachment(location)?.json()?)
}
fn get_icon_attachment(&self, location: &str) -> Result<Vec<u8>> {
Ok(self.get_attachment(location)?.body)
fn get_attachment(&self, location: &str) -> Result<Vec<u8>> {
Ok(remote_settings::Client::get_attachment(self, location)?)
}
}
/// The response body for a Suggest Remote Settings collection request.
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct SuggestRemoteSettingsRecords {
pub data: Vec<SuggestRecord>,
}
/// A record with a known or an unknown type, or a tombstone, in the Suggest
/// Remote Settings collection.
/// A record in the Suggest Remote Settings collection.
///
/// Because `#[serde(other)]` doesn't support associated data
/// (serde-rs/serde#1973), we can't define variants for all the known types and
/// the unknown type in the same enum. Instead, we have this "outer", untagged
/// `SuggestRecord` with the "unknown type" variant, and an "inner", internally
/// tagged `TypedSuggestRecord` with all the "known type" variants.
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub(crate) enum SuggestRecord {
/// A record with a known type.
Typed(TypedSuggestRecord),
/// A tombstone, or a record with an unknown type, that we don't know how
/// to ingest.
///
/// Tombstones only have these three fields, with `deleted` set to `true`.
/// Records with unknown types have `deleted` set to `false`, and may
/// contain other fields that we ignore.
Untyped {
id: SuggestRecordId,
last_modified: u64,
#[serde(default)]
deleted: bool,
},
}
/// A record that we know how to ingest from Remote Settings.
/// Except for the type, Suggest records don't carry additional fields. All
/// suggestions are stored in each record's attachment.
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub(crate) enum TypedSuggestRecord {
pub(crate) enum SuggestRecord {
#[serde(rename = "icon")]
Icon {
id: SuggestRecordId,
last_modified: u64,
attachment: Attachment,
},
Icon,
#[serde(rename = "data")]
Data {
id: SuggestRecordId,
last_modified: u64,
attachment: Attachment,
},
AmpWikipedia,
}
/// Represents either a single value, or a list of values. This is used to
/// deserialize downloaded data attachments.
/// deserialize downloaded attachments.
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub(crate) enum OneOrMany<T> {
enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
impl<T> Deref for OneOrMany<T> {
type Target = [T];
/// A downloaded Remote Settings attachment that contains suggestions.
#[derive(Clone, Debug, Deserialize)]
#[serde(transparent)]
pub(crate) struct SuggestAttachment<T>(OneOrMany<T>);
fn deref(&self) -> &Self::Target {
match self {
impl<T> SuggestAttachment<T> {
/// Returns a slice of suggestions to ingest from the downloaded attachment.
pub fn suggestions(&self) -> &[T] {
match &self.0 {
OneOrMany::One(value) => std::slice::from_ref(value),
OneOrMany::Many(values) => values,
}
}
}
/// The contents of a downloaded [`TypedSuggestRecord::Data`] attachment.
#[derive(Clone, Debug, Deserialize)]
#[serde(transparent)]
pub(crate) struct DownloadedSuggestDataAttachment(pub OneOrMany<DownloadedSuggestion>);
/// The ID of a record in the Suggest Remote Settings collection.
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub(crate) struct SuggestRecordId(String);
pub(crate) struct SuggestRecordId<'a>(Cow<'a, str>);
impl SuggestRecordId {
impl<'a> SuggestRecordId<'a> {
pub fn as_str(&self) -> &str {
&self.0
}
@ -146,18 +130,107 @@ impl SuggestRecordId {
}
}
/// A suggestion to ingest from a downloaded Remote Settings attachment.
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct DownloadedSuggestion {
#[serde(rename = "id")]
pub block_id: i64,
pub advertiser: String,
pub iab_category: String,
impl<'a, T> From<T> for SuggestRecordId<'a>
where
T: Into<Cow<'a, str>>,
{
fn from(value: T) -> Self {
Self(value.into())
}
}
/// Fields that are common to all downloaded suggestions.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub(crate) struct DownloadedSuggestionCommonDetails {
pub keywords: Vec<String>,
pub title: String,
pub url: String,
}
/// An AMP suggestion to ingest from an AMP-Wikipedia attachment.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub(crate) struct DownloadedAmpSuggestion {
#[serde(flatten)]
pub common_details: DownloadedSuggestionCommonDetails,
pub advertiser: String,
#[serde(rename = "id")]
pub block_id: i32,
pub iab_category: String,
pub click_url: String,
pub impression_url: String,
#[serde(rename = "icon")]
pub icon_id: String,
pub impression_url: Option<String>,
pub click_url: Option<String>,
}
/// A Wikipedia suggestion to ingest from an AMP-Wikipedia attachment.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub(crate) struct DownloadedWikipediaSuggestion {
#[serde(flatten)]
pub common_details: DownloadedSuggestionCommonDetails,
#[serde(rename = "icon")]
pub icon_id: String,
}
/// A suggestion to ingest from an AMP-Wikipedia attachment downloaded from
/// Remote Settings.
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum DownloadedAmpWikipediaSuggestion {
Amp(DownloadedAmpSuggestion),
Wikipedia(DownloadedWikipediaSuggestion),
}
impl DownloadedAmpWikipediaSuggestion {
/// Returns the details that are common to AMP and Wikipedia suggestions.
pub fn common_details(&self) -> &DownloadedSuggestionCommonDetails {
match self {
Self::Amp(DownloadedAmpSuggestion { common_details, .. }) => common_details,
Self::Wikipedia(DownloadedWikipediaSuggestion { common_details, .. }) => common_details,
}
}
/// Returns the provider of this suggestion.
pub fn provider(&self) -> SuggestionProvider {
match self {
DownloadedAmpWikipediaSuggestion::Amp(_) => SuggestionProvider::Amp,
DownloadedAmpWikipediaSuggestion::Wikipedia(_) => SuggestionProvider::Wikipedia,
}
}
}
impl<'de> Deserialize<'de> for DownloadedAmpWikipediaSuggestion {
fn deserialize<D>(
deserializer: D,
) -> std::result::Result<DownloadedAmpWikipediaSuggestion, D::Error>
where
D: Deserializer<'de>,
{
// AMP and Wikipedia suggestions use the same schema. To separate them,
// we use a "maybe tagged" outer enum with tagged and untagged variants,
// and a "tagged" inner enum.
//
// Wikipedia suggestions will deserialize successfully into the tagged
// variant. AMP suggestions will try the tagged variant, fail, and fall
// back to the untagged variant.
//
// This approach works around serde-rs/serde#912.
#[derive(Deserialize)]
#[serde(untagged)]
enum MaybeTagged {
Tagged(Tagged),
Untagged(DownloadedAmpSuggestion),
}
#[derive(Deserialize)]
#[serde(tag = "advertiser")]
enum Tagged {
#[serde(rename = "Wikipedia")]
Wikipedia(DownloadedWikipediaSuggestion),
}
Ok(match MaybeTagged::deserialize(deserializer)? {
MaybeTagged::Tagged(Tagged::Wikipedia(wikipedia)) => Self::Wikipedia(wikipedia),
MaybeTagged::Untagged(amp) => Self::Amp(amp),
})
}
}

View file

@ -6,7 +6,7 @@
use rusqlite::{Connection, Transaction};
use sql_support::open_database::{self, ConnectionInitializer};
pub const VERSION: u32 = 1;
pub const VERSION: u32 = 3;
pub const SQL: &str = "
CREATE TABLE meta(
@ -26,14 +26,26 @@ pub const SQL: &str = "
CREATE TABLE suggestions(
id INTEGER PRIMARY KEY,
record_id TEXT NOT NULL,
block_id INTEGER NOT NULL,
advertiser TEXT NOT NULL,
iab_category TEXT NOT NULL,
provider INTEGER NOT NULL,
title TEXT NOT NULL,
url TEXT NOT NULL,
url TEXT NOT NULL
);
CREATE TABLE amp_custom_details(
suggestion_id INTEGER PRIMARY KEY,
advertiser TEXT NOT NULL,
block_id INTEGER NOT NULL,
iab_category TEXT NOT NULL,
impression_url TEXT NOT NULL,
click_url TEXT NOT NULL,
icon_id TEXT NOT NULL,
impression_url TEXT,
click_url TEXT
FOREIGN KEY(suggestion_id) REFERENCES suggestions(id)
ON DELETE CASCADE
);
CREATE TABLE wikipedia_custom_details(
suggestion_id INTEGER PRIMARY KEY REFERENCES suggestions(id) ON DELETE CASCADE,
icon_id TEXT NOT NULL
);
CREATE INDEX suggestions_record_id ON suggestions(record_id);
@ -71,6 +83,14 @@ impl ConnectionInitializer for SuggestConnectionInitializer {
}
fn upgrade_from(&self, _db: &Transaction<'_>, version: u32) -> open_database::Result<()> {
Err(open_database::Error::IncompatibleVersion(version))
match version {
1..=2 => {
// These schema versions were used during development, and never
// shipped in any applications. Treat these databases as
// corrupt, so that they'll be replaced.
Err(open_database::Error::Corrupt)
}
_ => Err(open_database::Error::IncompatibleVersion(version)),
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -15,17 +15,31 @@ interface SuggestApiError {
Other(string reason);
};
dictionary Suggestion {
i64 block_id;
string advertiser;
string iab_category;
boolean is_sponsored;
string full_keyword;
string title;
string url;
sequence<u8>? icon;
string? impression_url;
string? click_url;
enum SuggestionProvider {
"Amp",
"Wikipedia",
};
[Enum]
interface Suggestion {
Amp(
string title,
string url,
sequence<u8>? icon,
string full_keyword,
i64 block_id,
string advertiser,
string iab_category,
string impression_url,
string click_url
);
Wikipedia(
string title,
string url,
sequence<u8>? icon,
string full_keyword
);
};
dictionary SuggestionQuery {

View file

@ -0,0 +1,33 @@
/* 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/.
*/
/// A suggestion from the database to show in the address bar.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Suggestion {
Amp {
title: String,
url: String,
icon: Option<Vec<u8>>,
full_keyword: String,
block_id: i64,
advertiser: String,
iab_category: String,
impression_url: String,
click_url: String,
},
Wikipedia {
title: String,
url: String,
icon: Option<Vec<u8>>,
full_keyword: String,
},
}
impl Suggestion {
/// Returns `true` if the suggestion is sponsored.
pub(crate) fn is_sponsored(&self) -> bool {
matches!(self, Self::Amp { .. })
}
}

View file

@ -578,244 +578,6 @@ export class FfiConverterTypeSuggestIngestionConstraints extends FfiConverterArr
}
}
export class Suggestion {
constructor(blockId,advertiser,iabCategory,isSponsored,fullKeyword,title,url,icon,impressionUrl,clickUrl) {
try {
FfiConverterI64.checkType(blockId)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("blockId");
}
throw e;
}
try {
FfiConverterString.checkType(advertiser)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("advertiser");
}
throw e;
}
try {
FfiConverterString.checkType(iabCategory)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("iabCategory");
}
throw e;
}
try {
FfiConverterBool.checkType(isSponsored)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("isSponsored");
}
throw e;
}
try {
FfiConverterString.checkType(fullKeyword)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("fullKeyword");
}
throw e;
}
try {
FfiConverterString.checkType(title)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("title");
}
throw e;
}
try {
FfiConverterString.checkType(url)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("url");
}
throw e;
}
try {
FfiConverterOptionalSequenceu8.checkType(icon)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("icon");
}
throw e;
}
try {
FfiConverterOptionalstring.checkType(impressionUrl)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("impressionUrl");
}
throw e;
}
try {
FfiConverterOptionalstring.checkType(clickUrl)
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart("clickUrl");
}
throw e;
}
this.blockId = blockId;
this.advertiser = advertiser;
this.iabCategory = iabCategory;
this.isSponsored = isSponsored;
this.fullKeyword = fullKeyword;
this.title = title;
this.url = url;
this.icon = icon;
this.impressionUrl = impressionUrl;
this.clickUrl = clickUrl;
}
equals(other) {
return (
this.blockId == other.blockId &&
this.advertiser == other.advertiser &&
this.iabCategory == other.iabCategory &&
this.isSponsored == other.isSponsored &&
this.fullKeyword == other.fullKeyword &&
this.title == other.title &&
this.url == other.url &&
this.icon == other.icon &&
this.impressionUrl == other.impressionUrl &&
this.clickUrl == other.clickUrl
)
}
}
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestion extends FfiConverterArrayBuffer {
static read(dataStream) {
return new Suggestion(
FfiConverterI64.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterBool.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterOptionalSequenceu8.read(dataStream),
FfiConverterOptionalstring.read(dataStream),
FfiConverterOptionalstring.read(dataStream)
);
}
static write(dataStream, value) {
FfiConverterI64.write(dataStream, value.blockId);
FfiConverterString.write(dataStream, value.advertiser);
FfiConverterString.write(dataStream, value.iabCategory);
FfiConverterBool.write(dataStream, value.isSponsored);
FfiConverterString.write(dataStream, value.fullKeyword);
FfiConverterString.write(dataStream, value.title);
FfiConverterString.write(dataStream, value.url);
FfiConverterOptionalSequenceu8.write(dataStream, value.icon);
FfiConverterOptionalstring.write(dataStream, value.impressionUrl);
FfiConverterOptionalstring.write(dataStream, value.clickUrl);
}
static computeSize(value) {
let totalSize = 0;
totalSize += FfiConverterI64.computeSize(value.blockId);
totalSize += FfiConverterString.computeSize(value.advertiser);
totalSize += FfiConverterString.computeSize(value.iabCategory);
totalSize += FfiConverterBool.computeSize(value.isSponsored);
totalSize += FfiConverterString.computeSize(value.fullKeyword);
totalSize += FfiConverterString.computeSize(value.title);
totalSize += FfiConverterString.computeSize(value.url);
totalSize += FfiConverterOptionalSequenceu8.computeSize(value.icon);
totalSize += FfiConverterOptionalstring.computeSize(value.impressionUrl);
totalSize += FfiConverterOptionalstring.computeSize(value.clickUrl);
return totalSize
}
static checkType(value) {
super.checkType(value);
try {
FfiConverterI64.checkType(value.blockId);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".blockId");
}
throw e;
}
try {
FfiConverterString.checkType(value.advertiser);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".advertiser");
}
throw e;
}
try {
FfiConverterString.checkType(value.iabCategory);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".iabCategory");
}
throw e;
}
try {
FfiConverterBool.checkType(value.isSponsored);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".isSponsored");
}
throw e;
}
try {
FfiConverterString.checkType(value.fullKeyword);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".fullKeyword");
}
throw e;
}
try {
FfiConverterString.checkType(value.title);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".title");
}
throw e;
}
try {
FfiConverterString.checkType(value.url);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".url");
}
throw e;
}
try {
FfiConverterOptionalSequenceu8.checkType(value.icon);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".icon");
}
throw e;
}
try {
FfiConverterOptionalstring.checkType(value.impressionUrl);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".impressionUrl");
}
throw e;
}
try {
FfiConverterOptionalstring.checkType(value.clickUrl);
} catch (e) {
if (e instanceof UniFFITypeError) {
e.addItemDescriptionPart(".clickUrl");
}
throw e;
}
}
}
export class SuggestionQuery {
constructor(keyword,includeSponsored,includeNonSponsored) {
try {
@ -960,6 +722,177 @@ export class FfiConverterTypeSuggestApiError extends FfiConverterArrayBuffer {
static errorClass = SuggestApiError;
}
export class Suggestion {}
Suggestion.Amp = class extends Suggestion{
constructor(
title,
url,
icon,
fullKeyword,
blockId,
advertiser,
iabCategory,
impressionUrl,
clickUrl
) {
super();
this.title = title;
this.url = url;
this.icon = icon;
this.fullKeyword = fullKeyword;
this.blockId = blockId;
this.advertiser = advertiser;
this.iabCategory = iabCategory;
this.impressionUrl = impressionUrl;
this.clickUrl = clickUrl;
}
}
Suggestion.Wikipedia = class extends Suggestion{
constructor(
title,
url,
icon,
fullKeyword
) {
super();
this.title = title;
this.url = url;
this.icon = icon;
this.fullKeyword = fullKeyword;
}
}
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestion extends FfiConverterArrayBuffer {
static read(dataStream) {
switch (dataStream.readInt32()) {
case 1:
return new Suggestion.Amp(
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterOptionalSequenceu8.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterI64.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream)
);
case 2:
return new Suggestion.Wikipedia(
FfiConverterString.read(dataStream),
FfiConverterString.read(dataStream),
FfiConverterOptionalSequenceu8.read(dataStream),
FfiConverterString.read(dataStream)
);
default:
return new Error("Unknown Suggestion variant");
}
}
static write(dataStream, value) {
if (value instanceof Suggestion.Amp) {
dataStream.writeInt32(1);
FfiConverterString.write(dataStream, value.title);
FfiConverterString.write(dataStream, value.url);
FfiConverterOptionalSequenceu8.write(dataStream, value.icon);
FfiConverterString.write(dataStream, value.fullKeyword);
FfiConverterI64.write(dataStream, value.blockId);
FfiConverterString.write(dataStream, value.advertiser);
FfiConverterString.write(dataStream, value.iabCategory);
FfiConverterString.write(dataStream, value.impressionUrl);
FfiConverterString.write(dataStream, value.clickUrl);
return;
}
if (value instanceof Suggestion.Wikipedia) {
dataStream.writeInt32(2);
FfiConverterString.write(dataStream, value.title);
FfiConverterString.write(dataStream, value.url);
FfiConverterOptionalSequenceu8.write(dataStream, value.icon);
FfiConverterString.write(dataStream, value.fullKeyword);
return;
}
return new Error("Unknown Suggestion variant");
}
static computeSize(value) {
// Size of the Int indicating the variant
let totalSize = 4;
if (value instanceof Suggestion.Amp) {
totalSize += FfiConverterString.computeSize(value.title);
totalSize += FfiConverterString.computeSize(value.url);
totalSize += FfiConverterOptionalSequenceu8.computeSize(value.icon);
totalSize += FfiConverterString.computeSize(value.fullKeyword);
totalSize += FfiConverterI64.computeSize(value.blockId);
totalSize += FfiConverterString.computeSize(value.advertiser);
totalSize += FfiConverterString.computeSize(value.iabCategory);
totalSize += FfiConverterString.computeSize(value.impressionUrl);
totalSize += FfiConverterString.computeSize(value.clickUrl);
return totalSize;
}
if (value instanceof Suggestion.Wikipedia) {
totalSize += FfiConverterString.computeSize(value.title);
totalSize += FfiConverterString.computeSize(value.url);
totalSize += FfiConverterOptionalSequenceu8.computeSize(value.icon);
totalSize += FfiConverterString.computeSize(value.fullKeyword);
return totalSize;
}
return new Error("Unknown Suggestion variant");
}
static checkType(value) {
if (!(value instanceof Suggestion)) {
throw new UniFFITypeError(`${value} is not a subclass instance of Suggestion`);
}
}
}
export const SuggestionProvider = {
AMP: 1,
WIKIPEDIA: 2,
};
Object.freeze(SuggestionProvider);
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestionProvider extends FfiConverterArrayBuffer {
static read(dataStream) {
switch (dataStream.readInt32()) {
case 1:
return SuggestionProvider.AMP
case 2:
return SuggestionProvider.WIKIPEDIA
default:
return new Error("Unknown SuggestionProvider variant");
}
}
static write(dataStream, value) {
if (value === SuggestionProvider.AMP) {
dataStream.writeInt32(1);
return;
}
if (value === SuggestionProvider.WIKIPEDIA) {
dataStream.writeInt32(2);
return;
}
return new Error("Unknown SuggestionProvider variant");
}
static computeSize(value) {
return 4;
}
static checkType(value) {
if (!Number.isInteger(value) || value < 1 || value > 2) {
throw new UniFFITypeError(`${value} is not a valid value for SuggestionProvider`);
}
}
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalu64 extends FfiConverterArrayBuffer {
static checkType(value) {
@ -997,43 +930,6 @@ export class FfiConverterOptionalu64 extends FfiConverterArrayBuffer {
}
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalstring extends FfiConverterArrayBuffer {
static checkType(value) {
if (value !== undefined && value !== null) {
FfiConverterString.checkType(value)
}
}
static read(dataStream) {
const code = dataStream.readUint8(0);
switch (code) {
case 0:
return null
case 1:
return FfiConverterString.read(dataStream)
default:
throw UniFFIError(`Unexpected code: ${code}`);
}
}
static write(dataStream, value) {
if (value === null || value === undefined) {
dataStream.writeUint8(0);
return;
}
dataStream.writeUint8(1);
FfiConverterString.write(dataStream, value)
}
static computeSize(value) {
if (value === null || value === undefined) {
return 1;
}
return 1 + FfiConverterString.computeSize(value)
}
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalSequenceu8 extends FfiConverterArrayBuffer {
static checkType(value) {

View file

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES += [
"generated/RustRemoteSettings.sys.mjs",
"generated/RustSuggest.sys.mjs",
"generated/RustSync15.sys.mjs",
"generated/RustTabs.sys.mjs",

View file

@ -4,6 +4,12 @@ main = [
"log_even_numbers_main_thread",
]
[remote_settings.receiver_thread]
default = "worker"
main = [
"RemoteSettings",
]
[suggest.receiver_thread]
default = "worker"
main = [

View file

@ -377,7 +377,7 @@ export function add(a,b) {
throw e;
}
return UniFFIScaffolding.callAsync(
25, // arithmetic:uniffi_arithmetic_fn_func_add
29, // arithmetic:uniffi_arithmetic_fn_func_add
FfiConverterU64.lower(a),
FfiConverterU64.lower(b),
)
@ -411,7 +411,7 @@ export function sub(a,b) {
throw e;
}
return UniFFIScaffolding.callAsync(
26, // arithmetic:uniffi_arithmetic_fn_func_sub
30, // arithmetic:uniffi_arithmetic_fn_func_sub
FfiConverterU64.lower(a),
FfiConverterU64.lower(b),
)
@ -445,7 +445,7 @@ export function div(dividend,divisor) {
throw e;
}
return UniFFIScaffolding.callAsync(
27, // arithmetic:uniffi_arithmetic_fn_func_div
31, // arithmetic:uniffi_arithmetic_fn_func_div
FfiConverterU64.lower(dividend),
FfiConverterU64.lower(divisor),
)
@ -479,7 +479,7 @@ export function equal(a,b) {
throw e;
}
return UniFFIScaffolding.callAsync(
28, // arithmetic:uniffi_arithmetic_fn_func_equal
32, // arithmetic:uniffi_arithmetic_fn_func_equal
FfiConverterU64.lower(a),
FfiConverterU64.lower(b),
)

View file

@ -452,7 +452,7 @@ export function getCustomTypesDemo(demo) {
throw e;
}
return UniFFIScaffolding.callAsync(
112, // custom_types:uniffi_custom_types_fn_func_get_custom_types_demo
116, // custom_types:uniffi_custom_types_fn_func_get_custom_types_demo
FfiConverterOptionalTypeCustomTypesDemo.lower(demo),
)
}

View file

@ -344,7 +344,7 @@ export function gradient(value) {
throw e;
}
return UniFFIScaffolding.callAsync(
113, // external_types:uniffi_external_types_fn_func_gradient
117, // external_types:uniffi_external_types_fn_func_gradient
FfiConverterOptionalTypeLine.lower(value),
)
}

View file

@ -596,7 +596,7 @@ export function logEvenNumbers(logger,items) {
throw e;
}
return UniFFIScaffolding.callAsync(
110, // fixture_callbacks:uniffi_fixture_callbacks_fn_func_log_even_numbers
114, // fixture_callbacks:uniffi_fixture_callbacks_fn_func_log_even_numbers
FfiConverterCallbackInterfaceLogger.lower(logger),
FfiConverterSequencei32.lower(items),
)
@ -630,7 +630,7 @@ export function logEvenNumbersMainThread(logger,items) {
throw e;
}
return UniFFIScaffolding.callSync(
111, // fixture_callbacks:uniffi_fixture_callbacks_fn_func_log_even_numbers_main_thread
115, // fixture_callbacks:uniffi_fixture_callbacks_fn_func_log_even_numbers_main_thread
FfiConverterCallbackInterfaceLogger.lower(logger),
FfiConverterSequencei32.lower(items),
)

View file

@ -468,7 +468,7 @@ export function gradient(ln) {
throw e;
}
return UniFFIScaffolding.callAsync(
23, // geometry:uniffi_geometry_fn_func_gradient
27, // geometry:uniffi_geometry_fn_func_gradient
FfiConverterTypeLine.lower(ln),
)
}
@ -501,7 +501,7 @@ export function intersection(ln1,ln2) {
throw e;
}
return UniFFIScaffolding.callAsync(
24, // geometry:uniffi_geometry_fn_func_intersection
28, // geometry:uniffi_geometry_fn_func_intersection
FfiConverterTypeLine.lower(ln1),
FfiConverterTypeLine.lower(ln2),
)

View file

@ -158,7 +158,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
readPointerRetourneur() {
const pointerId = 3; // rondpoint:Retourneur
const pointerId = 4; // rondpoint:Retourneur
const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
this.pos += 8;
return res;
@ -168,7 +168,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
writePointerRetourneur(value) {
const pointerId = 3; // rondpoint:Retourneur
const pointerId = 4; // rondpoint:Retourneur
UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
this.pos += 8;
}
@ -178,7 +178,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
readPointerStringifier() {
const pointerId = 4; // rondpoint:Stringifier
const pointerId = 5; // rondpoint:Stringifier
const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
this.pos += 8;
return res;
@ -188,7 +188,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
writePointerStringifier(value) {
const pointerId = 4; // rondpoint:Stringifier
const pointerId = 5; // rondpoint:Stringifier
UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
this.pos += 8;
}
@ -198,7 +198,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
readPointerOptionneur() {
const pointerId = 5; // rondpoint:Optionneur
const pointerId = 6; // rondpoint:Optionneur
const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
this.pos += 8;
return res;
@ -208,7 +208,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
writePointerOptionneur(value) {
const pointerId = 5; // rondpoint:Optionneur
const pointerId = 6; // rondpoint:Optionneur
UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
this.pos += 8;
}
@ -620,7 +620,7 @@ export class Optionneur {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
58, // rondpoint:uniffi_rondpoint_fn_constructor_optionneur_new
62, // rondpoint:uniffi_rondpoint_fn_constructor_optionneur_new
)
}
try {
@ -642,7 +642,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
59, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_boolean
63, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_boolean
FfiConverterTypeOptionneur.lower(this),
FfiConverterBool.lower(value),
)
@ -667,7 +667,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
60, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_string
64, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_string
FfiConverterTypeOptionneur.lower(this),
FfiConverterString.lower(value),
)
@ -692,7 +692,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
61, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_sequence
65, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_sequence
FfiConverterTypeOptionneur.lower(this),
FfiConverterSequencestring.lower(value),
)
@ -717,7 +717,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
62, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_null
66, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_null
FfiConverterTypeOptionneur.lower(this),
FfiConverterOptionalstring.lower(value),
)
@ -742,7 +742,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
63, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_zero
67, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_zero
FfiConverterTypeOptionneur.lower(this),
FfiConverterOptionali32.lower(value),
)
@ -767,7 +767,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
64, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u8_dec
68, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u8_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterU8.lower(value),
)
@ -792,7 +792,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
65, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i8_dec
69, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i8_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterI8.lower(value),
)
@ -817,7 +817,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
66, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u16_dec
70, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u16_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterU16.lower(value),
)
@ -842,7 +842,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
67, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i16_dec
71, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i16_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterI16.lower(value),
)
@ -867,7 +867,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
68, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_dec
72, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterU32.lower(value),
)
@ -892,7 +892,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
69, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i32_dec
73, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i32_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterI32.lower(value),
)
@ -917,7 +917,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
70, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u64_dec
74, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u64_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterU64.lower(value),
)
@ -942,7 +942,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
71, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i64_dec
75, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i64_dec
FfiConverterTypeOptionneur.lower(this),
FfiConverterI64.lower(value),
)
@ -967,7 +967,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
72, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u8_hex
76, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u8_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterU8.lower(value),
)
@ -992,7 +992,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
73, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i8_hex
77, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i8_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterI8.lower(value),
)
@ -1017,7 +1017,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
74, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u16_hex
78, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u16_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterU16.lower(value),
)
@ -1042,7 +1042,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
75, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i16_hex
79, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i16_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterI16.lower(value),
)
@ -1067,7 +1067,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
76, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_hex
80, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterU32.lower(value),
)
@ -1092,7 +1092,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
77, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i32_hex
81, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i32_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterI32.lower(value),
)
@ -1117,7 +1117,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
78, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u64_hex
82, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u64_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterU64.lower(value),
)
@ -1142,7 +1142,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
79, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i64_hex
83, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_i64_hex
FfiConverterTypeOptionneur.lower(this),
FfiConverterI64.lower(value),
)
@ -1167,7 +1167,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
80, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_oct
84, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_u32_oct
FfiConverterTypeOptionneur.lower(this),
FfiConverterU32.lower(value),
)
@ -1192,7 +1192,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
81, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_f32
85, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_f32
FfiConverterTypeOptionneur.lower(this),
FfiConverterF32.lower(value),
)
@ -1217,7 +1217,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
82, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_f64
86, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_f64
FfiConverterTypeOptionneur.lower(this),
FfiConverterF64.lower(value),
)
@ -1242,7 +1242,7 @@ export class Optionneur {
throw e;
}
return UniFFIScaffolding.callAsync(
83, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_enum
87, // rondpoint:uniffi_rondpoint_fn_method_optionneur_sinon_enum
FfiConverterTypeOptionneur.lower(this),
FfiConverterTypeEnumeration.lower(value),
)
@ -1305,7 +1305,7 @@ export class Retourneur {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
29, // rondpoint:uniffi_rondpoint_fn_constructor_retourneur_new
33, // rondpoint:uniffi_rondpoint_fn_constructor_retourneur_new
)
}
try {
@ -1327,7 +1327,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
30, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i8
34, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i8
FfiConverterTypeRetourneur.lower(this),
FfiConverterI8.lower(value),
)
@ -1352,7 +1352,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
31, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u8
35, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u8
FfiConverterTypeRetourneur.lower(this),
FfiConverterU8.lower(value),
)
@ -1377,7 +1377,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
32, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i16
36, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i16
FfiConverterTypeRetourneur.lower(this),
FfiConverterI16.lower(value),
)
@ -1402,7 +1402,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
33, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u16
37, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u16
FfiConverterTypeRetourneur.lower(this),
FfiConverterU16.lower(value),
)
@ -1427,7 +1427,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
34, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i32
38, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i32
FfiConverterTypeRetourneur.lower(this),
FfiConverterI32.lower(value),
)
@ -1452,7 +1452,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
35, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u32
39, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u32
FfiConverterTypeRetourneur.lower(this),
FfiConverterU32.lower(value),
)
@ -1477,7 +1477,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
36, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i64
40, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_i64
FfiConverterTypeRetourneur.lower(this),
FfiConverterI64.lower(value),
)
@ -1502,7 +1502,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
37, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u64
41, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_u64
FfiConverterTypeRetourneur.lower(this),
FfiConverterU64.lower(value),
)
@ -1527,7 +1527,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
38, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_float
42, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_float
FfiConverterTypeRetourneur.lower(this),
FfiConverterF32.lower(value),
)
@ -1552,7 +1552,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
39, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_double
43, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_double
FfiConverterTypeRetourneur.lower(this),
FfiConverterF64.lower(value),
)
@ -1577,7 +1577,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
40, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_boolean
44, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_boolean
FfiConverterTypeRetourneur.lower(this),
FfiConverterBool.lower(value),
)
@ -1602,7 +1602,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
41, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_string
45, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_string
FfiConverterTypeRetourneur.lower(this),
FfiConverterString.lower(value),
)
@ -1627,7 +1627,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
42, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_nombres_signes
46, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_nombres_signes
FfiConverterTypeRetourneur.lower(this),
FfiConverterTypeDictionnaireNombresSignes.lower(value),
)
@ -1652,7 +1652,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
43, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_nombres
47, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_nombres
FfiConverterTypeRetourneur.lower(this),
FfiConverterTypeDictionnaireNombres.lower(value),
)
@ -1677,7 +1677,7 @@ export class Retourneur {
throw e;
}
return UniFFIScaffolding.callAsync(
44, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_optionneur_dictionnaire
48, // rondpoint:uniffi_rondpoint_fn_method_retourneur_identique_optionneur_dictionnaire
FfiConverterTypeRetourneur.lower(this),
FfiConverterTypeOptionneurDictionnaire.lower(value),
)
@ -1740,7 +1740,7 @@ export class Stringifier {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
45, // rondpoint:uniffi_rondpoint_fn_constructor_stringifier_new
49, // rondpoint:uniffi_rondpoint_fn_constructor_stringifier_new
)
}
try {
@ -1762,7 +1762,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
46, // rondpoint:uniffi_rondpoint_fn_method_stringifier_well_known_string
50, // rondpoint:uniffi_rondpoint_fn_method_stringifier_well_known_string
FfiConverterTypeStringifier.lower(this),
FfiConverterString.lower(value),
)
@ -1787,7 +1787,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
47, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i8
51, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i8
FfiConverterTypeStringifier.lower(this),
FfiConverterI8.lower(value),
)
@ -1812,7 +1812,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
48, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u8
52, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u8
FfiConverterTypeStringifier.lower(this),
FfiConverterU8.lower(value),
)
@ -1837,7 +1837,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
49, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i16
53, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i16
FfiConverterTypeStringifier.lower(this),
FfiConverterI16.lower(value),
)
@ -1862,7 +1862,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
50, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u16
54, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u16
FfiConverterTypeStringifier.lower(this),
FfiConverterU16.lower(value),
)
@ -1887,7 +1887,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
51, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i32
55, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i32
FfiConverterTypeStringifier.lower(this),
FfiConverterI32.lower(value),
)
@ -1912,7 +1912,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
52, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u32
56, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u32
FfiConverterTypeStringifier.lower(this),
FfiConverterU32.lower(value),
)
@ -1937,7 +1937,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
53, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i64
57, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_i64
FfiConverterTypeStringifier.lower(this),
FfiConverterI64.lower(value),
)
@ -1962,7 +1962,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
54, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u64
58, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_u64
FfiConverterTypeStringifier.lower(this),
FfiConverterU64.lower(value),
)
@ -1987,7 +1987,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
55, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_float
59, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_float
FfiConverterTypeStringifier.lower(this),
FfiConverterF32.lower(value),
)
@ -2012,7 +2012,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
56, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_double
60, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_double
FfiConverterTypeStringifier.lower(this),
FfiConverterF64.lower(value),
)
@ -2037,7 +2037,7 @@ export class Stringifier {
throw e;
}
return UniFFIScaffolding.callAsync(
57, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_boolean
61, // rondpoint:uniffi_rondpoint_fn_method_stringifier_to_string_boolean
FfiConverterTypeStringifier.lower(this),
FfiConverterBool.lower(value),
)
@ -3257,7 +3257,7 @@ export function copieDictionnaire(d) {
throw e;
}
return UniFFIScaffolding.callAsync(
84, // rondpoint:uniffi_rondpoint_fn_func_copie_dictionnaire
88, // rondpoint:uniffi_rondpoint_fn_func_copie_dictionnaire
FfiConverterTypeDictionnaire.lower(d),
)
}
@ -3282,7 +3282,7 @@ export function copieEnumeration(e) {
throw e;
}
return UniFFIScaffolding.callAsync(
85, // rondpoint:uniffi_rondpoint_fn_func_copie_enumeration
89, // rondpoint:uniffi_rondpoint_fn_func_copie_enumeration
FfiConverterTypeEnumeration.lower(e),
)
}
@ -3307,7 +3307,7 @@ export function copieEnumerations(e) {
throw e;
}
return UniFFIScaffolding.callAsync(
86, // rondpoint:uniffi_rondpoint_fn_func_copie_enumerations
90, // rondpoint:uniffi_rondpoint_fn_func_copie_enumerations
FfiConverterSequenceTypeEnumeration.lower(e),
)
}
@ -3332,7 +3332,7 @@ export function copieCarte(c) {
throw e;
}
return UniFFIScaffolding.callAsync(
87, // rondpoint:uniffi_rondpoint_fn_func_copie_carte
91, // rondpoint:uniffi_rondpoint_fn_func_copie_carte
FfiConverterMapStringTypeEnumerationAvecDonnees.lower(c),
)
}
@ -3357,7 +3357,7 @@ export function switcheroo(b) {
throw e;
}
return UniFFIScaffolding.callAsync(
88, // rondpoint:uniffi_rondpoint_fn_func_switcheroo
92, // rondpoint:uniffi_rondpoint_fn_func_switcheroo
FfiConverterBool.lower(b),
)
}

View file

@ -158,7 +158,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
readPointerSprite() {
const pointerId = 6; // sprites:Sprite
const pointerId = 7; // sprites:Sprite
const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
this.pos += 8;
return res;
@ -168,7 +168,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
writePointerSprite(value) {
const pointerId = 6; // sprites:Sprite
const pointerId = 7; // sprites:Sprite
UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
this.pos += 8;
}
@ -325,7 +325,7 @@ export class Sprite {
throw e;
}
return UniFFIScaffolding.callAsync(
89, // sprites:uniffi_sprites_fn_constructor_sprite_new
93, // sprites:uniffi_sprites_fn_constructor_sprite_new
FfiConverterOptionalTypePoint.lower(initialPosition),
)
}
@ -361,7 +361,7 @@ export class Sprite {
throw e;
}
return UniFFIScaffolding.callAsync(
90, // sprites:uniffi_sprites_fn_constructor_sprite_new_relative_to
94, // sprites:uniffi_sprites_fn_constructor_sprite_new_relative_to
FfiConverterTypePoint.lower(reference),
FfiConverterTypeVector.lower(direction),
)
@ -377,7 +377,7 @@ export class Sprite {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
91, // sprites:uniffi_sprites_fn_method_sprite_get_position
95, // sprites:uniffi_sprites_fn_method_sprite_get_position
FfiConverterTypeSprite.lower(this),
)
}
@ -401,7 +401,7 @@ export class Sprite {
throw e;
}
return UniFFIScaffolding.callAsync(
92, // sprites:uniffi_sprites_fn_method_sprite_move_to
96, // sprites:uniffi_sprites_fn_method_sprite_move_to
FfiConverterTypeSprite.lower(this),
FfiConverterTypePoint.lower(position),
)
@ -426,7 +426,7 @@ export class Sprite {
throw e;
}
return UniFFIScaffolding.callAsync(
93, // sprites:uniffi_sprites_fn_method_sprite_move_by
97, // sprites:uniffi_sprites_fn_method_sprite_move_by
FfiConverterTypeSprite.lower(this),
FfiConverterTypeVector.lower(direction),
)
@ -668,7 +668,7 @@ export function translate(position,direction) {
throw e;
}
return UniFFIScaffolding.callAsync(
94, // sprites:uniffi_sprites_fn_func_translate
98, // sprites:uniffi_sprites_fn_func_translate
FfiConverterTypePoint.lower(position),
FfiConverterTypeVector.lower(direction),
)

View file

@ -158,7 +158,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
readPointerTodoList() {
const pointerId = 7; // todolist:TodoList
const pointerId = 8; // todolist:TodoList
const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
this.pos += 8;
return res;
@ -168,7 +168,7 @@ class ArrayBufferDataStream {
// UniFFI Pointers are **always** 8 bytes long. That is enforced
// by the C++ and Rust Scaffolding code.
writePointerTodoList(value) {
const pointerId = 7; // todolist:TodoList
const pointerId = 8; // todolist:TodoList
UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
this.pos += 8;
}
@ -298,7 +298,7 @@ export class TodoList {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
95, // todolist:uniffi_todolist_fn_constructor_todolist_new
99, // todolist:uniffi_todolist_fn_constructor_todolist_new
)
}
try {
@ -320,7 +320,7 @@ export class TodoList {
throw e;
}
return UniFFIScaffolding.callAsync(
96, // todolist:uniffi_todolist_fn_method_todolist_add_item
100, // todolist:uniffi_todolist_fn_method_todolist_add_item
FfiConverterTypeTodoList.lower(this),
FfiConverterString.lower(todo),
)
@ -345,7 +345,7 @@ export class TodoList {
throw e;
}
return UniFFIScaffolding.callAsync(
97, // todolist:uniffi_todolist_fn_method_todolist_add_entry
101, // todolist:uniffi_todolist_fn_method_todolist_add_entry
FfiConverterTypeTodoList.lower(this),
FfiConverterTypeTodoEntry.lower(entry),
)
@ -362,7 +362,7 @@ export class TodoList {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
98, // todolist:uniffi_todolist_fn_method_todolist_get_entries
102, // todolist:uniffi_todolist_fn_method_todolist_get_entries
FfiConverterTypeTodoList.lower(this),
)
}
@ -378,7 +378,7 @@ export class TodoList {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
99, // todolist:uniffi_todolist_fn_method_todolist_get_items
103, // todolist:uniffi_todolist_fn_method_todolist_get_items
FfiConverterTypeTodoList.lower(this),
)
}
@ -402,7 +402,7 @@ export class TodoList {
throw e;
}
return UniFFIScaffolding.callAsync(
100, // todolist:uniffi_todolist_fn_method_todolist_add_entries
104, // todolist:uniffi_todolist_fn_method_todolist_add_entries
FfiConverterTypeTodoList.lower(this),
FfiConverterSequenceTypeTodoEntry.lower(entries),
)
@ -427,7 +427,7 @@ export class TodoList {
throw e;
}
return UniFFIScaffolding.callAsync(
101, // todolist:uniffi_todolist_fn_method_todolist_add_items
105, // todolist:uniffi_todolist_fn_method_todolist_add_items
FfiConverterTypeTodoList.lower(this),
FfiConverterSequencestring.lower(items),
)
@ -444,7 +444,7 @@ export class TodoList {
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
const functionCall = () => {
return UniFFIScaffolding.callAsync(
102, // todolist:uniffi_todolist_fn_method_todolist_get_last_entry
106, // todolist:uniffi_todolist_fn_method_todolist_get_last_entry
FfiConverterTypeTodoList.lower(this),
)
}
@ -460,7 +460,7 @@ export class TodoList {
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
const functionCall = () => {
return UniFFIScaffolding.callAsync(
103, // todolist:uniffi_todolist_fn_method_todolist_get_last
107, // todolist:uniffi_todolist_fn_method_todolist_get_last
FfiConverterTypeTodoList.lower(this),
)
}
@ -476,7 +476,7 @@ export class TodoList {
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
const functionCall = () => {
return UniFFIScaffolding.callAsync(
104, // todolist:uniffi_todolist_fn_method_todolist_get_first
108, // todolist:uniffi_todolist_fn_method_todolist_get_first
FfiConverterTypeTodoList.lower(this),
)
}
@ -500,7 +500,7 @@ export class TodoList {
throw e;
}
return UniFFIScaffolding.callAsync(
105, // todolist:uniffi_todolist_fn_method_todolist_clear_item
109, // todolist:uniffi_todolist_fn_method_todolist_clear_item
FfiConverterTypeTodoList.lower(this),
FfiConverterString.lower(todo),
)
@ -517,7 +517,7 @@ export class TodoList {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
106, // todolist:uniffi_todolist_fn_method_todolist_make_default
110, // todolist:uniffi_todolist_fn_method_todolist_make_default
FfiConverterTypeTodoList.lower(this),
)
}
@ -865,7 +865,7 @@ export function getDefaultList() {
const liftError = null;
const functionCall = () => {
return UniFFIScaffolding.callAsync(
107, // todolist:uniffi_todolist_fn_func_get_default_list
111, // todolist:uniffi_todolist_fn_func_get_default_list
)
}
try {
@ -889,7 +889,7 @@ export function setDefaultList(list) {
throw e;
}
return UniFFIScaffolding.callAsync(
108, // todolist:uniffi_todolist_fn_func_set_default_list
112, // todolist:uniffi_todolist_fn_func_set_default_list
FfiConverterTypeTodoList.lower(list),
)
}
@ -914,7 +914,7 @@ export function createEntryWith(todo) {
throw e;
}
return UniFFIScaffolding.callAsync(
109, // todolist:uniffi_todolist_fn_func_create_entry_with
113, // todolist:uniffi_todolist_fn_func_create_entry_with
FfiConverterString.lower(todo),
)
}

View file

@ -14,6 +14,7 @@ UDL_FILES = [
"third_party/rust/sync15/src/sync15.udl",
"third_party/rust/tabs/src/tabs.udl",
"third_party/rust/suggest/src/suggest.udl",
"third_party/rust/remote_settings/src/remote_settings.udl",
]
FIXTURE_UDL_FILES = [

File diff suppressed because it is too large Load diff

View file

@ -50,6 +50,11 @@ extern "C" {
void uniffi_suggest_fn_method_suggeststore_interrupt(void *, RustCallStatus*);
void uniffi_suggest_fn_method_suggeststore_ingest(void *, RustBuffer, RustCallStatus*);
void uniffi_suggest_fn_method_suggeststore_clear(void *, RustCallStatus*);
void uniffi_remote_settings_fn_free_remotesettings(void *, RustCallStatus*);
void * uniffi_remote_settings_fn_constructor_remotesettings_new(RustBuffer, RustCallStatus*);
RustBuffer uniffi_remote_settings_fn_method_remotesettings_get_records(void *, RustCallStatus*);
RustBuffer uniffi_remote_settings_fn_method_remotesettings_get_records_since(void *, uint64_t, RustCallStatus*);
void uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path(void *, RustBuffer, RustBuffer, RustCallStatus*);
}
// Define pointer types
@ -65,6 +70,10 @@ const static mozilla::uniffi::UniFFIPointerType kSuggestSuggestStorePointerType
"suggest::SuggestStore"_ns,
uniffi_suggest_fn_free_suggeststore
};
const static mozilla::uniffi::UniFFIPointerType kRemoteSettingsRemoteSettingsPointerType {
"remote_settings::RemoteSettings"_ns,
uniffi_remote_settings_fn_free_remotesettings
};
// Define the data we need per-callback interface
@ -171,6 +180,22 @@ Maybe<already_AddRefed<Promise>> UniFFICallAsync(const GlobalObject& aGlobal, ui
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingObjectConverter<&kSuggestSuggestStorePointerType>>;
return Some(CallHandler::CallAsync(uniffi_suggest_fn_method_suggeststore_clear, aGlobal, aArgs, "uniffi_suggest_fn_method_suggeststore_clear: "_ns, aError));
}
case 23: { // remote_settings:uniffi_remote_settings_fn_constructor_remotesettings_new
using CallHandler = ScaffoldingCallHandler<ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<RustBuffer>>;
return Some(CallHandler::CallAsync(uniffi_remote_settings_fn_constructor_remotesettings_new, aGlobal, aArgs, "uniffi_remote_settings_fn_constructor_remotesettings_new: "_ns, aError));
}
case 24: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_get_records
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>>;
return Some(CallHandler::CallAsync(uniffi_remote_settings_fn_method_remotesettings_get_records, aGlobal, aArgs, "uniffi_remote_settings_fn_method_remotesettings_get_records: "_ns, aError));
}
case 25: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_get_records_since
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<uint64_t>>;
return Some(CallHandler::CallAsync(uniffi_remote_settings_fn_method_remotesettings_get_records_since, aGlobal, aArgs, "uniffi_remote_settings_fn_method_remotesettings_get_records_since: "_ns, aError));
}
case 26: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<RustBuffer>, ScaffoldingConverter<RustBuffer>>;
return Some(CallHandler::CallAsync(uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path, aGlobal, aArgs, "uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path: "_ns, aError));
}
}
return Nothing();
}
@ -292,6 +317,26 @@ bool UniFFICallSync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<Sc
CallHandler::CallSync(uniffi_suggest_fn_method_suggeststore_clear, aGlobal, aArgs, aReturnValue, "uniffi_suggest_fn_method_suggeststore_clear: "_ns, aError);
return true;
}
case 23: { // remote_settings:uniffi_remote_settings_fn_constructor_remotesettings_new
using CallHandler = ScaffoldingCallHandler<ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<RustBuffer>>;
CallHandler::CallSync(uniffi_remote_settings_fn_constructor_remotesettings_new, aGlobal, aArgs, aReturnValue, "uniffi_remote_settings_fn_constructor_remotesettings_new: "_ns, aError);
return true;
}
case 24: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_get_records
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>>;
CallHandler::CallSync(uniffi_remote_settings_fn_method_remotesettings_get_records, aGlobal, aArgs, aReturnValue, "uniffi_remote_settings_fn_method_remotesettings_get_records: "_ns, aError);
return true;
}
case 25: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_get_records_since
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<uint64_t>>;
CallHandler::CallSync(uniffi_remote_settings_fn_method_remotesettings_get_records_since, aGlobal, aArgs, aReturnValue, "uniffi_remote_settings_fn_method_remotesettings_get_records_since: "_ns, aError);
return true;
}
case 26: { // remote_settings:uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingObjectConverter<&kRemoteSettingsRemoteSettingsPointerType>, ScaffoldingConverter<RustBuffer>, ScaffoldingConverter<RustBuffer>>;
CallHandler::CallSync(uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path, aGlobal, aArgs, aReturnValue, "uniffi_remote_settings_fn_method_remotesettings_download_attachment_to_path: "_ns, aError);
return true;
}
}
return false;
}
@ -311,6 +356,10 @@ Maybe<already_AddRefed<UniFFIPointer>> UniFFIReadPointer(const GlobalObject& aGl
type = &kSuggestSuggestStorePointerType;
break;
}
case 3: { // remote_settings:RemoteSettings
type = &kRemoteSettingsRemoteSettingsPointerType;
break;
}
default:
return Nothing();
}
@ -332,6 +381,10 @@ bool UniFFIWritePointer(const GlobalObject& aGlobal, uint64_t aId, const UniFFIP
type = &kSuggestSuggestStorePointerType;
break;
}
case 3: { // remote_settings:RemoteSettings
type = &kRemoteSettingsRemoteSettingsPointerType;
break;
}
default:
return false;
}