xref: /aosp_15_r20/external/flatbuffers/rust/flexbuffers/src/reader/de.rs (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker // Copyright 2019 Google LLC
2*890232f2SAndroid Build Coastguard Worker //
3*890232f2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*890232f2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*890232f2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*890232f2SAndroid Build Coastguard Worker //
7*890232f2SAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*890232f2SAndroid Build Coastguard Worker //
9*890232f2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*890232f2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*890232f2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*890232f2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*890232f2SAndroid Build Coastguard Worker // limitations under the License.
14*890232f2SAndroid Build Coastguard Worker 
15*890232f2SAndroid Build Coastguard Worker use super::Error;
16*890232f2SAndroid Build Coastguard Worker use crate::{FlexBufferType, Reader, ReaderIterator};
17*890232f2SAndroid Build Coastguard Worker use serde::de::{
18*890232f2SAndroid Build Coastguard Worker     DeserializeSeed, Deserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
19*890232f2SAndroid Build Coastguard Worker     VariantAccess, Visitor,
20*890232f2SAndroid Build Coastguard Worker };
21*890232f2SAndroid Build Coastguard Worker 
22*890232f2SAndroid Build Coastguard Worker /// Errors that may happen when deserializing a flexbuffer with serde.
23*890232f2SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
24*890232f2SAndroid Build Coastguard Worker pub enum DeserializationError {
25*890232f2SAndroid Build Coastguard Worker     Reader(Error),
26*890232f2SAndroid Build Coastguard Worker     Serde(String),
27*890232f2SAndroid Build Coastguard Worker }
28*890232f2SAndroid Build Coastguard Worker 
29*890232f2SAndroid Build Coastguard Worker impl std::error::Error for DeserializationError {}
30*890232f2SAndroid Build Coastguard Worker impl std::fmt::Display for DeserializationError {
fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>31*890232f2SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
32*890232f2SAndroid Build Coastguard Worker         match self {
33*890232f2SAndroid Build Coastguard Worker             Self::Reader(r) => write!(f, "Flexbuffer Read Error: {:?}", r),
34*890232f2SAndroid Build Coastguard Worker             Self::Serde(s) => write!(f, "Serde Error: {}", s),
35*890232f2SAndroid Build Coastguard Worker         }
36*890232f2SAndroid Build Coastguard Worker     }
37*890232f2SAndroid Build Coastguard Worker }
38*890232f2SAndroid Build Coastguard Worker 
39*890232f2SAndroid Build Coastguard Worker impl serde::de::Error for DeserializationError {
custom<T>(msg: T) -> Self where T: std::fmt::Display,40*890232f2SAndroid Build Coastguard Worker     fn custom<T>(msg: T) -> Self
41*890232f2SAndroid Build Coastguard Worker     where
42*890232f2SAndroid Build Coastguard Worker         T: std::fmt::Display,
43*890232f2SAndroid Build Coastguard Worker     {
44*890232f2SAndroid Build Coastguard Worker         Self::Serde(format!("{}", msg))
45*890232f2SAndroid Build Coastguard Worker     }
46*890232f2SAndroid Build Coastguard Worker }
47*890232f2SAndroid Build Coastguard Worker 
48*890232f2SAndroid Build Coastguard Worker impl std::convert::From<super::Error> for DeserializationError {
from(e: super::Error) -> Self49*890232f2SAndroid Build Coastguard Worker     fn from(e: super::Error) -> Self {
50*890232f2SAndroid Build Coastguard Worker         Self::Reader(e)
51*890232f2SAndroid Build Coastguard Worker     }
52*890232f2SAndroid Build Coastguard Worker }
53*890232f2SAndroid Build Coastguard Worker 
54*890232f2SAndroid Build Coastguard Worker impl<'de> SeqAccess<'de> for ReaderIterator<&'de [u8]> {
55*890232f2SAndroid Build Coastguard Worker     type Error = DeserializationError;
56*890232f2SAndroid Build Coastguard Worker 
next_element_seed<T>( &mut self, seed: T, ) -> Result<Option<<T as DeserializeSeed<'de>>::Value>, Self::Error> where T: DeserializeSeed<'de>,57*890232f2SAndroid Build Coastguard Worker     fn next_element_seed<T>(
58*890232f2SAndroid Build Coastguard Worker         &mut self,
59*890232f2SAndroid Build Coastguard Worker         seed: T,
60*890232f2SAndroid Build Coastguard Worker     ) -> Result<Option<<T as DeserializeSeed<'de>>::Value>, Self::Error>
61*890232f2SAndroid Build Coastguard Worker     where
62*890232f2SAndroid Build Coastguard Worker         T: DeserializeSeed<'de>,
63*890232f2SAndroid Build Coastguard Worker     {
64*890232f2SAndroid Build Coastguard Worker         if let Some(elem) = self.next() {
65*890232f2SAndroid Build Coastguard Worker             seed.deserialize(elem).map(Some)
66*890232f2SAndroid Build Coastguard Worker         } else {
67*890232f2SAndroid Build Coastguard Worker             Ok(None)
68*890232f2SAndroid Build Coastguard Worker         }
69*890232f2SAndroid Build Coastguard Worker     }
70*890232f2SAndroid Build Coastguard Worker 
size_hint(&self) -> Option<usize>71*890232f2SAndroid Build Coastguard Worker     fn size_hint(&self) -> Option<usize> {
72*890232f2SAndroid Build Coastguard Worker         Some(self.len())
73*890232f2SAndroid Build Coastguard Worker     }
74*890232f2SAndroid Build Coastguard Worker }
75*890232f2SAndroid Build Coastguard Worker 
76*890232f2SAndroid Build Coastguard Worker struct EnumReader<'de> {
77*890232f2SAndroid Build Coastguard Worker     variant: &'de str,
78*890232f2SAndroid Build Coastguard Worker     value: Option<Reader<&'de [u8]>>,
79*890232f2SAndroid Build Coastguard Worker }
80*890232f2SAndroid Build Coastguard Worker 
81*890232f2SAndroid Build Coastguard Worker impl<'de> EnumAccess<'de> for EnumReader<'de> {
82*890232f2SAndroid Build Coastguard Worker     type Error = DeserializationError;
83*890232f2SAndroid Build Coastguard Worker     type Variant = Reader<&'de [u8]>;
84*890232f2SAndroid Build Coastguard Worker 
variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>,85*890232f2SAndroid Build Coastguard Worker     fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
86*890232f2SAndroid Build Coastguard Worker     where
87*890232f2SAndroid Build Coastguard Worker         V: DeserializeSeed<'de>,
88*890232f2SAndroid Build Coastguard Worker     {
89*890232f2SAndroid Build Coastguard Worker         seed.deserialize(self.variant.into_deserializer())
90*890232f2SAndroid Build Coastguard Worker             .map(|v| (v, self.value.unwrap_or_default()))
91*890232f2SAndroid Build Coastguard Worker     }
92*890232f2SAndroid Build Coastguard Worker }
93*890232f2SAndroid Build Coastguard Worker 
94*890232f2SAndroid Build Coastguard Worker struct MapAccessor<'de> {
95*890232f2SAndroid Build Coastguard Worker     keys: ReaderIterator<&'de [u8]>,
96*890232f2SAndroid Build Coastguard Worker     vals: ReaderIterator<&'de [u8]>,
97*890232f2SAndroid Build Coastguard Worker }
98*890232f2SAndroid Build Coastguard Worker 
99*890232f2SAndroid Build Coastguard Worker impl<'de> MapAccess<'de> for MapAccessor<'de> {
100*890232f2SAndroid Build Coastguard Worker     type Error = DeserializationError;
101*890232f2SAndroid Build Coastguard Worker 
next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> where K: DeserializeSeed<'de>,102*890232f2SAndroid Build Coastguard Worker     fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
103*890232f2SAndroid Build Coastguard Worker     where
104*890232f2SAndroid Build Coastguard Worker         K: DeserializeSeed<'de>,
105*890232f2SAndroid Build Coastguard Worker     {
106*890232f2SAndroid Build Coastguard Worker         if let Some(k) = self.keys.next() {
107*890232f2SAndroid Build Coastguard Worker             seed.deserialize(k).map(Some)
108*890232f2SAndroid Build Coastguard Worker         } else {
109*890232f2SAndroid Build Coastguard Worker             Ok(None)
110*890232f2SAndroid Build Coastguard Worker         }
111*890232f2SAndroid Build Coastguard Worker     }
112*890232f2SAndroid Build Coastguard Worker 
next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> where V: DeserializeSeed<'de>,113*890232f2SAndroid Build Coastguard Worker     fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
114*890232f2SAndroid Build Coastguard Worker     where
115*890232f2SAndroid Build Coastguard Worker         V: DeserializeSeed<'de>,
116*890232f2SAndroid Build Coastguard Worker     {
117*890232f2SAndroid Build Coastguard Worker         let val = self.vals.next().ok_or(Error::IndexOutOfBounds)?;
118*890232f2SAndroid Build Coastguard Worker         seed.deserialize(val)
119*890232f2SAndroid Build Coastguard Worker     }
120*890232f2SAndroid Build Coastguard Worker }
121*890232f2SAndroid Build Coastguard Worker 
122*890232f2SAndroid Build Coastguard Worker impl<'de> VariantAccess<'de> for Reader<&'de [u8]> {
123*890232f2SAndroid Build Coastguard Worker     type Error = DeserializationError;
124*890232f2SAndroid Build Coastguard Worker 
unit_variant(self) -> Result<(), Self::Error>125*890232f2SAndroid Build Coastguard Worker     fn unit_variant(self) -> Result<(), Self::Error> {
126*890232f2SAndroid Build Coastguard Worker         Ok(())
127*890232f2SAndroid Build Coastguard Worker     }
128*890232f2SAndroid Build Coastguard Worker 
newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> where T: DeserializeSeed<'de>,129*890232f2SAndroid Build Coastguard Worker     fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
130*890232f2SAndroid Build Coastguard Worker     where
131*890232f2SAndroid Build Coastguard Worker         T: DeserializeSeed<'de>,
132*890232f2SAndroid Build Coastguard Worker     {
133*890232f2SAndroid Build Coastguard Worker         seed.deserialize(self)
134*890232f2SAndroid Build Coastguard Worker     }
135*890232f2SAndroid Build Coastguard Worker 
136*890232f2SAndroid Build Coastguard Worker     // Tuple variants have an internally tagged representation. They are vectors where Index 0 is
137*890232f2SAndroid Build Coastguard Worker     // the discriminant and index N is field N-1.
tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de>,138*890232f2SAndroid Build Coastguard Worker     fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
139*890232f2SAndroid Build Coastguard Worker     where
140*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
141*890232f2SAndroid Build Coastguard Worker     {
142*890232f2SAndroid Build Coastguard Worker         visitor.visit_seq(self.as_vector().iter())
143*890232f2SAndroid Build Coastguard Worker     }
144*890232f2SAndroid Build Coastguard Worker 
145*890232f2SAndroid Build Coastguard Worker     // Struct variants have an internally tagged representation. They are vectors where Index 0 is
146*890232f2SAndroid Build Coastguard Worker     // the discriminant and index N is field N-1.
struct_variant<V>( self, _fields: &'static [&'static str], visitor: V, ) -> Result<V::Value, Self::Error> where V: Visitor<'de>,147*890232f2SAndroid Build Coastguard Worker     fn struct_variant<V>(
148*890232f2SAndroid Build Coastguard Worker         self,
149*890232f2SAndroid Build Coastguard Worker         _fields: &'static [&'static str],
150*890232f2SAndroid Build Coastguard Worker         visitor: V,
151*890232f2SAndroid Build Coastguard Worker     ) -> Result<V::Value, Self::Error>
152*890232f2SAndroid Build Coastguard Worker     where
153*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
154*890232f2SAndroid Build Coastguard Worker     {
155*890232f2SAndroid Build Coastguard Worker         let m = self.get_map()?;
156*890232f2SAndroid Build Coastguard Worker         visitor.visit_map(MapAccessor {
157*890232f2SAndroid Build Coastguard Worker             keys: m.keys_vector().iter(),
158*890232f2SAndroid Build Coastguard Worker             vals: m.iter_values(),
159*890232f2SAndroid Build Coastguard Worker         })
160*890232f2SAndroid Build Coastguard Worker     }
161*890232f2SAndroid Build Coastguard Worker }
162*890232f2SAndroid Build Coastguard Worker 
163*890232f2SAndroid Build Coastguard Worker impl<'de> Deserializer<'de> for Reader<&'de [u8]> {
164*890232f2SAndroid Build Coastguard Worker     type Error = DeserializationError;
is_human_readable(&self) -> bool165*890232f2SAndroid Build Coastguard Worker     fn is_human_readable(&self) -> bool {
166*890232f2SAndroid Build Coastguard Worker         cfg!(deserialize_human_readable)
167*890232f2SAndroid Build Coastguard Worker     }
168*890232f2SAndroid Build Coastguard Worker 
deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de>,169*890232f2SAndroid Build Coastguard Worker     fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
170*890232f2SAndroid Build Coastguard Worker     where
171*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
172*890232f2SAndroid Build Coastguard Worker     {
173*890232f2SAndroid Build Coastguard Worker         use crate::BitWidth::*;
174*890232f2SAndroid Build Coastguard Worker         use crate::FlexBufferType::*;
175*890232f2SAndroid Build Coastguard Worker         match (self.flexbuffer_type(), self.bitwidth()) {
176*890232f2SAndroid Build Coastguard Worker             (Bool, _) => visitor.visit_bool(self.as_bool()),
177*890232f2SAndroid Build Coastguard Worker             (UInt, W8) => visitor.visit_u8(self.as_u8()),
178*890232f2SAndroid Build Coastguard Worker             (UInt, W16) => visitor.visit_u16(self.as_u16()),
179*890232f2SAndroid Build Coastguard Worker             (UInt, W32) => visitor.visit_u32(self.as_u32()),
180*890232f2SAndroid Build Coastguard Worker             (UInt, W64) => visitor.visit_u64(self.as_u64()),
181*890232f2SAndroid Build Coastguard Worker             (Int, W8) => visitor.visit_i8(self.as_i8()),
182*890232f2SAndroid Build Coastguard Worker             (Int, W16) => visitor.visit_i16(self.as_i16()),
183*890232f2SAndroid Build Coastguard Worker             (Int, W32) => visitor.visit_i32(self.as_i32()),
184*890232f2SAndroid Build Coastguard Worker             (Int, W64) => visitor.visit_i64(self.as_i64()),
185*890232f2SAndroid Build Coastguard Worker             (Float, W32) => visitor.visit_f32(self.as_f32()),
186*890232f2SAndroid Build Coastguard Worker             (Float, W64) => visitor.visit_f64(self.as_f64()),
187*890232f2SAndroid Build Coastguard Worker             (Float, _) => Err(Error::InvalidPackedType.into()), // f8 and f16 are not supported.
188*890232f2SAndroid Build Coastguard Worker             (Null, _) => visitor.visit_unit(),
189*890232f2SAndroid Build Coastguard Worker             (String, _) | (Key, _) => visitor.visit_borrowed_str(self.as_str()),
190*890232f2SAndroid Build Coastguard Worker             (Blob, _) => visitor.visit_borrowed_bytes(self.get_blob()?.0),
191*890232f2SAndroid Build Coastguard Worker             (Map, _) => {
192*890232f2SAndroid Build Coastguard Worker                 let m = self.get_map()?;
193*890232f2SAndroid Build Coastguard Worker                 visitor.visit_map(MapAccessor {
194*890232f2SAndroid Build Coastguard Worker                     keys: m.keys_vector().iter(),
195*890232f2SAndroid Build Coastguard Worker                     vals: m.iter_values(),
196*890232f2SAndroid Build Coastguard Worker                 })
197*890232f2SAndroid Build Coastguard Worker             }
198*890232f2SAndroid Build Coastguard Worker             (ty, _) if ty.is_vector() => visitor.visit_seq(self.as_vector().iter()),
199*890232f2SAndroid Build Coastguard Worker             (ty, bw) => unreachable!("TODO deserialize_any {:?} {:?}.", ty, bw),
200*890232f2SAndroid Build Coastguard Worker         }
201*890232f2SAndroid Build Coastguard Worker     }
202*890232f2SAndroid Build Coastguard Worker 
203*890232f2SAndroid Build Coastguard Worker     serde::forward_to_deserialize_any! {
204*890232f2SAndroid Build Coastguard Worker         bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 str unit unit_struct bytes
205*890232f2SAndroid Build Coastguard Worker         ignored_any map identifier struct tuple tuple_struct seq string
206*890232f2SAndroid Build Coastguard Worker     }
207*890232f2SAndroid Build Coastguard Worker 
deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de>,208*890232f2SAndroid Build Coastguard Worker     fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
209*890232f2SAndroid Build Coastguard Worker     where
210*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
211*890232f2SAndroid Build Coastguard Worker     {
212*890232f2SAndroid Build Coastguard Worker         visitor.visit_char(self.as_u8() as char)
213*890232f2SAndroid Build Coastguard Worker     }
214*890232f2SAndroid Build Coastguard Worker 
deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de>,215*890232f2SAndroid Build Coastguard Worker     fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
216*890232f2SAndroid Build Coastguard Worker     where
217*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
218*890232f2SAndroid Build Coastguard Worker     {
219*890232f2SAndroid Build Coastguard Worker         visitor.visit_byte_buf(self.get_blob()?.0.to_vec())
220*890232f2SAndroid Build Coastguard Worker     }
221*890232f2SAndroid Build Coastguard Worker 
deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de>,222*890232f2SAndroid Build Coastguard Worker     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
223*890232f2SAndroid Build Coastguard Worker     where
224*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
225*890232f2SAndroid Build Coastguard Worker     {
226*890232f2SAndroid Build Coastguard Worker         if self.flexbuffer_type() == FlexBufferType::Null {
227*890232f2SAndroid Build Coastguard Worker             visitor.visit_none()
228*890232f2SAndroid Build Coastguard Worker         } else {
229*890232f2SAndroid Build Coastguard Worker             visitor.visit_some(self)
230*890232f2SAndroid Build Coastguard Worker         }
231*890232f2SAndroid Build Coastguard Worker     }
232*890232f2SAndroid Build Coastguard Worker 
deserialize_newtype_struct<V>( self, _name: &'static str, visitor: V, ) -> Result<V::Value, Self::Error> where V: Visitor<'de>,233*890232f2SAndroid Build Coastguard Worker     fn deserialize_newtype_struct<V>(
234*890232f2SAndroid Build Coastguard Worker         self,
235*890232f2SAndroid Build Coastguard Worker         _name: &'static str,
236*890232f2SAndroid Build Coastguard Worker         visitor: V,
237*890232f2SAndroid Build Coastguard Worker     ) -> Result<V::Value, Self::Error>
238*890232f2SAndroid Build Coastguard Worker     where
239*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
240*890232f2SAndroid Build Coastguard Worker     {
241*890232f2SAndroid Build Coastguard Worker         visitor.visit_newtype_struct(self)
242*890232f2SAndroid Build Coastguard Worker     }
243*890232f2SAndroid Build Coastguard Worker 
deserialize_enum<V>( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result<V::Value, Self::Error> where V: Visitor<'de>,244*890232f2SAndroid Build Coastguard Worker     fn deserialize_enum<V>(
245*890232f2SAndroid Build Coastguard Worker         self,
246*890232f2SAndroid Build Coastguard Worker         _name: &'static str,
247*890232f2SAndroid Build Coastguard Worker         _variants: &'static [&'static str],
248*890232f2SAndroid Build Coastguard Worker         visitor: V,
249*890232f2SAndroid Build Coastguard Worker     ) -> Result<V::Value, Self::Error>
250*890232f2SAndroid Build Coastguard Worker     where
251*890232f2SAndroid Build Coastguard Worker         V: Visitor<'de>,
252*890232f2SAndroid Build Coastguard Worker     {
253*890232f2SAndroid Build Coastguard Worker         let (variant, value) = match self.fxb_type {
254*890232f2SAndroid Build Coastguard Worker             FlexBufferType::String => (self.as_str(), None),
255*890232f2SAndroid Build Coastguard Worker             FlexBufferType::Map => {
256*890232f2SAndroid Build Coastguard Worker                 let m = self.get_map()?;
257*890232f2SAndroid Build Coastguard Worker                 let variant = m.keys_vector().idx(0).get_key()?;
258*890232f2SAndroid Build Coastguard Worker                 let value = Some(m.idx(0));
259*890232f2SAndroid Build Coastguard Worker                 (variant, value)
260*890232f2SAndroid Build Coastguard Worker             }
261*890232f2SAndroid Build Coastguard Worker             _ => {
262*890232f2SAndroid Build Coastguard Worker                 return Err(Error::UnexpectedFlexbufferType {
263*890232f2SAndroid Build Coastguard Worker                     expected: FlexBufferType::Map,
264*890232f2SAndroid Build Coastguard Worker                     actual: self.fxb_type,
265*890232f2SAndroid Build Coastguard Worker                 }
266*890232f2SAndroid Build Coastguard Worker                 .into());
267*890232f2SAndroid Build Coastguard Worker             }
268*890232f2SAndroid Build Coastguard Worker         };
269*890232f2SAndroid Build Coastguard Worker         visitor.visit_enum(EnumReader { variant, value })
270*890232f2SAndroid Build Coastguard Worker     }
271*890232f2SAndroid Build Coastguard Worker }
272