1pub mod attributes;
30
31use std::borrow::Cow;
32use std::fmt::{self, Debug, Formatter};
33use std::iter::FusedIterator;
34use std::mem::replace;
35use std::ops::Deref;
36use std::str::from_utf8;
37
38#[cfg(feature = "encoding")]
39use oxixml_encoding::Encoding;
40
41use crate::XmlVersion;
42use crate::encoding::{Decoder, EncodingError};
43use crate::errors::{Error, IllFormedError};
44use crate::escape::{
45 EscapeError, escape, minimal_escape, normalize_xml10_eols, normalize_xml11_eols, parse_number,
46 partial_escape,
47};
48use crate::name::{LocalName, QName};
49use crate::utils::{self, name_len, trim_xml_end, trim_xml_start, write_cow_string};
50use attributes::{AttrError, Attribute, Attributes};
51
52#[derive(Clone, Eq, PartialEq)]
70pub struct BytesStart<'a> {
71 pub(crate) buf: Cow<'a, [u8]>,
73 pub(crate) name_len: usize,
75 decoder: Decoder,
77}
78
79impl<'a> BytesStart<'a> {
80 #[inline]
82 #[allow(dead_code)] pub(crate) const fn wrap(content: &'a [u8], name_len: usize, decoder: Decoder) -> Self {
84 BytesStart {
85 buf: Cow::Borrowed(content),
86 name_len,
87 decoder,
88 }
89 }
90
91 #[inline]
97 pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
98 let buf = str_cow_to_bytes(name);
99 BytesStart {
100 name_len: buf.len(),
101 buf,
102 decoder: Decoder::utf8(),
103 }
104 }
105
106 #[inline]
113 pub fn from_content<C: Into<Cow<'a, str>>>(content: C, name_len: usize) -> Self {
114 BytesStart {
115 buf: str_cow_to_bytes(content),
116 name_len,
117 decoder: Decoder::utf8(),
118 }
119 }
120
121 pub fn into_owned(self) -> BytesStart<'static> {
123 BytesStart {
124 buf: Cow::Owned(self.buf.into_owned()),
125 name_len: self.name_len,
126 decoder: self.decoder,
127 }
128 }
129
130 pub fn to_owned(&self) -> BytesStart<'static> {
132 BytesStart {
133 buf: Cow::Owned(self.buf.clone().into_owned()),
134 name_len: self.name_len,
135 decoder: self.decoder,
136 }
137 }
138
139 pub fn borrow(&self) -> BytesStart<'_> {
142 BytesStart {
143 buf: Cow::Borrowed(&self.buf),
144 name_len: self.name_len,
145 decoder: self.decoder,
146 }
147 }
148
149 #[inline]
151 pub fn to_end(&self) -> BytesEnd<'_> {
152 BytesEnd::from(self.name())
153 }
154
155 #[inline]
158 pub const fn decoder(&self) -> Decoder {
159 self.decoder
160 }
161
162 #[inline]
164 pub fn name(&self) -> QName<'_> {
165 QName(&self.buf[..self.name_len])
166 }
167
168 #[inline]
171 pub fn local_name(&self) -> LocalName<'_> {
172 self.name().into()
173 }
174
175 pub fn set_name(&mut self, name: &[u8]) -> &mut BytesStart<'a> {
181 let bytes = self.buf.to_mut();
182 bytes.splice(..self.name_len, name.iter().cloned());
183 self.name_len = name.len();
184 self
185 }
186}
187
188impl<'a> BytesStart<'a> {
190 pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
193 where
194 I: IntoIterator,
195 I::Item: Into<Attribute<'b>>,
196 {
197 self.extend_attributes(attributes);
198 self
199 }
200
201 pub fn extend_attributes<'b, I>(&mut self, attributes: I) -> &mut BytesStart<'a>
204 where
205 I: IntoIterator,
206 I::Item: Into<Attribute<'b>>,
207 {
208 for attr in attributes {
209 self.push_attribute(attr);
210 }
211 self
212 }
213
214 pub fn push_attribute<'b, A>(&mut self, attr: A)
216 where
217 A: Into<Attribute<'b>>,
218 {
219 self.buf.to_mut().push(b' ');
220 self.push_attr(attr.into());
221 }
222
223 pub fn clear_attributes(&mut self) -> &mut BytesStart<'a> {
225 self.buf.to_mut().truncate(self.name_len);
226 self
227 }
228
229 pub fn attributes(&self) -> Attributes<'_> {
231 Attributes::wrap(&self.buf, self.name_len, false, self.decoder)
232 }
233
234 pub fn html_attributes(&self) -> Attributes<'_> {
237 Attributes::wrap(&self.buf, self.name_len, true, self.decoder)
238 }
239
240 #[inline]
243 pub fn attributes_raw(&self) -> &[u8] {
244 &self.buf[self.name_len..]
245 }
246
247 pub fn try_get_attribute<N: AsRef<[u8]> + Sized>(
249 &'a self,
250 attr_name: N,
251 ) -> Result<Option<Attribute<'a>>, AttrError> {
252 for a in self.attributes().with_checks(false) {
253 let a = a?;
254 if a.key.as_ref() == attr_name.as_ref() {
255 return Ok(Some(a));
256 }
257 }
258 Ok(None)
259 }
260
261 pub(crate) fn push_attr<'b>(&mut self, attr: Attribute<'b>) {
263 let bytes = self.buf.to_mut();
264 bytes.extend_from_slice(attr.key.as_ref());
265 bytes.extend_from_slice(b"=\"");
266 bytes.extend_from_slice(attr.value.as_ref());
267 bytes.push(b'"');
268 }
269
270 pub(crate) fn push_newline(&mut self) {
273 self.buf.to_mut().push(b'\n');
274 }
275
276 pub(crate) fn push_indent(&mut self, indent: &[u8]) {
279 self.buf.to_mut().extend_from_slice(indent);
280 }
281}
282
283impl<'a> Debug for BytesStart<'a> {
284 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
285 write!(f, "BytesStart {{ buf: ")?;
286 write_cow_string(f, &self.buf)?;
287 write!(f, ", name_len: {} }}", self.name_len)
288 }
289}
290
291impl<'a> Deref for BytesStart<'a> {
292 type Target = [u8];
293
294 fn deref(&self) -> &[u8] {
295 &self.buf
296 }
297}
298
299#[cfg(feature = "arbitrary")]
303#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
304impl<'a> arbitrary::Arbitrary<'a> for BytesStart<'a> {
305 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
306 let s = <&str>::arbitrary(u)?;
307 if s.is_empty() || !s.chars().all(char::is_alphanumeric) {
308 return Err(arbitrary::Error::IncorrectFormat);
309 }
310 let mut result = Self::new(s);
311 result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?);
312 Ok(result)
313 }
314
315 fn size_hint(depth: usize) -> (usize, Option<usize>) {
316 <&str as arbitrary::Arbitrary>::size_hint(depth)
317 }
318}
319
320#[derive(Clone, Eq, PartialEq)]
335pub struct BytesEnd<'a> {
336 name: Cow<'a, [u8]>,
337}
338
339impl<'a> BytesEnd<'a> {
340 #[inline]
342 pub(crate) const fn wrap(name: Cow<'a, [u8]>) -> Self {
343 BytesEnd { name }
344 }
345
346 #[inline]
352 pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
353 Self::wrap(str_cow_to_bytes(name))
354 }
355
356 pub fn into_owned(self) -> BytesEnd<'static> {
358 BytesEnd {
359 name: Cow::Owned(self.name.into_owned()),
360 }
361 }
362
363 #[inline]
365 pub fn borrow(&self) -> BytesEnd<'_> {
366 BytesEnd {
367 name: Cow::Borrowed(&self.name),
368 }
369 }
370
371 #[inline]
373 pub fn name(&self) -> QName<'_> {
374 QName(&self.name)
375 }
376
377 #[inline]
379 pub fn local_name(&self) -> LocalName<'_> {
380 self.name().into()
381 }
382}
383
384impl<'a> Debug for BytesEnd<'a> {
385 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
386 write!(f, "BytesEnd {{ name: ")?;
387 write_cow_string(f, &self.name)?;
388 write!(f, " }}")
389 }
390}
391
392impl<'a> Deref for BytesEnd<'a> {
393 type Target = [u8];
394
395 fn deref(&self) -> &[u8] {
396 &self.name
397 }
398}
399
400impl<'a> From<QName<'a>> for BytesEnd<'a> {
401 #[inline]
402 fn from(name: QName<'a>) -> Self {
403 Self::wrap(name.into_inner().into())
404 }
405}
406
407#[cfg(feature = "arbitrary")]
411#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
412impl<'a> arbitrary::Arbitrary<'a> for BytesEnd<'a> {
413 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
414 Ok(Self::new(<&str>::arbitrary(u)?))
415 }
416
417 fn size_hint(depth: usize) -> (usize, Option<usize>) {
418 <&str as arbitrary::Arbitrary>::size_hint(depth)
419 }
420}
421
422#[derive(Clone, Eq, PartialEq)]
436pub struct BytesText<'a> {
437 content: Cow<'a, [u8]>,
439 decoder: Decoder,
441}
442
443impl<'a> BytesText<'a> {
444 #[inline]
446 pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
447 Self {
448 content: content.into(),
449 decoder,
450 }
451 }
452
453 #[inline]
459 pub fn from_escaped<C: Into<Cow<'a, str>>>(content: C) -> Self {
460 Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
461 }
462
463 #[inline]
467 pub fn new(content: &'a str) -> Self {
468 Self::from_escaped(escape(content))
469 }
470
471 #[inline]
473 pub fn into_owned(self) -> BytesText<'static> {
474 BytesText {
475 content: self.content.into_owned().into(),
476 decoder: self.decoder,
477 }
478 }
479
480 #[inline]
482 pub fn into_inner(self) -> Cow<'a, [u8]> {
483 self.content
484 }
485
486 #[inline]
488 pub fn borrow(&self) -> BytesText<'_> {
489 BytesText {
490 content: Cow::Borrowed(&self.content),
491 decoder: self.decoder,
492 }
493 }
494
495 pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
500 self.decoder.decode_cow(&self.content)
501 }
502
503 pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
505 self.decoder.content(&self.content, normalize_xml10_eols)
506 }
507
508 pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
510 self.decoder.content(&self.content, normalize_xml11_eols)
511 }
512
513 #[inline]
515 pub fn xml_content(&self, version: XmlVersion) -> Result<Cow<'a, str>, EncodingError> {
516 match version {
517 XmlVersion::Explicit1_1 => self.xml11_content(),
518 _ => self.xml10_content(),
519 }
520 }
521
522 #[inline]
524 pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
525 self.xml10_content()
526 }
527
528 pub fn inplace_trim_start(&mut self) -> bool {
531 self.content = trim_cow(
532 replace(&mut self.content, Cow::Borrowed(b"")),
533 trim_xml_start,
534 );
535 self.content.is_empty()
536 }
537
538 pub fn inplace_trim_end(&mut self) -> bool {
541 self.content = trim_cow(replace(&mut self.content, Cow::Borrowed(b"")), trim_xml_end);
542 self.content.is_empty()
543 }
544}
545
546impl<'a> Debug for BytesText<'a> {
547 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
548 write!(f, "BytesText {{ content: ")?;
549 write_cow_string(f, &self.content)?;
550 write!(f, " }}")
551 }
552}
553
554impl<'a> Deref for BytesText<'a> {
555 type Target = [u8];
556
557 fn deref(&self) -> &[u8] {
558 &self.content
559 }
560}
561
562#[cfg(feature = "arbitrary")]
567#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
568impl<'a> arbitrary::Arbitrary<'a> for BytesText<'a> {
569 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
570 let s = <&str>::arbitrary(u)?;
571 if !s.chars().all(char::is_alphanumeric) {
572 return Err(arbitrary::Error::IncorrectFormat);
573 }
574 Ok(Self::new(s))
575 }
576
577 fn size_hint(depth: usize) -> (usize, Option<usize>) {
578 <&str as arbitrary::Arbitrary>::size_hint(depth)
579 }
580}
581
582#[derive(Clone, Eq, PartialEq)]
595pub struct BytesCData<'a> {
596 content: Cow<'a, [u8]>,
597 decoder: Decoder,
599}
600
601impl<'a> BytesCData<'a> {
602 #[inline]
604 pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
605 Self {
606 content: content.into(),
607 decoder,
608 }
609 }
610
611 #[inline]
618 pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
619 Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
620 }
621
622 #[inline]
636 pub const fn escaped(content: &'a str) -> CDataIterator<'a> {
637 CDataIterator {
638 inner: utils::CDataIterator::new(content),
639 }
640 }
641
642 #[inline]
644 pub fn into_owned(self) -> BytesCData<'static> {
645 BytesCData {
646 content: self.content.into_owned().into(),
647 decoder: self.decoder,
648 }
649 }
650
651 #[inline]
653 pub fn into_inner(self) -> Cow<'a, [u8]> {
654 self.content
655 }
656
657 #[inline]
659 pub fn borrow(&self) -> BytesCData<'_> {
660 BytesCData {
661 content: Cow::Borrowed(&self.content),
662 decoder: self.decoder,
663 }
664 }
665
666 pub fn escape(self) -> Result<BytesText<'a>, EncodingError> {
669 let decoded = self.decode()?;
670 Ok(BytesText::wrap(
671 match escape(decoded) {
672 Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
673 Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
674 },
675 Decoder::utf8(),
676 ))
677 }
678
679 pub fn partial_escape(self) -> Result<BytesText<'a>, EncodingError> {
682 let decoded = self.decode()?;
683 Ok(BytesText::wrap(
684 match partial_escape(decoded) {
685 Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
686 Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
687 },
688 Decoder::utf8(),
689 ))
690 }
691
692 pub fn minimal_escape(self) -> Result<BytesText<'a>, EncodingError> {
695 let decoded = self.decode()?;
696 Ok(BytesText::wrap(
697 match minimal_escape(decoded) {
698 Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
699 Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
700 },
701 Decoder::utf8(),
702 ))
703 }
704
705 pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
708 self.decoder.decode_cow(&self.content)
709 }
710
711 pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
713 self.decoder.content(&self.content, normalize_xml10_eols)
714 }
715
716 pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
718 self.decoder.content(&self.content, normalize_xml11_eols)
719 }
720
721 #[inline]
723 pub fn xml_content(&self, version: XmlVersion) -> Result<Cow<'a, str>, EncodingError> {
724 match version {
725 XmlVersion::Explicit1_1 => self.xml11_content(),
726 _ => self.xml10_content(),
727 }
728 }
729
730 #[inline]
732 pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
733 self.xml10_content()
734 }
735}
736
737impl<'a> Debug for BytesCData<'a> {
738 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
739 write!(f, "BytesCData {{ content: ")?;
740 write_cow_string(f, &self.content)?;
741 write!(f, " }}")
742 }
743}
744
745impl<'a> Deref for BytesCData<'a> {
746 type Target = [u8];
747
748 fn deref(&self) -> &[u8] {
749 &self.content
750 }
751}
752
753#[cfg(feature = "arbitrary")]
757#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
758impl<'a> arbitrary::Arbitrary<'a> for BytesCData<'a> {
759 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
760 Ok(Self::new(<&str>::arbitrary(u)?))
761 }
762
763 fn size_hint(depth: usize) -> (usize, Option<usize>) {
764 <&str as arbitrary::Arbitrary>::size_hint(depth)
765 }
766}
767
768#[derive(Debug, Clone)]
770pub struct CDataIterator<'a> {
771 inner: utils::CDataIterator<'a>,
772}
773
774impl<'a> Iterator for CDataIterator<'a> {
775 type Item = BytesCData<'a>;
776
777 fn next(&mut self) -> Option<BytesCData<'a>> {
778 self.inner
779 .next()
780 .map(|slice| BytesCData::wrap(slice.as_bytes(), Decoder::utf8()))
781 }
782}
783
784impl FusedIterator for CDataIterator<'_> {}
785
786#[derive(Clone, Eq, PartialEq)]
802pub struct BytesPI<'a> {
803 content: BytesStart<'a>,
804}
805
806impl<'a> BytesPI<'a> {
807 #[inline]
809 #[allow(dead_code)] pub(crate) const fn wrap(content: &'a [u8], target_len: usize, decoder: Decoder) -> Self {
811 Self {
812 content: BytesStart::wrap(content, target_len, decoder),
813 }
814 }
815
816 #[inline]
822 pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
823 let buf = str_cow_to_bytes(content);
824 let name_len = name_len(&buf);
825 Self {
826 content: BytesStart {
827 buf,
828 name_len,
829 decoder: Decoder::utf8(),
830 },
831 }
832 }
833
834 #[inline]
836 pub fn into_owned(self) -> BytesPI<'static> {
837 BytesPI {
838 content: self.content.into_owned(),
839 }
840 }
841
842 #[inline]
844 pub fn into_inner(self) -> Cow<'a, [u8]> {
845 self.content.buf
846 }
847
848 #[inline]
850 pub fn borrow(&self) -> BytesPI<'_> {
851 BytesPI {
852 content: self.content.borrow(),
853 }
854 }
855
856 #[inline]
859 pub fn target(&self) -> &[u8] {
860 self.content.name().0
861 }
862
863 #[inline]
866 pub fn content(&self) -> &[u8] {
867 self.content.attributes_raw()
868 }
869
870 #[inline]
886 pub fn attributes(&self) -> Attributes<'_> {
887 self.content.attributes()
888 }
889}
890
891impl<'a> Debug for BytesPI<'a> {
892 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
893 write!(f, "BytesPI {{ content: ")?;
894 write_cow_string(f, &self.content.buf)?;
895 write!(f, " }}")
896 }
897}
898
899impl<'a> Deref for BytesPI<'a> {
900 type Target = [u8];
901
902 fn deref(&self) -> &[u8] {
903 &self.content
904 }
905}
906
907#[cfg(feature = "arbitrary")]
911#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
912impl<'a> arbitrary::Arbitrary<'a> for BytesPI<'a> {
913 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
914 Ok(Self::new(<&str>::arbitrary(u)?))
915 }
916
917 fn size_hint(depth: usize) -> (usize, Option<usize>) {
918 <&str as arbitrary::Arbitrary>::size_hint(depth)
919 }
920}
921
922#[derive(Clone, Debug, Eq, PartialEq)]
935pub struct BytesDecl<'a> {
936 content: BytesStart<'a>,
937}
938
939impl<'a> BytesDecl<'a> {
940 pub fn new(
946 version: &str,
947 encoding: Option<&str>,
948 standalone: Option<&str>,
949 ) -> BytesDecl<'static> {
950 let encoding_attr_len = if let Some(xs) = encoding {
952 12 + xs.len()
953 } else {
954 0
955 };
956 let standalone_attr_len = if let Some(xs) = standalone {
958 14 + xs.len()
959 } else {
960 0
961 };
962 let mut buf = String::with_capacity(14 + encoding_attr_len + standalone_attr_len);
964
965 buf.push_str("xml version=\"");
966 buf.push_str(version);
967
968 if let Some(encoding_val) = encoding {
969 buf.push_str("\" encoding=\"");
970 buf.push_str(encoding_val);
971 }
972
973 if let Some(standalone_val) = standalone {
974 buf.push_str("\" standalone=\"");
975 buf.push_str(standalone_val);
976 }
977 buf.push('"');
978
979 BytesDecl {
980 content: BytesStart::from_content(buf, 3),
981 }
982 }
983
984 pub const fn from_start(start: BytesStart<'a>) -> Self {
986 Self { content: start }
987 }
988
989 pub fn version(&self) -> Result<Cow<'_, [u8]>, Error> {
1007 match self.content.attributes().with_checks(false).next() {
1008 Some(Ok(a)) if a.key.as_ref() == b"version" => Ok(a.value),
1009 Some(Ok(a)) => {
1010 let found = from_utf8(a.key.as_ref())
1011 .map_err(|_| IllFormedError::MissingDeclVersion(None))?
1012 .to_string();
1013 Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(
1014 found,
1015 ))))
1016 }
1017 Some(Err(e)) => Err(e.into()),
1018 None => Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))),
1019 }
1020 }
1021
1022 pub fn encoding(&self) -> Option<Result<Cow<'_, [u8]>, AttrError>> {
1025 self.content
1026 .try_get_attribute("encoding")
1027 .map(|a| a.map(|a| a.value))
1028 .transpose()
1029 }
1030
1031 pub fn standalone(&self) -> Option<Result<Cow<'_, [u8]>, AttrError>> {
1034 self.content
1035 .try_get_attribute("standalone")
1036 .map(|a| a.map(|a| a.value))
1037 .transpose()
1038 }
1039
1040 pub fn xml_version(&self) -> Result<XmlVersion, Error> {
1045 let v = self.version()?;
1046 match v.as_ref() {
1047 b"1.0" => Ok(XmlVersion::Explicit1_0),
1048 b"1.1" => Ok(XmlVersion::Explicit1_1),
1049 _ => Err(Error::IllFormed(IllFormedError::UnknownVersion)),
1050 }
1051 }
1052
1053 #[cfg(feature = "encoding")]
1066 #[cfg_attr(docsrs, doc(cfg(feature = "encoding")))]
1067 pub fn encoder(&self) -> Option<Encoding> {
1068 self.encoding()
1069 .and_then(|e| e.ok())
1070 .and_then(|e| std::str::from_utf8(&e).ok().and_then(Encoding::for_label))
1071 }
1072
1073 pub fn into_owned(self) -> BytesDecl<'static> {
1075 BytesDecl {
1076 content: self.content.into_owned(),
1077 }
1078 }
1079
1080 #[inline]
1082 pub fn borrow(&self) -> BytesDecl<'_> {
1083 BytesDecl {
1084 content: self.content.borrow(),
1085 }
1086 }
1087}
1088
1089impl<'a> Deref for BytesDecl<'a> {
1090 type Target = [u8];
1091
1092 fn deref(&self) -> &[u8] {
1093 &self.content
1094 }
1095}
1096
1097#[cfg(feature = "arbitrary")]
1101#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
1102impl<'a> arbitrary::Arbitrary<'a> for BytesDecl<'a> {
1103 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1104 Ok(Self::new(
1105 <&str>::arbitrary(u)?,
1106 Option::<&str>::arbitrary(u)?,
1107 Option::<&str>::arbitrary(u)?,
1108 ))
1109 }
1110
1111 fn size_hint(depth: usize) -> (usize, Option<usize>) {
1112 <&str as arbitrary::Arbitrary>::size_hint(depth)
1113 }
1114}
1115
1116#[derive(Clone, Eq, PartialEq)]
1129pub struct BytesRef<'a> {
1130 content: Cow<'a, [u8]>,
1131 decoder: Decoder,
1133}
1134
1135impl<'a> BytesRef<'a> {
1136 #[inline]
1138 #[allow(dead_code)] pub(crate) const fn wrap(content: &'a [u8], decoder: Decoder) -> Self {
1140 Self {
1141 content: Cow::Borrowed(content),
1142 decoder,
1143 }
1144 }
1145
1146 #[inline]
1152 pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
1153 Self {
1154 content: str_cow_to_bytes(name),
1155 decoder: Decoder::utf8(),
1156 }
1157 }
1158
1159 pub fn into_owned(self) -> BytesRef<'static> {
1161 BytesRef {
1162 content: Cow::Owned(self.content.into_owned()),
1163 decoder: self.decoder,
1164 }
1165 }
1166
1167 #[inline]
1169 pub fn into_inner(self) -> Cow<'a, [u8]> {
1170 self.content
1171 }
1172
1173 #[inline]
1175 pub fn borrow(&self) -> BytesRef<'_> {
1176 BytesRef {
1177 content: Cow::Borrowed(&self.content),
1178 decoder: self.decoder,
1179 }
1180 }
1181
1182 pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
1184 self.decoder.decode_cow(&self.content)
1185 }
1186
1187 pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
1189 self.decoder.content(&self.content, normalize_xml10_eols)
1190 }
1191
1192 pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
1194 self.decoder.content(&self.content, normalize_xml11_eols)
1195 }
1196
1197 #[inline]
1199 pub fn xml_content(&self, version: XmlVersion) -> Result<Cow<'a, str>, EncodingError> {
1200 match version {
1201 XmlVersion::Explicit1_1 => self.xml11_content(),
1202 _ => self.xml10_content(),
1203 }
1204 }
1205
1206 #[inline]
1208 pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
1209 self.xml10_content()
1210 }
1211
1212 pub fn is_char_ref(&self) -> bool {
1221 matches!(self.content.first(), Some(b'#'))
1222 }
1223
1224 pub fn resolve_char_ref(&self) -> Result<Option<char>, Error> {
1234 if let Some(num) = self.decode()?.strip_prefix('#') {
1235 let ch = parse_number(num).map_err(EscapeError::InvalidCharRef)?;
1236 return Ok(Some(ch));
1237 }
1238 Ok(None)
1239 }
1240}
1241
1242impl<'a> Debug for BytesRef<'a> {
1243 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1244 write!(f, "BytesRef {{ content: ")?;
1245 write_cow_string(f, &self.content)?;
1246 write!(f, " }}")
1247 }
1248}
1249
1250impl<'a> Deref for BytesRef<'a> {
1251 type Target = [u8];
1252
1253 fn deref(&self) -> &[u8] {
1254 &self.content
1255 }
1256}
1257
1258#[cfg(feature = "arbitrary")]
1262#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
1263impl<'a> arbitrary::Arbitrary<'a> for BytesRef<'a> {
1264 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1265 Ok(Self::new(<&str>::arbitrary(u)?))
1266 }
1267
1268 fn size_hint(depth: usize) -> (usize, Option<usize>) {
1269 <&str as arbitrary::Arbitrary>::size_hint(depth)
1270 }
1271}
1272
1273#[derive(Clone, Debug, Eq, PartialEq)]
1277#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1278pub enum Event<'a> {
1279 Start(BytesStart<'a>),
1281 End(BytesEnd<'a>),
1283 Empty(BytesStart<'a>),
1285 Text(BytesText<'a>),
1287 CData(BytesCData<'a>),
1289 Comment(BytesText<'a>),
1291 Decl(BytesDecl<'a>),
1293 PI(BytesPI<'a>),
1295 DocType(BytesText<'a>),
1297 GeneralRef(BytesRef<'a>),
1300 Eof,
1302}
1303
1304impl<'a> Event<'a> {
1305 pub fn into_owned(self) -> Event<'static> {
1308 match self {
1309 Event::Start(e) => Event::Start(e.into_owned()),
1310 Event::End(e) => Event::End(e.into_owned()),
1311 Event::Empty(e) => Event::Empty(e.into_owned()),
1312 Event::Text(e) => Event::Text(e.into_owned()),
1313 Event::Comment(e) => Event::Comment(e.into_owned()),
1314 Event::CData(e) => Event::CData(e.into_owned()),
1315 Event::Decl(e) => Event::Decl(e.into_owned()),
1316 Event::PI(e) => Event::PI(e.into_owned()),
1317 Event::DocType(e) => Event::DocType(e.into_owned()),
1318 Event::GeneralRef(e) => Event::GeneralRef(e.into_owned()),
1319 Event::Eof => Event::Eof,
1320 }
1321 }
1322
1323 #[inline]
1325 pub fn borrow(&self) -> Event<'_> {
1326 match self {
1327 Event::Start(e) => Event::Start(e.borrow()),
1328 Event::End(e) => Event::End(e.borrow()),
1329 Event::Empty(e) => Event::Empty(e.borrow()),
1330 Event::Text(e) => Event::Text(e.borrow()),
1331 Event::Comment(e) => Event::Comment(e.borrow()),
1332 Event::CData(e) => Event::CData(e.borrow()),
1333 Event::Decl(e) => Event::Decl(e.borrow()),
1334 Event::PI(e) => Event::PI(e.borrow()),
1335 Event::DocType(e) => Event::DocType(e.borrow()),
1336 Event::GeneralRef(e) => Event::GeneralRef(e.borrow()),
1337 Event::Eof => Event::Eof,
1338 }
1339 }
1340}
1341
1342impl<'a> Deref for Event<'a> {
1343 type Target = [u8];
1344
1345 fn deref(&self) -> &[u8] {
1346 match *self {
1347 Event::Start(ref e) | Event::Empty(ref e) => e,
1348 Event::End(ref e) => e,
1349 Event::Text(ref e) => e,
1350 Event::Decl(ref e) => e,
1351 Event::PI(ref e) => e,
1352 Event::CData(ref e) => e,
1353 Event::Comment(ref e) => e,
1354 Event::DocType(ref e) => e,
1355 Event::GeneralRef(ref e) => e,
1356 Event::Eof => &[],
1357 }
1358 }
1359}
1360
1361impl<'a> AsRef<Event<'a>> for Event<'a> {
1362 fn as_ref(&self) -> &Event<'a> {
1363 self
1364 }
1365}
1366
1367#[inline]
1370fn str_cow_to_bytes<'a, C: Into<Cow<'a, str>>>(content: C) -> Cow<'a, [u8]> {
1371 match content.into() {
1372 Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
1373 Cow::Owned(s) => Cow::Owned(s.into_bytes()),
1374 }
1375}
1376
1377fn trim_cow<'a, F>(value: Cow<'a, [u8]>, trim: F) -> Cow<'a, [u8]>
1378where
1379 F: FnOnce(&[u8]) -> &[u8],
1380{
1381 match value {
1382 Cow::Borrowed(bytes) => Cow::Borrowed(trim(bytes)),
1383 Cow::Owned(mut bytes) => {
1384 let trimmed = trim(&bytes);
1385 if trimmed.len() != bytes.len() {
1386 bytes = trimmed.to_vec();
1387 }
1388 Cow::Owned(bytes)
1389 }
1390 }
1391}
1392
1393#[cfg(test)]
1394mod tests;