1use crate::{Error, Result};
7use remote_settings::{RemoteSettingsClient, RemoteSettingsRecord};
8use serde::Deserialize;
9pub(crate) const REMOTE_SETTINGS_COLLECTION: &str = "content-relevance";
11
12pub(crate) trait RelevancyRemoteSettingsClient {
16 fn get_records(&self) -> Result<Vec<RemoteSettingsRecord>>;
18
19 fn get_attachment(&self, location: &RemoteSettingsRecord) -> Result<Vec<u8>>;
22
23 fn close(&self);
25}
26
27impl RelevancyRemoteSettingsClient for RemoteSettingsClient {
28 fn get_records(&self) -> Result<Vec<RemoteSettingsRecord>> {
29 self.sync()?;
30 Ok(self
31 .get_records(false)
32 .expect("RemoteSettingsClient::get_records() returned None after `sync()` called"))
33 }
34
35 fn get_attachment(&self, record: &RemoteSettingsRecord) -> Result<Vec<u8>> {
36 Ok(self.get_attachment(record)?)
37 }
38
39 fn close(&self) {
40 self.shutdown()
41 }
42}
43
44impl<T: RelevancyRemoteSettingsClient> RelevancyRemoteSettingsClient for &T {
45 fn get_records(&self) -> Result<Vec<RemoteSettingsRecord>> {
46 (*self).get_records()
47 }
48
49 fn get_attachment(&self, record: &RemoteSettingsRecord) -> Result<Vec<u8>> {
50 (*self).get_attachment(record)
51 }
52
53 fn close(&self) {
54 (*self).close();
55 }
56}
57
58impl<T: RelevancyRemoteSettingsClient> RelevancyRemoteSettingsClient for std::sync::Arc<T> {
59 fn get_records(&self) -> Result<Vec<RemoteSettingsRecord>> {
60 (**self).get_records()
61 }
62
63 fn get_attachment(&self, record: &RemoteSettingsRecord) -> Result<Vec<u8>> {
64 (**self).get_attachment(record)
65 }
66
67 fn close(&self) {
68 (**self).close()
69 }
70}
71
72#[derive(Clone, Debug, Deserialize)]
73pub struct RelevancyRecord {
74 #[allow(dead_code)]
75 #[serde(rename = "type")]
76 pub record_type: String,
77 pub record_custom_details: RecordCustomDetails,
78}
79
80#[derive(Clone, Debug, Deserialize)]
82pub struct RecordCustomDetails {
83 pub category_to_domains: CategoryToDomains,
84}
85
86#[derive(Clone, Debug, Deserialize)]
88pub struct CategoryToDomains {
89 #[allow(dead_code)]
90 pub version: i32,
91 #[allow(dead_code)]
92 pub category: String,
93 pub category_code: i32,
94}
95
96#[derive(Clone, Debug, Deserialize)]
98pub struct RelevancyAttachmentData {
99 pub domain: String,
100}
101
102pub fn from_json<T: serde::de::DeserializeOwned>(value: serde_json::Value) -> Result<T> {
104 serde_path_to_error::deserialize(value).map_err(|e| Error::RemoteSettingsParseError {
105 type_name: std::any::type_name::<T>().to_owned(),
106 path: e.path().to_string(),
107 error: e.into_inner(),
108 })
109}
110
111pub fn from_json_slice<T: serde::de::DeserializeOwned>(value: &[u8]) -> Result<T> {
113 let json_value =
114 serde_json::from_slice(value).map_err(|e| Error::RemoteSettingsParseError {
115 type_name: std::any::type_name::<T>().to_owned(),
116 path: "<while parsing JSON>".to_owned(),
117 error: e,
118 })?;
119 from_json(json_value)
120}
121
122#[cfg(test)]
123pub mod test {
124 use super::*;
125
126 pub struct NullRelavancyRemoteSettingsClient;
130
131 impl RelevancyRemoteSettingsClient for NullRelavancyRemoteSettingsClient {
132 fn get_records(&self) -> Result<Vec<RemoteSettingsRecord>> {
133 panic!("NullRelavancyRemoteSettingsClient::get_records was called")
134 }
135
136 fn get_attachment(&self, _record: &RemoteSettingsRecord) -> Result<Vec<u8>> {
137 panic!("NullRelavancyRemoteSettingsClient::get_records was called")
138 }
139
140 fn close(&self) {}
141 }
142}