Line | Count | Source (jump to first uncovered line) |
1 | | //! Roundtrip serde Options module. |
2 | | |
3 | | use alloc::string::String; |
4 | | use core::fmt; |
5 | | |
6 | | use serde::{de, ser}; |
7 | | use serde_derive::{Deserialize, Serialize}; |
8 | | |
9 | | use crate::{ |
10 | | de::Deserializer, |
11 | | error::{Result, SpannedResult}, |
12 | | extensions::Extensions, |
13 | | ser::{PrettyConfig, Serializer}, |
14 | | }; |
15 | | |
16 | | #[cfg(feature = "std")] |
17 | | use { |
18 | | crate::error::{Position, Span, SpannedError}, |
19 | | alloc::vec::Vec, |
20 | | std::io, |
21 | | }; |
22 | | |
23 | | /// Roundtrip serde options. |
24 | | /// |
25 | | /// # Examples |
26 | | /// |
27 | | /// ``` |
28 | | /// use ron::{Options, extensions::Extensions}; |
29 | | /// |
30 | | /// let ron = Options::default() |
31 | | /// .with_default_extension(Extensions::IMPLICIT_SOME); |
32 | | /// |
33 | | /// let de: Option<i32> = ron.from_str("42").unwrap(); |
34 | | /// let ser = ron.to_string(&de).unwrap(); |
35 | | /// |
36 | | /// assert_eq!(ser, "42"); |
37 | | /// ``` |
38 | | #[derive(Clone, Debug, Serialize, Deserialize)] // GRCOV_EXCL_LINE |
39 | | #[serde(default)] |
40 | | #[non_exhaustive] |
41 | | pub struct Options { |
42 | | /// Extensions that are enabled by default during serialization and |
43 | | /// deserialization. |
44 | | /// During serialization, these extensions do NOT have to be explicitly |
45 | | /// enabled in the parsed RON. |
46 | | /// During deserialization, these extensions are used, but their explicit |
47 | | /// activation is NOT included in the output RON. |
48 | | /// No extensions are enabled by default. |
49 | | pub default_extensions: Extensions, |
50 | | /// Default recursion limit that is checked during serialization and |
51 | | /// deserialization. |
52 | | /// If set to `None`, infinite recursion is allowed and stack overflow |
53 | | /// errors can crash the serialization or deserialization process. |
54 | | /// Defaults to `Some(128)`, i.e. 128 recursive calls are allowed. |
55 | | pub recursion_limit: Option<usize>, |
56 | | } |
57 | | |
58 | | impl Default for Options { |
59 | 4.56M | fn default() -> Self { |
60 | 4.56M | Self { |
61 | 4.56M | default_extensions: Extensions::empty(), |
62 | 4.56M | recursion_limit: Some(128), |
63 | 4.56M | } |
64 | 4.56M | } |
65 | | } |
66 | | |
67 | | impl Options { |
68 | | #[must_use] |
69 | | /// Enable `default_extension` by default during serialization and deserialization. |
70 | 0 | pub fn with_default_extension(mut self, default_extension: Extensions) -> Self { |
71 | 0 | self.default_extensions |= default_extension; |
72 | 0 | self |
73 | 0 | } |
74 | | |
75 | | #[must_use] |
76 | | /// Do NOT enable `default_extension` by default during serialization and deserialization. |
77 | 0 | pub fn without_default_extension(mut self, default_extension: Extensions) -> Self { |
78 | 0 | self.default_extensions &= !default_extension; |
79 | 0 | self |
80 | 0 | } |
81 | | |
82 | | #[must_use] |
83 | | /// Set a maximum recursion limit during serialization and deserialization. |
84 | 16.8k | pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self { |
85 | 16.8k | self.recursion_limit = Some(recursion_limit); |
86 | 16.8k | self |
87 | 16.8k | } |
88 | | |
89 | | #[must_use] |
90 | | /// Disable the recursion limit during serialization and deserialization. |
91 | | /// |
92 | | /// If you expect to handle highly recursive datastructures, consider wrapping |
93 | | /// `ron` with [`serde_stacker`](https://docs.rs/serde_stacker/latest/serde_stacker/). |
94 | 0 | pub fn without_recursion_limit(mut self) -> Self { |
95 | 0 | self.recursion_limit = None; |
96 | 0 | self |
97 | 0 | } |
98 | | } |
99 | | |
100 | | impl Options { |
101 | | /// A convenience function for building a deserializer |
102 | | /// and deserializing a value of type `T` from a reader. |
103 | | #[cfg(feature = "std")] |
104 | 0 | pub fn from_reader<R, T>(&self, rdr: R) -> SpannedResult<T> |
105 | 0 | where |
106 | 0 | R: io::Read, |
107 | 0 | T: de::DeserializeOwned, |
108 | 0 | { |
109 | 0 | self.from_reader_seed(rdr, core::marker::PhantomData) |
110 | 0 | } |
111 | | |
112 | | /// A convenience function for building a deserializer |
113 | | /// and deserializing a value of type `T` from a string. |
114 | 132k | pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T> |
115 | 132k | where |
116 | 132k | T: de::Deserialize<'a>, |
117 | 132k | { |
118 | 132k | self.from_str_seed(s, core::marker::PhantomData) |
119 | 132k | } <ron::options::Options>::from_str::<ron::value::Value> Line | Count | Source | 114 | 10.7k | pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T> | 115 | 10.7k | where | 116 | 10.7k | T: de::Deserialize<'a>, | 117 | 10.7k | { | 118 | 10.7k | self.from_str_seed(s, core::marker::PhantomData) | 119 | 10.7k | } |
<ron::options::Options>::from_str::<serde::de::ignored_any::IgnoredAny> Line | Count | Source | 114 | 77.4k | pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T> | 115 | 77.4k | where | 116 | 77.4k | T: de::Deserialize<'a>, | 117 | 77.4k | { | 118 | 77.4k | self.from_str_seed(s, core::marker::PhantomData) | 119 | 77.4k | } |
<ron::options::Options>::from_str::<ron::value::Value> Line | Count | Source | 114 | 15.0k | pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T> | 115 | 15.0k | where | 116 | 15.0k | T: de::Deserialize<'a>, | 117 | 15.0k | { | 118 | 15.0k | self.from_str_seed(s, core::marker::PhantomData) | 119 | 15.0k | } |
<ron::options::Options>::from_str::<alloc::string::String> Line | Count | Source | 114 | 29.6k | pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T> | 115 | 29.6k | where | 116 | 29.6k | T: de::Deserialize<'a>, | 117 | 29.6k | { | 118 | 29.6k | self.from_str_seed(s, core::marker::PhantomData) | 119 | 29.6k | } |
|
120 | | |
121 | | /// A convenience function for building a deserializer |
122 | | /// and deserializing a value of type `T` from bytes. |
123 | 0 | pub fn from_bytes<'a, T>(&self, s: &'a [u8]) -> SpannedResult<T> |
124 | 0 | where |
125 | 0 | T: de::Deserialize<'a>, |
126 | 0 | { |
127 | 0 | self.from_bytes_seed(s, core::marker::PhantomData) |
128 | 0 | } |
129 | | |
130 | | /// A convenience function for building a deserializer |
131 | | /// and deserializing a value of type `T` from a reader |
132 | | /// and a seed. |
133 | | // FIXME: panic is not actually possible, remove once utf8_chunks is stabilized |
134 | | #[allow(clippy::missing_panics_doc)] |
135 | | #[cfg(feature = "std")] |
136 | 0 | pub fn from_reader_seed<R, S, T>(&self, mut rdr: R, seed: S) -> SpannedResult<T> |
137 | 0 | where |
138 | 0 | R: io::Read, |
139 | 0 | S: for<'a> de::DeserializeSeed<'a, Value = T>, |
140 | 0 | { |
141 | 0 | let mut bytes = Vec::new(); |
142 | | |
143 | 0 | let io_err = if let Err(err) = rdr.read_to_end(&mut bytes) { |
144 | 0 | err |
145 | | } else { |
146 | 0 | return self.from_bytes_seed(&bytes, seed); |
147 | | }; |
148 | | |
149 | | // Try to compute a good error position for the I/O error |
150 | | // FIXME: use [`utf8_chunks`](https://github.com/rust-lang/rust/issues/99543) once stabilised |
151 | | #[allow(clippy::expect_used)] |
152 | 0 | let valid_input = match core::str::from_utf8(&bytes) { |
153 | 0 | Ok(valid_input) => valid_input, |
154 | 0 | Err(err) => core::str::from_utf8(&bytes[..err.valid_up_to()]) |
155 | 0 | .expect("source is valid up to error"), |
156 | | }; |
157 | | |
158 | 0 | Err(SpannedError { |
159 | 0 | code: io_err.into(), |
160 | 0 | span: Span { |
161 | 0 | start: Position { line: 1, col: 1 }, |
162 | 0 | end: Position::from_src_end(valid_input), |
163 | 0 | }, |
164 | 0 | }) |
165 | 0 | } |
166 | | |
167 | | /// A convenience function for building a deserializer |
168 | | /// and deserializing a value of type `T` from a string |
169 | | /// and a seed. |
170 | 132k | pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T> |
171 | 132k | where |
172 | 132k | S: de::DeserializeSeed<'a, Value = T>, |
173 | 132k | { |
174 | 132k | let mut deserializer = Deserializer::from_str_with_options(s, self)?; |
175 | | |
176 | 132k | let value = seed |
177 | 132k | .deserialize(&mut deserializer) |
178 | 132k | .map_err(|e| deserializer.span_error(e))?; <ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value>::{closure#0}Line | Count | Source | 178 | 6.84k | .map_err(|e| deserializer.span_error(e))?; |
Unexecuted instantiation: <ron::options::Options>::from_str_seed::<core::marker::PhantomData<serde::de::ignored_any::IgnoredAny>, serde::de::ignored_any::IgnoredAny>::{closure#0}<ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value>::{closure#0}Line | Count | Source | 178 | 134 | .map_err(|e| deserializer.span_error(e))?; |
<ron::options::Options>::from_str_seed::<core::marker::PhantomData<alloc::string::String>, alloc::string::String>::{closure#0}Line | Count | Source | 178 | 562 | .map_err(|e| deserializer.span_error(e))?; |
|
179 | | |
180 | 124k | deserializer.end().map_err(|e| deserializer.span_error(e))?; <ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value>::{closure#1}Line | Count | Source | 180 | 856 | deserializer.end().map_err(|e| deserializer.span_error(e))?; |
Unexecuted instantiation: <ron::options::Options>::from_str_seed::<core::marker::PhantomData<serde::de::ignored_any::IgnoredAny>, serde::de::ignored_any::IgnoredAny>::{closure#1}Unexecuted instantiation: <ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value>::{closure#1}Unexecuted instantiation: <ron::options::Options>::from_str_seed::<core::marker::PhantomData<alloc::string::String>, alloc::string::String>::{closure#1} |
181 | | |
182 | 124k | Ok(value) |
183 | 132k | } <ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value> Line | Count | Source | 170 | 10.7k | pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T> | 171 | 10.7k | where | 172 | 10.7k | S: de::DeserializeSeed<'a, Value = T>, | 173 | 10.7k | { | 174 | 10.7k | let mut deserializer = Deserializer::from_str_with_options(s, self)?; | 175 | | | 176 | 10.2k | let value = seed | 177 | 10.2k | .deserialize(&mut deserializer) | 178 | 10.2k | .map_err(|e| deserializer.span_error(e))?; | 179 | | | 180 | 3.40k | deserializer.end().map_err(|e| deserializer.span_error(e))?; | 181 | | | 182 | 2.54k | Ok(value) | 183 | 10.7k | } |
<ron::options::Options>::from_str_seed::<core::marker::PhantomData<serde::de::ignored_any::IgnoredAny>, serde::de::ignored_any::IgnoredAny> Line | Count | Source | 170 | 77.4k | pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T> | 171 | 77.4k | where | 172 | 77.4k | S: de::DeserializeSeed<'a, Value = T>, | 173 | 77.4k | { | 174 | 77.4k | let mut deserializer = Deserializer::from_str_with_options(s, self)?; | 175 | | | 176 | 77.4k | let value = seed | 177 | 77.4k | .deserialize(&mut deserializer) | 178 | 77.4k | .map_err(|e| deserializer.span_error(e))?; | 179 | | | 180 | 77.4k | deserializer.end().map_err(|e| deserializer.span_error(e))?; | 181 | | | 182 | 77.4k | Ok(value) | 183 | 77.4k | } |
<ron::options::Options>::from_str_seed::<core::marker::PhantomData<ron::value::Value>, ron::value::Value> Line | Count | Source | 170 | 15.0k | pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T> | 171 | 15.0k | where | 172 | 15.0k | S: de::DeserializeSeed<'a, Value = T>, | 173 | 15.0k | { | 174 | 15.0k | let mut deserializer = Deserializer::from_str_with_options(s, self)?; | 175 | | | 176 | 15.0k | let value = seed | 177 | 15.0k | .deserialize(&mut deserializer) | 178 | 15.0k | .map_err(|e| deserializer.span_error(e))?; | 179 | | | 180 | 14.9k | deserializer.end().map_err(|e| deserializer.span_error(e))?; | 181 | | | 182 | 14.9k | Ok(value) | 183 | 15.0k | } |
<ron::options::Options>::from_str_seed::<core::marker::PhantomData<alloc::string::String>, alloc::string::String> Line | Count | Source | 170 | 29.6k | pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T> | 171 | 29.6k | where | 172 | 29.6k | S: de::DeserializeSeed<'a, Value = T>, | 173 | 29.6k | { | 174 | 29.6k | let mut deserializer = Deserializer::from_str_with_options(s, self)?; | 175 | | | 176 | 29.6k | let value = seed | 177 | 29.6k | .deserialize(&mut deserializer) | 178 | 29.6k | .map_err(|e| deserializer.span_error(e))?; | 179 | | | 180 | 29.1k | deserializer.end().map_err(|e| deserializer.span_error(e))?; | 181 | | | 182 | 29.1k | Ok(value) | 183 | 29.6k | } |
|
184 | | |
185 | | /// A convenience function for building a deserializer |
186 | | /// and deserializing a value of type `T` from bytes |
187 | | /// and a seed. |
188 | 0 | pub fn from_bytes_seed<'a, S, T>(&self, s: &'a [u8], seed: S) -> SpannedResult<T> |
189 | 0 | where |
190 | 0 | S: de::DeserializeSeed<'a, Value = T>, |
191 | 0 | { |
192 | 0 | let mut deserializer = Deserializer::from_bytes_with_options(s, self)?; |
193 | | |
194 | 0 | let value = seed |
195 | 0 | .deserialize(&mut deserializer) |
196 | 0 | .map_err(|e| deserializer.span_error(e))?; |
197 | | |
198 | 0 | deserializer.end().map_err(|e| deserializer.span_error(e))?; |
199 | | |
200 | 0 | Ok(value) |
201 | 0 | } |
202 | | |
203 | | /// Serializes `value` into `writer`. |
204 | | /// |
205 | | /// This function does not generate any newlines or nice formatting; |
206 | | /// if you want that, you can use |
207 | | /// [`to_writer_pretty`][Self::to_writer_pretty] instead. |
208 | 0 | pub fn to_writer<W, T>(&self, writer: W, value: &T) -> Result<()> |
209 | 0 | where |
210 | 0 | W: fmt::Write, |
211 | 0 | T: ?Sized + ser::Serialize, |
212 | 0 | { |
213 | 0 | let mut s = Serializer::with_options(writer, None, self)?; |
214 | 0 | value.serialize(&mut s) |
215 | 0 | } |
216 | | |
217 | | /// Serializes `value` into `writer` in a pretty way. |
218 | 0 | pub fn to_writer_pretty<W, T>(&self, writer: W, value: &T, config: PrettyConfig) -> Result<()> |
219 | 0 | where |
220 | 0 | W: fmt::Write, |
221 | 0 | T: ?Sized + ser::Serialize, |
222 | 0 | { |
223 | 0 | let mut s = Serializer::with_options(writer, Some(config), self)?; |
224 | 0 | value.serialize(&mut s) |
225 | 0 | } |
226 | | |
227 | | /// Serializes `value` into `writer`. |
228 | | /// |
229 | | /// This function does not generate any newlines or nice formatting; |
230 | | /// if you want that, you can use |
231 | | /// [`to_io_writer_pretty`][Self::to_io_writer_pretty] instead. |
232 | | #[cfg(feature = "std")] |
233 | 0 | pub fn to_io_writer<W, T>(&self, writer: W, value: &T) -> Result<()> |
234 | 0 | where |
235 | 0 | W: io::Write, |
236 | 0 | T: ?Sized + ser::Serialize, |
237 | 0 | { |
238 | 0 | let mut adapter = Adapter { |
239 | 0 | writer, |
240 | 0 | error: Ok(()), |
241 | 0 | }; |
242 | 0 | let result = self.to_writer(&mut adapter, value); |
243 | 0 | adapter.error?; |
244 | 0 | result |
245 | 0 | } |
246 | | |
247 | | /// Serializes `value` into `writer` in a pretty way. |
248 | | #[cfg(feature = "std")] |
249 | 0 | pub fn to_io_writer_pretty<W, T>( |
250 | 0 | &self, |
251 | 0 | writer: W, |
252 | 0 | value: &T, |
253 | 0 | config: PrettyConfig, |
254 | 0 | ) -> Result<()> |
255 | 0 | where |
256 | 0 | W: io::Write, |
257 | 0 | T: ?Sized + ser::Serialize, |
258 | 0 | { |
259 | 0 | let mut adapter = Adapter { |
260 | 0 | writer, |
261 | 0 | error: Ok(()), |
262 | 0 | }; |
263 | 0 | let result = self.to_writer_pretty(&mut adapter, value, config); |
264 | 0 | adapter.error?; |
265 | 0 | result |
266 | 0 | } |
267 | | |
268 | | /// Serializes `value` and returns it as string. |
269 | | /// |
270 | | /// This function does not generate any newlines or nice formatting; |
271 | | /// if you want that, you can use |
272 | | /// [`to_string_pretty`][Self::to_string_pretty] instead. |
273 | 4.29M | pub fn to_string<T>(&self, value: &T) -> Result<String> |
274 | 4.29M | where |
275 | 4.29M | T: ?Sized + ser::Serialize, |
276 | 4.29M | { |
277 | 4.29M | let mut output = String::new(); |
278 | 4.29M | let mut s = Serializer::with_options(&mut output, None, self)?; |
279 | 4.29M | value.serialize(&mut s)?; |
280 | 4.29M | Ok(output) |
281 | 4.29M | } <ron::options::Options>::to_string::<ron::value::Value> Line | Count | Source | 273 | 2.54k | pub fn to_string<T>(&self, value: &T) -> Result<String> | 274 | 2.54k | where | 275 | 2.54k | T: ?Sized + ser::Serialize, | 276 | 2.54k | { | 277 | 2.54k | let mut output = String::new(); | 278 | 2.54k | let mut s = Serializer::with_options(&mut output, None, self)?; | 279 | 2.54k | value.serialize(&mut s)?; | 280 | 2.54k | Ok(output) | 281 | 2.54k | } |
Unexecuted instantiation: <ron::options::Options>::to_string::<_> <ron::options::Options>::to_string::<dyn erased_serde::ser::Serialize> Line | Count | Source | 273 | 348k | pub fn to_string<T>(&self, value: &T) -> Result<String> | 274 | 348k | where | 275 | 348k | T: ?Sized + ser::Serialize, | 276 | 348k | { | 277 | 348k | let mut output = String::new(); | 278 | 348k | let mut s = Serializer::with_options(&mut output, None, self)?; | 279 | 348k | value.serialize(&mut s)?; | 280 | 348k | Ok(output) | 281 | 348k | } |
<ron::options::Options>::to_string::<arbitrary::typed_data::BorrowedTypedSerdeData> Line | Count | Source | 273 | 29.7k | pub fn to_string<T>(&self, value: &T) -> Result<String> | 274 | 29.7k | where | 275 | 29.7k | T: ?Sized + ser::Serialize, | 276 | 29.7k | { | 277 | 29.7k | let mut output = String::new(); | 278 | 29.7k | let mut s = Serializer::with_options(&mut output, None, self)?; | 279 | 29.7k | value.serialize(&mut s)?; | 280 | 29.6k | Ok(output) | 281 | 29.7k | } |
<ron::options::Options>::to_string::<&str> Line | Count | Source | 273 | 3.42M | pub fn to_string<T>(&self, value: &T) -> Result<String> | 274 | 3.42M | where | 275 | 3.42M | T: ?Sized + ser::Serialize, | 276 | 3.42M | { | 277 | 3.42M | let mut output = String::new(); | 278 | 3.42M | let mut s = Serializer::with_options(&mut output, None, self)?; | 279 | 3.42M | value.serialize(&mut s)?; | 280 | 3.42M | Ok(output) | 281 | 3.42M | } |
<ron::options::Options>::to_string::<str> Line | Count | Source | 273 | 489k | pub fn to_string<T>(&self, value: &T) -> Result<String> | 274 | 489k | where | 275 | 489k | T: ?Sized + ser::Serialize, | 276 | 489k | { | 277 | 489k | let mut output = String::new(); | 278 | 489k | let mut s = Serializer::with_options(&mut output, None, self)?; | 279 | 489k | value.serialize(&mut s)?; | 280 | 489k | Ok(output) | 281 | 489k | } |
|
282 | | |
283 | | /// Serializes `value` in the recommended RON layout in a pretty way. |
284 | 16.8k | pub fn to_string_pretty<T>(&self, value: &T, config: PrettyConfig) -> Result<String> |
285 | 16.8k | where |
286 | 16.8k | T: ?Sized + ser::Serialize, |
287 | 16.8k | { |
288 | 16.8k | let mut output = String::new(); |
289 | 16.8k | let mut s = Serializer::with_options(&mut output, Some(config), self)?; |
290 | 16.8k | value.serialize(&mut s)?; |
291 | 15.0k | Ok(output) |
292 | 16.8k | } Unexecuted instantiation: <ron::options::Options>::to_string_pretty::<_> <ron::options::Options>::to_string_pretty::<arbitrary::typed_data::TypedSerdeData> Line | Count | Source | 284 | 16.8k | pub fn to_string_pretty<T>(&self, value: &T, config: PrettyConfig) -> Result<String> | 285 | 16.8k | where | 286 | 16.8k | T: ?Sized + ser::Serialize, | 287 | 16.8k | { | 288 | 16.8k | let mut output = String::new(); | 289 | 16.8k | let mut s = Serializer::with_options(&mut output, Some(config), self)?; | 290 | 16.8k | value.serialize(&mut s)?; | 291 | 15.0k | Ok(output) | 292 | 16.8k | } |
|
293 | | } |
294 | | |
295 | | // Adapter from io::Write to fmt::Write that keeps the error |
296 | | #[cfg(feature = "std")] |
297 | | struct Adapter<W: io::Write> { |
298 | | writer: W, |
299 | | error: io::Result<()>, |
300 | | } |
301 | | |
302 | | #[cfg(feature = "std")] |
303 | | impl<T: io::Write> fmt::Write for Adapter<T> { |
304 | 0 | fn write_str(&mut self, s: &str) -> fmt::Result { |
305 | 0 | match self.writer.write_all(s.as_bytes()) { |
306 | 0 | Ok(()) => Ok(()), |
307 | 0 | Err(e) => { |
308 | 0 | self.error = Err(e); |
309 | 0 | Err(fmt::Error) |
310 | | } |
311 | | } |
312 | 0 | } |
313 | | } |