relevancy/
rs.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* 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 crate::{Error, Result};
use remote_settings::RemoteSettingsResponse;
use serde::Deserialize;
/// The Remote Settings collection name.
pub(crate) const REMOTE_SETTINGS_COLLECTION: &str = "content-relevance";

/// A trait for a client that downloads records from Remote Settings.
///
/// This trait lets tests use a mock client.
pub(crate) trait RelevancyRemoteSettingsClient {
    /// Fetches records from the Suggest Remote Settings collection.
    fn get_records(&self) -> Result<RemoteSettingsResponse>;

    /// Fetches a record's attachment from the Suggest Remote Settings
    /// collection.
    fn get_attachment(&self, location: &str) -> Result<Vec<u8>>;
}

impl RelevancyRemoteSettingsClient for remote_settings::RemoteSettings {
    fn get_records(&self) -> Result<RemoteSettingsResponse> {
        Ok(remote_settings::RemoteSettings::get_records(self)?)
    }

    fn get_attachment(&self, location: &str) -> Result<Vec<u8>> {
        Ok(remote_settings::RemoteSettings::get_attachment(
            self, location,
        )?)
    }
}

/// A record in the Relevancy Remote Settings collection.
#[derive(Clone, Debug, Deserialize)]
pub struct RelevancyRecord {
    #[allow(dead_code)]
    #[serde(rename = "type")]
    pub record_type: String,
    pub record_custom_details: RecordCustomDetails,
}

// Custom details related to category of the record.
#[derive(Clone, Debug, Deserialize)]
pub struct RecordCustomDetails {
    pub category_to_domains: CategoryToDomains,
}

/// Category information related to the record.
#[derive(Clone, Debug, Deserialize)]
pub struct CategoryToDomains {
    #[allow(dead_code)]
    pub version: i32,
    #[allow(dead_code)]
    pub category: String,
    pub category_code: i32,
}

/// A downloaded Remote Settings attachment that contains domain data.
#[derive(Clone, Debug, Deserialize)]
pub struct RelevancyAttachmentData {
    pub domain: String,
}

/// Deserialize one of these types from a JSON value
pub fn from_json<T: serde::de::DeserializeOwned>(value: serde_json::Value) -> Result<T> {
    serde_path_to_error::deserialize(value).map_err(|e| Error::RemoteSettingsParseError {
        type_name: std::any::type_name::<T>().to_owned(),
        path: e.path().to_string(),
        error: e.into_inner(),
    })
}

/// Deserialize one of these types from a slice of JSON data
pub fn from_json_slice<T: serde::de::DeserializeOwned>(value: &[u8]) -> Result<T> {
    let json_value =
        serde_json::from_slice(value).map_err(|e| Error::RemoteSettingsParseError {
            type_name: std::any::type_name::<T>().to_owned(),
            path: "<while parsing JSON>".to_owned(),
            error: e,
        })?;
    from_json(json_value)
}