dpp_domain/domain/sector/data/
sector_data.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5use super::aluminium::AluminiumData;
6use super::battery::BatteryData;
7use super::construction::ConstructionData;
8use super::detergent::DetergentData;
9use super::electronics::ElectronicsData;
10use super::furniture::FurnitureData;
11use super::steel::SteelData;
12use super::textile::TextileData;
13use super::toy::ToyData;
14use super::tyre::TyreData;
15use super::unsold_goods::UnsoldGoodsReport;
16use crate::domain::sector::Sector;
17
18#[derive(Debug, Clone, PartialEq)]
32#[non_exhaustive]
33pub enum SectorData {
34 Battery(BatteryData),
35 Textile(TextileData),
36 UnsoldGoods(UnsoldGoodsReport),
37 Steel(SteelData),
38 Electronics(ElectronicsData),
39 Construction(ConstructionData),
40 Tyre(TyreData),
41 Toy(ToyData),
42 Aluminium(AluminiumData),
43 Furniture(FurnitureData),
44 Detergent(DetergentData),
45 Other {
52 sector: String,
54 data: serde_json::Value,
56 },
57}
58
59impl Serialize for SectorData {
73 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
74 let mut value = match self {
78 Self::Battery(d) => serde_json::to_value(d),
79 Self::Textile(d) => serde_json::to_value(d),
80 Self::UnsoldGoods(d) => serde_json::to_value(d),
81 Self::Steel(d) => serde_json::to_value(d),
82 Self::Electronics(d) => serde_json::to_value(d),
83 Self::Construction(d) => serde_json::to_value(d),
84 Self::Tyre(d) => serde_json::to_value(d),
85 Self::Toy(d) => serde_json::to_value(d),
86 Self::Aluminium(d) => serde_json::to_value(d),
87 Self::Furniture(d) => serde_json::to_value(d),
88 Self::Detergent(d) => serde_json::to_value(d),
89 Self::Other { data, .. } => Ok(data.clone()),
90 }
91 .map_err(serde::ser::Error::custom)?;
92
93 let tag = self.sector();
94 if let serde_json::Value::Object(ref mut map) = value {
95 map.insert(
96 "sector".to_owned(),
97 serde_json::Value::String(tag.wire_str().to_owned()),
98 );
99 }
100 value.serialize(serializer)
101 }
102}
103
104impl<'de> Deserialize<'de> for SectorData {
105 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
106 use serde::de::Error as _;
107
108 let value = serde_json::Value::deserialize(deserializer)?;
109 let tag = value
110 .get("sector")
111 .and_then(serde_json::Value::as_str)
112 .ok_or_else(|| D::Error::missing_field("sector"))?
113 .to_owned();
114
115 macro_rules! typed {
118 ($variant:ident) => {
119 serde_json::from_value(value.clone())
120 .map(Self::$variant)
121 .map_err(D::Error::custom)
122 };
123 }
124
125 match Sector::from_wire_tag(&tag) {
126 Sector::Battery => typed!(Battery),
127 Sector::Textile => typed!(Textile),
128 Sector::UnsoldGoods => typed!(UnsoldGoods),
129 Sector::Steel => typed!(Steel),
130 Sector::Electronics => typed!(Electronics),
131 Sector::Construction => typed!(Construction),
132 Sector::Tyre => typed!(Tyre),
133 Sector::Toy => typed!(Toy),
134 Sector::Aluminium => typed!(Aluminium),
135 Sector::Furniture => typed!(Furniture),
136 Sector::Detergent => typed!(Detergent),
137 Sector::Other(sector) => Ok(Self::Other {
138 sector,
139 data: value,
140 }),
141 }
142 }
143}
144
145impl SectorData {
146 #[must_use]
161 pub fn other(data: serde_json::Value) -> Option<Self> {
162 let sector = data
163 .get("sector")
164 .and_then(serde_json::Value::as_str)
165 .unwrap_or("other")
166 .to_owned();
167 match Sector::from_wire_tag(§or) {
168 Sector::Other(_) => Some(Self::Other { sector, data }),
169 _ => None,
170 }
171 }
172
173 pub fn sector(&self) -> Sector {
175 match self {
176 SectorData::Battery(_) => Sector::Battery,
177 SectorData::Textile(_) => Sector::Textile,
178 SectorData::UnsoldGoods(_) => Sector::UnsoldGoods,
179 SectorData::Steel(_) => Sector::Steel,
180 SectorData::Electronics(_) => Sector::Electronics,
181 SectorData::Construction(_) => Sector::Construction,
182 SectorData::Tyre(_) => Sector::Tyre,
183 SectorData::Toy(_) => Sector::Toy,
184 SectorData::Aluminium(_) => Sector::Aluminium,
185 SectorData::Furniture(_) => Sector::Furniture,
186 SectorData::Detergent(_) => Sector::Detergent,
187 SectorData::Other { sector, .. } => Sector::Other(sector.clone()),
188 }
189 }
190
191 pub fn gtin(&self) -> Option<&str> {
197 match self {
198 SectorData::Battery(d) => Some(d.gtin.as_str()),
199 SectorData::Textile(d) => Some(d.gtin.as_str()),
200 SectorData::Steel(d) => Some(d.gtin.as_str()),
201 SectorData::Electronics(d) => Some(d.gtin.as_str()),
202 SectorData::Construction(d) => Some(d.gtin.as_str()),
203 SectorData::Tyre(d) => Some(d.gtin.as_str()),
204 SectorData::Toy(d) => Some(d.gtin.as_str()),
205 SectorData::Aluminium(d) => Some(d.gtin.as_str()),
206 SectorData::Furniture(d) => Some(d.gtin.as_str()),
207 SectorData::Detergent(d) => Some(d.gtin.as_str()),
208 SectorData::UnsoldGoods(_) | SectorData::Other { .. } => None,
209 }
210 }
211}
212
213pub fn redact_sector_data(
225 data: &SectorData,
226 audience: crate::domain::identity::Audience,
227 descriptor: &crate::catalog::SectorDescriptor,
228) -> serde_json::Value {
229 let mut value = match serde_json::to_value(data) {
230 Ok(v) => v,
231 Err(_) => return serde_json::Value::Null,
232 };
233 if let Some(obj) = value.as_object_mut() {
234 obj.retain(|key, _| match descriptor.disclosure.get(key) {
235 Some(&class) => audience.may_see(class),
236 None => true,
237 });
238 }
239 value
240}