1use std::convert::{TryFrom, TryInto};
2
3use super::{bson::RawBson, Error, RawArray, RawDocument, Result};
4use crate::{
5 oid::{self, ObjectId},
6 raw::{write_string, CStr, RawJavaScriptCodeWithScope},
7 spec::{BinarySubtype, ElementType},
8 Binary,
9 Bson,
10 DbPointer,
11 Decimal128,
12 RawArrayBuf,
13 RawDocumentBuf,
14 Regex,
15 Timestamp,
16};
17
18#[cfg(feature = "serde")]
19use serde::ser::SerializeStruct as _;
20
21#[derive(Debug, Clone, Copy, PartialEq)]
23pub enum RawBsonRef<'a> {
24 Double(f64),
26 String(&'a str),
28 Array(&'a RawArray),
30 Document(&'a RawDocument),
32 Boolean(bool),
34 Null,
36 RegularExpression(RawRegexRef<'a>),
38 JavaScriptCode(&'a str),
40 JavaScriptCodeWithScope(RawJavaScriptCodeWithScopeRef<'a>),
42 Int32(i32),
44 Int64(i64),
46 Timestamp(Timestamp),
48 Binary(RawBinaryRef<'a>),
50 ObjectId(oid::ObjectId),
52 DateTime(crate::DateTime),
54 Symbol(&'a str),
56 Decimal128(Decimal128),
58 Undefined,
60 MaxKey,
62 MinKey,
64 DbPointer(RawDbPointerRef<'a>),
66}
67
68impl<'a> RawBsonRef<'a> {
69 pub fn element_type(&self) -> ElementType {
71 match *self {
72 RawBsonRef::Double(..) => ElementType::Double,
73 RawBsonRef::String(..) => ElementType::String,
74 RawBsonRef::Array(..) => ElementType::Array,
75 RawBsonRef::Document(..) => ElementType::EmbeddedDocument,
76 RawBsonRef::Boolean(..) => ElementType::Boolean,
77 RawBsonRef::Null => ElementType::Null,
78 RawBsonRef::RegularExpression(..) => ElementType::RegularExpression,
79 RawBsonRef::JavaScriptCode(..) => ElementType::JavaScriptCode,
80 RawBsonRef::JavaScriptCodeWithScope(..) => ElementType::JavaScriptCodeWithScope,
81 RawBsonRef::Int32(..) => ElementType::Int32,
82 RawBsonRef::Int64(..) => ElementType::Int64,
83 RawBsonRef::Timestamp(..) => ElementType::Timestamp,
84 RawBsonRef::Binary(..) => ElementType::Binary,
85 RawBsonRef::ObjectId(..) => ElementType::ObjectId,
86 RawBsonRef::DateTime(..) => ElementType::DateTime,
87 RawBsonRef::Symbol(..) => ElementType::Symbol,
88 RawBsonRef::Decimal128(..) => ElementType::Decimal128,
89 RawBsonRef::Undefined => ElementType::Undefined,
90 RawBsonRef::MaxKey => ElementType::MaxKey,
91 RawBsonRef::MinKey => ElementType::MinKey,
92 RawBsonRef::DbPointer(..) => ElementType::DbPointer,
93 }
94 }
95
96 pub fn as_f64(self) -> Option<f64> {
99 match self {
100 RawBsonRef::Double(d) => Some(d),
101 _ => None,
102 }
103 }
104
105 pub fn as_str(self) -> Option<&'a str> {
108 match self {
109 RawBsonRef::String(s) => Some(s),
110 _ => None,
111 }
112 }
113
114 pub fn as_array(self) -> Option<&'a RawArray> {
117 match self {
118 RawBsonRef::Array(v) => Some(v),
119 _ => None,
120 }
121 }
122
123 pub fn as_document(self) -> Option<&'a RawDocument> {
126 match self {
127 RawBsonRef::Document(v) => Some(v),
128 _ => None,
129 }
130 }
131
132 pub fn as_bool(self) -> Option<bool> {
135 match self {
136 RawBsonRef::Boolean(v) => Some(v),
137 _ => None,
138 }
139 }
140
141 pub fn as_i32(self) -> Option<i32> {
144 match self {
145 RawBsonRef::Int32(v) => Some(v),
146 _ => None,
147 }
148 }
149
150 pub fn as_i64(self) -> Option<i64> {
153 match self {
154 RawBsonRef::Int64(v) => Some(v),
155 _ => None,
156 }
157 }
158
159 pub fn as_object_id(self) -> Option<oid::ObjectId> {
162 match self {
163 RawBsonRef::ObjectId(v) => Some(v),
164 _ => None,
165 }
166 }
167
168 pub fn as_binary(self) -> Option<RawBinaryRef<'a>> {
171 match self {
172 RawBsonRef::Binary(v) => Some(v),
173 _ => None,
174 }
175 }
176
177 pub fn as_regex(self) -> Option<RawRegexRef<'a>> {
180 match self {
181 RawBsonRef::RegularExpression(v) => Some(v),
182 _ => None,
183 }
184 }
185
186 pub fn as_datetime(self) -> Option<crate::DateTime> {
189 match self {
190 RawBsonRef::DateTime(v) => Some(v),
191 _ => None,
192 }
193 }
194
195 pub fn as_symbol(self) -> Option<&'a str> {
198 match self {
199 RawBsonRef::Symbol(v) => Some(v),
200 _ => None,
201 }
202 }
203
204 pub fn as_timestamp(self) -> Option<Timestamp> {
207 match self {
208 RawBsonRef::Timestamp(timestamp) => Some(timestamp),
209 _ => None,
210 }
211 }
212
213 pub fn as_null(self) -> Option<()> {
216 match self {
217 RawBsonRef::Null => Some(()),
218 _ => None,
219 }
220 }
221
222 pub fn as_db_pointer(self) -> Option<RawDbPointerRef<'a>> {
225 match self {
226 RawBsonRef::DbPointer(d) => Some(d),
227 _ => None,
228 }
229 }
230
231 pub fn as_javascript(self) -> Option<&'a str> {
234 match self {
235 RawBsonRef::JavaScriptCode(s) => Some(s),
236 _ => None,
237 }
238 }
239
240 pub fn as_javascript_with_scope(self) -> Option<RawJavaScriptCodeWithScopeRef<'a>> {
243 match self {
244 RawBsonRef::JavaScriptCodeWithScope(s) => Some(s),
245 _ => None,
246 }
247 }
248
249 #[inline]
250 pub(crate) fn append_to(self, dest: &mut Vec<u8>) {
251 match self {
252 Self::Int32(val) => dest.extend(val.to_le_bytes()),
253 Self::Int64(val) => dest.extend(val.to_le_bytes()),
254 Self::Double(val) => dest.extend(val.to_le_bytes()),
255 Self::Binary(b @ RawBinaryRef { subtype, bytes }) => {
256 let len = b.len();
257 dest.extend(len.to_le_bytes());
258 dest.push(subtype.into());
259 if let BinarySubtype::BinaryOld = subtype {
260 dest.extend((len - 4).to_le_bytes())
261 }
262 dest.extend(bytes);
263 }
264 Self::String(s) => write_string(dest, s),
265 Self::Array(raw_array) => dest.extend(raw_array.as_bytes()),
266 Self::Document(raw_document) => dest.extend(raw_document.as_bytes()),
267 Self::Boolean(b) => dest.push(b as u8),
268 Self::RegularExpression(re) => {
269 re.pattern.append_to(dest);
270 re.options.append_to(dest);
271 }
272 Self::JavaScriptCode(js) => write_string(dest, js),
273 Self::JavaScriptCodeWithScope(code_w_scope) => {
274 let len = code_w_scope.len();
275 dest.extend(len.to_le_bytes());
276 write_string(dest, code_w_scope.code);
277 dest.extend(code_w_scope.scope.as_bytes());
278 }
279 Self::Timestamp(ts) => dest.extend(ts.to_le_bytes()),
280 Self::ObjectId(oid) => dest.extend(oid.bytes()),
281 Self::DateTime(dt) => dest.extend(dt.timestamp_millis().to_le_bytes()),
282 Self::Symbol(s) => write_string(dest, s),
283 Self::Decimal128(d) => dest.extend(d.bytes()),
284 Self::DbPointer(dbp) => {
285 write_string(dest, dbp.namespace);
286 dest.extend(dbp.id.bytes());
287 }
288 Self::Null | Self::Undefined | Self::MinKey | Self::MaxKey => {}
289 }
290 }
291}
292
293impl<'a> From<RawBsonRef<'a>> for RawBson {
294 fn from(value: RawBsonRef<'a>) -> Self {
295 match value {
296 RawBsonRef::Double(d) => RawBson::Double(d),
297 RawBsonRef::String(s) => RawBson::String(s.to_string()),
298 RawBsonRef::Array(a) => RawBson::Array(a.to_owned()),
299 RawBsonRef::Document(d) => RawBson::Document(d.to_owned()),
300 RawBsonRef::Boolean(b) => RawBson::Boolean(b),
301 RawBsonRef::Null => RawBson::Null,
302 RawBsonRef::RegularExpression(re) => {
303 let mut chars: Vec<_> = re.options.as_str().chars().collect();
304 chars.sort_unstable();
305 let options: String = chars.into_iter().collect();
306 RawBson::RegularExpression(Regex {
307 pattern: re.pattern.into(),
308 options: super::CString::from_string_unchecked(options),
309 })
310 }
311 RawBsonRef::JavaScriptCode(c) => RawBson::JavaScriptCode(c.to_owned()),
312 RawBsonRef::JavaScriptCodeWithScope(c_w_s) => {
313 RawBson::JavaScriptCodeWithScope(RawJavaScriptCodeWithScope {
314 code: c_w_s.code.to_string(),
315 scope: c_w_s.scope.to_owned(),
316 })
317 }
318 RawBsonRef::Int32(i) => RawBson::Int32(i),
319 RawBsonRef::Int64(i) => RawBson::Int64(i),
320 RawBsonRef::Timestamp(t) => RawBson::Timestamp(t),
321 RawBsonRef::Binary(b) => RawBson::Binary(Binary {
322 bytes: b.bytes.to_vec(),
323 subtype: b.subtype,
324 }),
325 RawBsonRef::ObjectId(o) => RawBson::ObjectId(o),
326 RawBsonRef::DateTime(dt) => RawBson::DateTime(dt),
327 RawBsonRef::Symbol(s) => RawBson::Symbol(s.to_string()),
328 RawBsonRef::Decimal128(d) => RawBson::Decimal128(d),
329 RawBsonRef::Undefined => RawBson::Undefined,
330 RawBsonRef::MaxKey => RawBson::MaxKey,
331 RawBsonRef::MinKey => RawBson::MinKey,
332 RawBsonRef::DbPointer(d) => RawBson::DbPointer(DbPointer {
333 namespace: d.namespace.to_string(),
334 id: d.id,
335 }),
336 }
337 }
338}
339
340#[cfg(feature = "serde")]
341impl<'de: 'a, 'a> serde::Deserialize<'de> for RawBsonRef<'a> {
342 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
343 where
344 D: serde::Deserializer<'de>,
345 {
346 use super::serde::{bson_visitor::OwnedOrBorrowedRawBsonVisitor, OwnedOrBorrowedRawBson};
347 match deserializer.deserialize_newtype_struct(
348 crate::raw::RAW_BSON_NEWTYPE,
349 OwnedOrBorrowedRawBsonVisitor,
350 )? {
351 OwnedOrBorrowedRawBson::Borrowed(b) => Ok(b),
352 o => Err(serde::de::Error::custom(format!(
353 "RawBson must be deserialized from borrowed content, instead got {:?}",
354 o
355 ))),
356 }
357 }
358}
359
360#[cfg(feature = "serde")]
361impl serde::Serialize for RawBsonRef<'_> {
362 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
363 where
364 S: serde::Serializer,
365 {
366 match self {
367 RawBsonRef::Double(v) => serializer.serialize_f64(*v),
368 RawBsonRef::String(v) => serializer.serialize_str(v),
369 RawBsonRef::Array(v) => v.serialize(serializer),
370 RawBsonRef::Document(v) => v.serialize(serializer),
371 RawBsonRef::Boolean(v) => serializer.serialize_bool(*v),
372 RawBsonRef::Null => serializer.serialize_unit(),
373 RawBsonRef::Int32(v) => serializer.serialize_i32(*v),
374 RawBsonRef::Int64(v) => serializer.serialize_i64(*v),
375 RawBsonRef::ObjectId(oid) => oid.serialize(serializer),
376 RawBsonRef::DateTime(dt) => dt.serialize(serializer),
377 RawBsonRef::Binary(b) => b.serialize(serializer),
378 RawBsonRef::JavaScriptCode(c) => {
379 let mut state = serializer.serialize_struct("$code", 1)?;
380 state.serialize_field("$code", c)?;
381 state.end()
382 }
383 RawBsonRef::JavaScriptCodeWithScope(code_w_scope) => code_w_scope.serialize(serializer),
384 RawBsonRef::DbPointer(dbp) => dbp.serialize(serializer),
385 RawBsonRef::Symbol(s) => {
386 let mut state = serializer.serialize_struct("$symbol", 1)?;
387 state.serialize_field("$symbol", s)?;
388 state.end()
389 }
390 RawBsonRef::RegularExpression(re) => re.serialize(serializer),
391 RawBsonRef::Timestamp(t) => t.serialize(serializer),
392 RawBsonRef::Decimal128(d) => d.serialize(serializer),
393 RawBsonRef::Undefined => {
394 let mut state = serializer.serialize_struct("$undefined", 1)?;
395 state.serialize_field("$undefined", &true)?;
396 state.end()
397 }
398 RawBsonRef::MaxKey => {
399 let mut state = serializer.serialize_struct("$maxKey", 1)?;
400 state.serialize_field("$maxKey", &1)?;
401 state.end()
402 }
403 RawBsonRef::MinKey => {
404 let mut state = serializer.serialize_struct("$minKey", 1)?;
405 state.serialize_field("$minKey", &1)?;
406 state.end()
407 }
408 }
409 }
410}
411
412impl<'a> TryFrom<RawBsonRef<'a>> for Bson {
413 type Error = Error;
414
415 fn try_from(rawbson: RawBsonRef<'a>) -> Result<Bson> {
416 RawBson::from(rawbson).try_into()
417 }
418}
419
420impl From<i32> for RawBsonRef<'_> {
421 fn from(i: i32) -> Self {
422 RawBsonRef::Int32(i)
423 }
424}
425
426impl From<i64> for RawBsonRef<'_> {
427 fn from(i: i64) -> Self {
428 RawBsonRef::Int64(i)
429 }
430}
431
432impl<'a> From<&'a str> for RawBsonRef<'a> {
433 fn from(s: &'a str) -> Self {
434 RawBsonRef::String(s)
435 }
436}
437
438impl From<f64> for RawBsonRef<'_> {
439 fn from(f: f64) -> Self {
440 RawBsonRef::Double(f)
441 }
442}
443
444impl From<bool> for RawBsonRef<'_> {
445 fn from(b: bool) -> Self {
446 RawBsonRef::Boolean(b)
447 }
448}
449
450impl<'a> From<&'a RawDocumentBuf> for RawBsonRef<'a> {
451 fn from(d: &'a RawDocumentBuf) -> Self {
452 RawBsonRef::Document(d.as_ref())
453 }
454}
455
456impl<'a> From<&'a RawDocument> for RawBsonRef<'a> {
457 fn from(d: &'a RawDocument) -> Self {
458 RawBsonRef::Document(d)
459 }
460}
461
462impl<'a> From<&'a RawArray> for RawBsonRef<'a> {
463 fn from(a: &'a RawArray) -> Self {
464 RawBsonRef::Array(a)
465 }
466}
467
468impl<'a> From<&'a RawArrayBuf> for RawBsonRef<'a> {
469 fn from(a: &'a RawArrayBuf) -> Self {
470 RawBsonRef::Array(a)
471 }
472}
473
474impl From<crate::DateTime> for RawBsonRef<'_> {
475 fn from(dt: crate::DateTime) -> Self {
476 RawBsonRef::DateTime(dt)
477 }
478}
479
480impl From<Timestamp> for RawBsonRef<'_> {
481 fn from(ts: Timestamp) -> Self {
482 RawBsonRef::Timestamp(ts)
483 }
484}
485
486impl From<ObjectId> for RawBsonRef<'_> {
487 fn from(oid: ObjectId) -> Self {
488 RawBsonRef::ObjectId(oid)
489 }
490}
491
492impl From<Decimal128> for RawBsonRef<'_> {
493 fn from(d: Decimal128) -> Self {
494 RawBsonRef::Decimal128(d)
495 }
496}
497
498impl<'a> From<&'a RawBson> for RawBsonRef<'a> {
499 fn from(value: &'a RawBson) -> Self {
500 value.as_raw_bson_ref()
501 }
502}
503
504#[derive(Clone, Copy, Debug, PartialEq)]
506pub struct RawBinaryRef<'a> {
507 pub subtype: BinarySubtype,
509
510 pub bytes: &'a [u8],
512}
513
514impl RawBinaryRef<'_> {
515 pub fn to_binary(&self) -> Binary {
517 Binary {
518 subtype: self.subtype,
519 bytes: self.bytes.to_owned(),
520 }
521 }
522
523 pub(crate) fn len(&self) -> i32 {
524 match self.subtype {
525 BinarySubtype::BinaryOld => self.bytes.len() as i32 + 4,
526 _ => self.bytes.len() as i32,
527 }
528 }
529}
530
531#[cfg(feature = "serde")]
532impl<'de: 'a, 'a> serde::Deserialize<'de> for RawBinaryRef<'a> {
533 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
534 where
535 D: serde::Deserializer<'de>,
536 {
537 match RawBsonRef::deserialize(deserializer)? {
538 RawBsonRef::Binary(b) => Ok(b),
539 c => Err(serde::de::Error::custom(format!(
540 "expected binary, but got {:?} instead",
541 c
542 ))),
543 }
544 }
545}
546
547#[cfg(feature = "serde")]
548impl serde::Serialize for RawBinaryRef<'_> {
549 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
550 where
551 S: serde::Serializer,
552 {
553 if let BinarySubtype::Generic = self.subtype {
554 serializer.serialize_bytes(self.bytes)
555 } else if !serializer.is_human_readable() {
556 use serde_bytes::Bytes;
557
558 #[derive(serde::Serialize)]
559 struct BorrowedBinary<'a> {
560 bytes: &'a Bytes,
561
562 #[serde(rename = "subType")]
563 subtype: u8,
564 }
565
566 let mut state = serializer.serialize_struct("$binary", 1)?;
567 let body = BorrowedBinary {
568 bytes: Bytes::new(self.bytes),
569 subtype: self.subtype.into(),
570 };
571 state.serialize_field("$binary", &body)?;
572 state.end()
573 } else {
574 let mut state = serializer.serialize_struct("$binary", 1)?;
575 let body = crate::extjson::models::BinaryBody {
576 base64: crate::base64::encode(self.bytes),
577 subtype: hex::encode([self.subtype.into()]),
578 };
579 state.serialize_field("$binary", &body)?;
580 state.end()
581 }
582 }
583}
584
585impl<'a> From<RawBinaryRef<'a>> for RawBsonRef<'a> {
586 fn from(b: RawBinaryRef<'a>) -> Self {
587 RawBsonRef::Binary(b)
588 }
589}
590
591impl<'a> From<&'a Binary> for RawBsonRef<'a> {
592 fn from(bin: &'a Binary) -> Self {
593 bin.as_raw_binary().into()
594 }
595}
596
597#[derive(Clone, Copy, Debug, PartialEq)]
599pub struct RawRegexRef<'a> {
600 pub pattern: &'a CStr,
602
603 pub options: &'a CStr,
611}
612
613#[cfg(feature = "serde")]
614impl<'de: 'a, 'a> serde::Deserialize<'de> for RawRegexRef<'a> {
615 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
616 where
617 D: serde::Deserializer<'de>,
618 {
619 match RawBsonRef::deserialize(deserializer)? {
620 RawBsonRef::RegularExpression(b) => Ok(b),
621 c => Err(serde::de::Error::custom(format!(
622 "expected Regex, but got {:?} instead",
623 c
624 ))),
625 }
626 }
627}
628
629#[cfg(feature = "serde")]
630impl serde::Serialize for RawRegexRef<'_> {
631 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
632 where
633 S: serde::Serializer,
634 {
635 #[derive(serde::Serialize)]
636 struct BorrowedRegexBody<'a> {
637 pattern: &'a CStr,
638 options: &'a CStr,
639 }
640
641 let mut state = serializer.serialize_struct("$regularExpression", 1)?;
642 let body = BorrowedRegexBody {
643 pattern: self.pattern,
644 options: self.options,
645 };
646 state.serialize_field("$regularExpression", &body)?;
647 state.end()
648 }
649}
650
651impl<'a> From<RawRegexRef<'a>> for RawBsonRef<'a> {
652 fn from(re: RawRegexRef<'a>) -> Self {
653 RawBsonRef::RegularExpression(re)
654 }
655}
656
657#[derive(Clone, Copy, Debug, PartialEq)]
659pub struct RawJavaScriptCodeWithScopeRef<'a> {
660 pub code: &'a str,
662
663 pub scope: &'a RawDocument,
665}
666
667impl RawJavaScriptCodeWithScopeRef<'_> {
668 pub(crate) fn len(self) -> i32 {
669 4 + 4 + self.code.len() as i32 + 1 + self.scope.as_bytes().len() as i32
670 }
671}
672
673#[cfg(feature = "serde")]
674impl<'de: 'a, 'a> serde::Deserialize<'de> for RawJavaScriptCodeWithScopeRef<'a> {
675 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
676 where
677 D: serde::Deserializer<'de>,
678 {
679 match RawBsonRef::deserialize(deserializer)? {
680 RawBsonRef::JavaScriptCodeWithScope(b) => Ok(b),
681 c => Err(serde::de::Error::custom(format!(
682 "expected CodeWithScope, but got {:?} instead",
683 c
684 ))),
685 }
686 }
687}
688
689#[cfg(feature = "serde")]
690impl serde::Serialize for RawJavaScriptCodeWithScopeRef<'_> {
691 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
692 where
693 S: serde::Serializer,
694 {
695 let mut state = serializer.serialize_struct("$codeWithScope", 2)?;
696 state.serialize_field("$code", &self.code)?;
697 state.serialize_field("$scope", &self.scope)?;
698 state.end()
699 }
700}
701
702impl<'a> From<RawJavaScriptCodeWithScopeRef<'a>> for RawBsonRef<'a> {
703 fn from(code_w_scope: RawJavaScriptCodeWithScopeRef<'a>) -> Self {
704 RawBsonRef::JavaScriptCodeWithScope(code_w_scope)
705 }
706}
707
708#[derive(Debug, Clone, Copy, PartialEq)]
710pub struct RawDbPointerRef<'a> {
711 pub(crate) namespace: &'a str,
712 pub(crate) id: ObjectId,
713}
714
715#[cfg(feature = "serde")]
716impl<'de: 'a, 'a> serde::Deserialize<'de> for RawDbPointerRef<'a> {
717 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
718 where
719 D: serde::Deserializer<'de>,
720 {
721 match RawBsonRef::deserialize(deserializer)? {
722 RawBsonRef::DbPointer(b) => Ok(b),
723 c => Err(serde::de::Error::custom(format!(
724 "expected DbPointer, but got {:?} instead",
725 c
726 ))),
727 }
728 }
729}
730
731#[cfg(feature = "serde")]
732impl serde::Serialize for RawDbPointerRef<'_> {
733 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
734 where
735 S: serde::Serializer,
736 {
737 #[derive(serde::Serialize)]
738 struct BorrowedDbPointerBody<'a> {
739 #[serde(rename = "$ref")]
740 ref_ns: &'a str,
741
742 #[serde(rename = "$id")]
743 id: ObjectId,
744 }
745
746 let mut state = serializer.serialize_struct("$dbPointer", 1)?;
747 let body = BorrowedDbPointerBody {
748 ref_ns: self.namespace,
749 id: self.id,
750 };
751 state.serialize_field("$dbPointer", &body)?;
752 state.end()
753 }
754}