1use std::convert::TryFrom;
21
22use chumsky::input::{Input, Stream};
23use chumsky::prelude::*;
24use chumsky::{Parser, error::Rich, extra};
25
26use crate::keyword::{
27 KW_CLASS_CONFIDENTIAL, KW_CLASS_PRIVATE, KW_CLASS_PUBLIC, KW_STATUS_CANCELLED,
28 KW_STATUS_COMPLETED, KW_STATUS_CONFIRMED, KW_STATUS_DRAFT, KW_STATUS_FINAL,
29 KW_STATUS_IN_PROCESS, KW_STATUS_NEEDS_ACTION, KW_STATUS_TENTATIVE,
30};
31use crate::parameter::{Encoding, Parameter, ValueType};
32use crate::property::PropertyKind;
33use crate::property::common::{Text, take_single_text, take_single_value};
34use crate::string_storage::{Segments, StringStorage};
35use crate::syntax::RawParameter;
36use crate::typed::{ParsedProperty, TypedError};
37use crate::value::{Value, ValueText, values_float_semicolon};
38
39#[derive(Debug, Clone)]
41pub struct Attachment<S: StringStorage> {
42 pub value: AttachmentValue<S>,
44 pub fmt_type: Option<S>,
46 pub encoding: Option<Encoding>,
48 pub x_parameters: Vec<RawParameter<S>>,
50 pub retained_parameters: Vec<Parameter<S>>,
52 pub span: S::Span,
54}
55
56#[derive(Debug, Clone)]
58pub enum AttachmentValue<S: StringStorage> {
59 Uri(S),
61 Binary(S),
63}
64
65impl<'src> TryFrom<ParsedProperty<'src>> for Attachment<Segments<'src>> {
66 type Error = Vec<TypedError<'src>>;
67
68 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
69 if !matches!(prop.kind, PropertyKind::Attach) {
70 return Err(vec![TypedError::PropertyUnexpectedKind {
71 expected: PropertyKind::Attach,
72 found: prop.kind,
73 span: prop.span,
74 }]);
75 }
76
77 let mut errors = Vec::new();
78
79 let mut fmt_type = None;
81 let mut encoding = None;
82 let mut x_parameters = Vec::new();
83 let mut retained_parameters = Vec::new();
84
85 for param in prop.parameters {
86 match param {
87 p @ Parameter::FormatType { .. } if fmt_type.is_some() => {
88 errors.push(TypedError::ParameterDuplicated {
89 span: p.span(),
90 parameter: p.kind().into(),
91 });
92 }
93 Parameter::FormatType { value, .. } => fmt_type = Some(value),
94
95 p @ Parameter::Encoding { .. } if encoding.is_some() => {
96 errors.push(TypedError::ParameterDuplicated {
97 span: p.span(),
98 parameter: p.kind().into(),
99 });
100 }
101 Parameter::Encoding { value, .. } => encoding = Some(value),
102
103 Parameter::XName(raw) => x_parameters.push(raw),
104 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
105 p => {
106 retained_parameters.push(p);
108 }
109 }
110 }
111
112 let value = match take_single_value(&PropertyKind::Attach, prop.value) {
114 Ok(Value::Binary { value, .. }) => Some(AttachmentValue::Binary(value)),
115 Ok(Value::Uri { value, .. }) => Some(AttachmentValue::Uri(value)),
116 Ok(v) => {
117 const EXPECTED: &[ValueType<String>] = &[ValueType::Uri, ValueType::Binary];
118 errors.push(TypedError::PropertyUnexpectedValue {
119 property: prop.kind,
120 expected: EXPECTED,
121 found: v.kind().into(),
122 span: v.span(),
123 });
124 None
125 }
126 Err(e) => {
127 errors.extend(e);
128 None
129 }
130 };
131
132 if !errors.is_empty() {
134 return Err(errors);
135 }
136
137 Ok(Attachment {
138 value: value.unwrap(), fmt_type,
140 encoding,
141 x_parameters,
142 retained_parameters,
143 span: prop.span,
144 })
145 }
146}
147
148impl Attachment<Segments<'_>> {
149 #[must_use]
151 pub fn to_owned(&self) -> Attachment<String> {
152 Attachment {
153 value: self.value.to_owned(),
154 fmt_type: self.fmt_type.as_ref().map(Segments::to_owned),
155 encoding: self.encoding,
156 x_parameters: self
157 .x_parameters
158 .iter()
159 .map(RawParameter::to_owned)
160 .collect(),
161 retained_parameters: self
162 .retained_parameters
163 .iter()
164 .map(Parameter::to_owned)
165 .collect(),
166 span: (),
167 }
168 }
169}
170
171impl AttachmentValue<Segments<'_>> {
172 #[must_use]
174 pub fn to_owned(&self) -> AttachmentValue<String> {
175 match self {
176 AttachmentValue::Uri(uri) => AttachmentValue::Uri(uri.to_owned()),
177 AttachmentValue::Binary(data) => AttachmentValue::Binary(data.to_owned()),
178 }
179 }
180}
181
182define_prop_value_enum! {
183 #[derive(Default)]
185 pub enum ClassificationValue {
186 #[default]
188 Public => KW_CLASS_PUBLIC,
189 Private => KW_CLASS_PRIVATE,
191 Confidential => KW_CLASS_CONFIDENTIAL,
193 }
194}
195
196#[derive(Debug, Clone)]
198pub struct Classification<S: StringStorage> {
199 pub value: ClassificationValue,
201 pub x_parameters: Vec<RawParameter<S>>,
203 pub retained_parameters: Vec<Parameter<S>>,
205 pub span: S::Span,
207}
208
209impl<'src> TryFrom<ParsedProperty<'src>> for Classification<Segments<'src>> {
210 type Error = Vec<TypedError<'src>>;
211
212 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
213 if !matches!(prop.kind, PropertyKind::Class) {
214 return Err(vec![TypedError::PropertyUnexpectedKind {
215 expected: PropertyKind::Class,
216 found: prop.kind,
217 span: prop.span,
218 }]);
219 }
220
221 let mut x_parameters = Vec::new();
222 let mut retained_parameters = Vec::new();
223
224 for param in prop.parameters {
225 match param {
226 Parameter::XName(raw) => x_parameters.push(raw),
227 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
228 p => {
229 retained_parameters.push(p);
231 }
232 }
233 }
234
235 let value_span = prop.value.span();
236 let text = take_single_text(&PropertyKind::Class, prop.value)?;
237 let value = text.try_into().map_err(|text| {
238 vec![TypedError::PropertyInvalidValue {
239 property: PropertyKind::Class,
240 value: format!("Invalid classification: {text}"),
241 span: value_span,
242 }]
243 })?;
244
245 Ok(Self {
246 value,
247 x_parameters,
248 retained_parameters,
249 span: prop.span,
250 })
251 }
252}
253
254impl Classification<Segments<'_>> {
255 #[must_use]
257 pub fn to_owned(&self) -> Classification<String> {
258 Classification {
259 value: self.value,
260 x_parameters: self
261 .x_parameters
262 .iter()
263 .map(RawParameter::to_owned)
264 .collect(),
265 retained_parameters: self
266 .retained_parameters
267 .iter()
268 .map(Parameter::to_owned)
269 .collect(),
270 span: (),
271 }
272 }
273}
274
275simple_property_wrapper!(
276 pub Comment<S> => Text
278);
279
280simple_property_wrapper!(
281 pub Description<S> => Text
283);
284
285impl Description<String> {
286 #[must_use]
288 pub fn new(value: String) -> Self {
289 Self {
290 inner: Text::new(value),
291 span: (),
292 }
293 }
294}
295
296#[derive(Debug, Clone)]
298pub struct Geo<S: StringStorage> {
299 pub lat: f64,
301 pub lon: f64,
303 pub x_parameters: Vec<RawParameter<S>>,
305 pub retained_parameters: Vec<Parameter<S>>,
307 pub span: S::Span,
309}
310
311impl<'src> TryFrom<ParsedProperty<'src>> for Geo<Segments<'src>> {
312 type Error = Vec<TypedError<'src>>;
313
314 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
315 if !matches!(prop.kind, PropertyKind::Geo) {
316 return Err(vec![TypedError::PropertyUnexpectedKind {
317 expected: PropertyKind::Geo,
318 found: prop.kind,
319 span: prop.span,
320 }]);
321 }
322
323 let mut x_parameters = Vec::new();
324 let mut retained_parameters = Vec::new();
325
326 for param in prop.parameters {
327 match param {
328 Parameter::XName(raw) => x_parameters.push(raw),
329 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
330 p => {
331 retained_parameters.push(p);
333 }
334 }
335 }
336
337 let value_span = prop.value.span();
338 let text = take_single_text(&PropertyKind::Geo, prop.value)?;
339
340 let stream = make_input(text.clone()); let parser = values_float_semicolon::<_, extra::Err<Rich<char, _>>>();
343
344 match parser.parse(stream).into_result() {
345 Ok(result) => {
346 if result.len() != 2 {
347 return Err(vec![TypedError::PropertyInvalidValue {
348 property: PropertyKind::Geo,
349 value: format!(
350 "Expected exactly 2 float values (lat;long), got {}",
351 result.len()
352 ),
353 span: value_span,
354 }]);
355 }
356
357 Ok(Geo {
358 lat: result.first().copied().unwrap_or_default(),
359 lon: result.get(1).copied().unwrap_or_default(),
360 x_parameters,
361 retained_parameters,
362 span: prop.span,
363 })
364 }
365 Err(_) => Err(vec![TypedError::PropertyInvalidValue {
366 property: PropertyKind::Geo,
367 value: format!("Expected 'lat;long' format with semicolon separator, got {text}"),
368 span: value_span,
369 }]),
370 }
371 }
372}
373
374impl Geo<Segments<'_>> {
375 #[must_use]
377 pub fn to_owned(&self) -> Geo<String> {
378 Geo {
379 lat: self.lat,
380 lon: self.lon,
381 x_parameters: self
382 .x_parameters
383 .iter()
384 .map(RawParameter::to_owned)
385 .collect(),
386 retained_parameters: self
387 .retained_parameters
388 .iter()
389 .map(Parameter::to_owned)
390 .collect(),
391 span: (),
392 }
393 }
394}
395
396simple_property_wrapper!(
397 pub Location<S> => Text
399);
400
401impl Location<String> {
402 #[must_use]
404 pub fn new(value: String) -> Self {
405 Self {
406 inner: Text::new(value),
407 span: (),
408 }
409 }
410}
411
412define_prop_value_enum! {
413 pub enum StatusValue {
419 Tentative => KW_STATUS_TENTATIVE,
421 Confirmed => KW_STATUS_CONFIRMED,
423 NeedsAction => KW_STATUS_NEEDS_ACTION,
425 Completed => KW_STATUS_COMPLETED,
427 InProcess => KW_STATUS_IN_PROCESS,
429 Draft => KW_STATUS_DRAFT,
431 Final => KW_STATUS_FINAL,
433 Cancelled => KW_STATUS_CANCELLED,
435 }
436}
437
438#[derive(Debug, Clone)]
440pub struct Status<S: StringStorage> {
441 pub value: StatusValue,
443 pub x_parameters: Vec<RawParameter<S>>,
445 pub retained_parameters: Vec<Parameter<S>>,
447 pub span: S::Span,
449}
450
451impl<'src> TryFrom<ParsedProperty<'src>> for Status<Segments<'src>> {
452 type Error = Vec<TypedError<'src>>;
453
454 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
455 if !matches!(prop.kind, PropertyKind::Status) {
456 return Err(vec![TypedError::PropertyUnexpectedKind {
457 expected: PropertyKind::Status,
458 found: prop.kind,
459 span: prop.span,
460 }]);
461 }
462
463 let mut x_parameters = Vec::new();
464 let mut retained_parameters = Vec::new();
465
466 for param in prop.parameters {
467 match param {
468 Parameter::XName(raw) => x_parameters.push(raw),
469 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
470 p => {
471 retained_parameters.push(p);
473 }
474 }
475 }
476
477 let value_span = prop.value.span();
478 let text = take_single_text(&PropertyKind::Status, prop.value)?;
479 let value = text.try_into().map_err(|text| {
480 vec![TypedError::PropertyInvalidValue {
481 property: PropertyKind::Status,
482 value: format!("Invalid status: {text}"),
483 span: value_span,
484 }]
485 })?;
486
487 Ok(Self {
488 value,
489 x_parameters,
490 retained_parameters,
491 span: prop.span,
492 })
493 }
494}
495
496impl Status<Segments<'_>> {
497 #[must_use]
499 pub fn to_owned(&self) -> Status<String> {
500 Status {
501 value: self.value,
502 x_parameters: self
503 .x_parameters
504 .iter()
505 .map(RawParameter::to_owned)
506 .collect(),
507 retained_parameters: self
508 .retained_parameters
509 .iter()
510 .map(Parameter::to_owned)
511 .collect(),
512 span: (),
513 }
514 }
515}
516
517impl Status<String> {
518 #[must_use]
520 pub fn new(value: StatusValue) -> Self {
521 Self {
522 value,
523 x_parameters: Vec::new(),
524 retained_parameters: Vec::new(),
525 span: (),
526 }
527 }
528}
529
530#[derive(Debug, Clone)]
535pub struct PercentComplete<S: StringStorage> {
536 pub value: u8,
538 pub x_parameters: Vec<RawParameter<S>>,
540 pub retained_parameters: Vec<Parameter<S>>,
542 pub span: S::Span,
544}
545
546impl<'src> TryFrom<ParsedProperty<'src>> for PercentComplete<Segments<'src>> {
547 type Error = Vec<TypedError<'src>>;
548
549 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
550 if !matches!(prop.kind, PropertyKind::PercentComplete) {
551 return Err(vec![TypedError::PropertyUnexpectedKind {
552 expected: PropertyKind::PercentComplete,
553 found: prop.kind,
554 span: prop.span,
555 }]);
556 }
557
558 let mut x_parameters = Vec::new();
559 let mut retained_parameters = Vec::new();
560
561 for param in prop.parameters {
562 match param {
563 Parameter::XName(raw) => x_parameters.push(raw),
564 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
565 p => {
566 retained_parameters.push(p);
568 }
569 }
570 }
571
572 let value_span = prop.value.span();
573 match take_single_value(&PropertyKind::PercentComplete, prop.value) {
574 #[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
575 Ok(Value::Integer {
576 values: mut ints, ..
577 }) if ints.len() == 1 => {
578 let i = ints.pop().unwrap();
579 if (0..=100).contains(&i) {
580 Ok(Self {
581 value: i as u8,
582 x_parameters,
583 retained_parameters,
584 span: prop.span,
585 })
586 } else {
587 Err(vec![TypedError::PropertyInvalidValue {
588 property: prop.kind,
589 value: "Percent complete must be 0-100".to_string(),
590 span: value_span,
591 }])
592 }
593 }
594 Ok(Value::Integer { .. }) => Err(vec![TypedError::PropertyInvalidValue {
595 property: prop.kind,
596 value: "Percent complete must be 0-100".to_string(),
597 span: value_span,
598 }]),
599 Ok(v) => {
600 const EXPECTED: &[ValueType<String>] = &[ValueType::Integer];
601 let span = v.span();
602 Err(vec![TypedError::PropertyUnexpectedValue {
603 property: prop.kind,
604 expected: EXPECTED,
605 found: v.kind().into(),
606 span,
607 }])
608 }
609 Err(e) => Err(e),
610 }
611 }
612}
613
614impl PercentComplete<Segments<'_>> {
615 #[must_use]
617 pub fn to_owned(&self) -> PercentComplete<String> {
618 PercentComplete {
619 value: self.value,
620 x_parameters: self
621 .x_parameters
622 .iter()
623 .map(RawParameter::to_owned)
624 .collect(),
625 retained_parameters: self
626 .retained_parameters
627 .iter()
628 .map(Parameter::to_owned)
629 .collect(),
630 span: (),
631 }
632 }
633}
634
635impl PercentComplete<String> {
636 #[must_use]
638 pub fn new(value: u8) -> Self {
639 Self {
640 value,
641 x_parameters: Vec::new(),
642 retained_parameters: Vec::new(),
643 span: (),
644 }
645 }
646}
647
648#[derive(Debug, Clone)]
653pub struct Priority<S: StringStorage> {
654 pub value: u8,
656 pub x_parameters: Vec<RawParameter<S>>,
658 pub retained_parameters: Vec<Parameter<S>>,
660 pub span: S::Span,
662}
663
664impl<'src> TryFrom<ParsedProperty<'src>> for Priority<Segments<'src>> {
665 type Error = Vec<TypedError<'src>>;
666
667 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
668 if !matches!(prop.kind, PropertyKind::Priority) {
669 return Err(vec![TypedError::PropertyUnexpectedKind {
670 expected: PropertyKind::Priority,
671 found: prop.kind,
672 span: prop.span,
673 }]);
674 }
675
676 let mut x_parameters = Vec::new();
677 let mut retained_parameters = Vec::new();
678
679 for param in prop.parameters {
680 match param {
681 Parameter::XName(raw) => x_parameters.push(raw),
682 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
683 p => {
684 retained_parameters.push(p);
686 }
687 }
688 }
689
690 let value_span = prop.value.span();
691 match take_single_value(&PropertyKind::Priority, prop.value) {
692 #[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
693 Ok(Value::Integer {
694 values: mut ints, ..
695 }) if ints.len() == 1 => {
696 let i = ints.pop().unwrap();
697 if (0..=9).contains(&i) {
698 Ok(Self {
699 value: i as u8,
700 x_parameters,
701 retained_parameters,
702 span: prop.span,
703 })
704 } else {
705 Err(vec![TypedError::PropertyInvalidValue {
706 property: prop.kind,
707 value: "Priority must be 0-9".to_string(),
708 span: value_span,
709 }])
710 }
711 }
712 Ok(Value::Integer { .. }) => Err(vec![TypedError::PropertyInvalidValue {
713 property: prop.kind,
714 value: "Priority must be 0-9".to_string(),
715 span: value_span,
716 }]),
717 Ok(v) => {
718 const EXPECTED: &[ValueType<String>] = &[ValueType::Integer];
719 let span = v.span();
720 Err(vec![TypedError::PropertyUnexpectedValue {
721 property: prop.kind,
722 expected: EXPECTED,
723 found: v.kind().into(),
724 span,
725 }])
726 }
727 Err(e) => Err(e),
728 }
729 }
730}
731
732impl Priority<Segments<'_>> {
733 #[must_use]
735 pub fn to_owned(&self) -> Priority<String> {
736 Priority {
737 value: self.value,
738 x_parameters: self
739 .x_parameters
740 .iter()
741 .map(RawParameter::to_owned)
742 .collect(),
743 retained_parameters: self
744 .retained_parameters
745 .iter()
746 .map(Parameter::to_owned)
747 .collect(),
748 span: (),
749 }
750 }
751}
752
753impl Priority<String> {
754 #[must_use]
756 pub fn new(value: u8) -> Self {
757 Self {
758 value,
759 x_parameters: Vec::new(),
760 retained_parameters: Vec::new(),
761 span: (),
762 }
763 }
764}
765
766#[derive(Debug, Clone)]
772pub struct Categories<S: StringStorage> {
773 pub values: Vec<ValueText<S>>,
775 pub language: Option<S>,
777 pub x_parameters: Vec<RawParameter<S>>,
779 pub retained_parameters: Vec<Parameter<S>>,
781 pub span: S::Span,
783}
784
785impl<'src> TryFrom<ParsedProperty<'src>> for Categories<Segments<'src>> {
786 type Error = Vec<TypedError<'src>>;
787
788 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
789 if !matches!(prop.kind, PropertyKind::Categories) {
790 return Err(vec![TypedError::PropertyUnexpectedKind {
791 expected: PropertyKind::Categories,
792 found: prop.kind,
793 span: prop.span,
794 }]);
795 }
796
797 let mut language = None;
798 let mut x_parameters = Vec::new();
799 let mut retained_parameters = Vec::new();
800
801 for param in prop.parameters {
802 match param {
803 p @ Parameter::Language { .. } if language.is_some() => {
804 return Err(vec![TypedError::ParameterDuplicated {
805 span: p.span(),
806 parameter: p.kind().into(),
807 }]);
808 }
809 Parameter::Language { value, .. } => language = Some(value),
810
811 Parameter::XName(raw) => x_parameters.push(raw),
812 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
813 p => {
814 retained_parameters.push(p);
816 }
817 }
818 }
819
820 let Value::Text { values, .. } = prop.value else {
821 const EXPECTED: &[ValueType<String>] = &[ValueType::Text];
822 let span = prop.value.span();
823 return Err(vec![TypedError::PropertyUnexpectedValue {
824 property: prop.kind,
825 expected: EXPECTED,
826 found: prop.value.kind().into(),
827 span,
828 }]);
829 };
830
831 Ok(Self {
832 values,
833 language,
834 x_parameters,
835 retained_parameters,
836 span: prop.span,
837 })
838 }
839}
840
841impl Categories<Segments<'_>> {
842 #[must_use]
844 pub fn to_owned(&self) -> Categories<String> {
845 Categories {
846 values: self.values.iter().map(ValueText::to_owned).collect(),
847 language: self.language.as_ref().map(Segments::to_owned),
848 x_parameters: self
849 .x_parameters
850 .iter()
851 .map(RawParameter::to_owned)
852 .collect(),
853 retained_parameters: self
854 .retained_parameters
855 .iter()
856 .map(Parameter::to_owned)
857 .collect(),
858 span: (),
859 }
860 }
861}
862
863#[derive(Debug, Clone)]
869pub struct Resources<S: StringStorage> {
870 pub values: Vec<ValueText<S>>,
872 pub language: Option<S>,
874 pub altrep: Option<S>,
876 pub x_parameters: Vec<RawParameter<S>>,
878 pub retained_parameters: Vec<Parameter<S>>,
880 pub span: S::Span,
882}
883
884impl<'src> TryFrom<ParsedProperty<'src>> for Resources<Segments<'src>> {
885 type Error = Vec<TypedError<'src>>;
886
887 fn try_from(prop: ParsedProperty<'src>) -> Result<Self, Self::Error> {
888 if !matches!(prop.kind, PropertyKind::Resources) {
889 return Err(vec![TypedError::PropertyUnexpectedKind {
890 expected: PropertyKind::Resources,
891 found: prop.kind,
892 span: prop.span,
893 }]);
894 }
895
896 let mut errors = Vec::new();
897 let mut language = None;
898 let mut altrep = None;
899 let mut x_parameters = Vec::new();
900 let mut retained_parameters = Vec::new();
901
902 for param in prop.parameters {
903 match param {
904 p @ Parameter::Language { .. } if language.is_some() => {
905 errors.push(TypedError::ParameterDuplicated {
906 span: p.span(),
907 parameter: p.kind().into(),
908 });
909 }
910 Parameter::Language { value, .. } => language = Some(value),
911
912 p @ Parameter::AlternateText { .. } if altrep.is_some() => {
913 errors.push(TypedError::ParameterDuplicated {
914 span: p.span(),
915 parameter: p.kind().into(),
916 });
917 }
918 Parameter::AlternateText { value, .. } => altrep = Some(value),
919
920 Parameter::XName(raw) => x_parameters.push(raw),
921 p @ Parameter::Unrecognized { .. } => retained_parameters.push(p),
922 p => {
923 retained_parameters.push(p);
925 }
926 }
927 }
928
929 if !errors.is_empty() {
930 return Err(errors);
931 }
932
933 let Value::Text { values, .. } = prop.value else {
934 const EXPECTED: &[ValueType<String>] = &[ValueType::Text];
935 let span = prop.value.span();
936 return Err(vec![TypedError::PropertyUnexpectedValue {
937 property: prop.kind,
938 expected: EXPECTED,
939 found: prop.value.kind().into(),
940 span,
941 }]);
942 };
943
944 Ok(Self {
945 values,
946 language,
947 altrep,
948 x_parameters,
949 retained_parameters,
950 span: prop.span,
951 })
952 }
953}
954
955impl Resources<Segments<'_>> {
956 #[must_use]
958 pub fn to_owned(&self) -> Resources<String> {
959 Resources {
960 values: self.values.iter().map(ValueText::to_owned).collect(),
961 language: self.language.as_ref().map(Segments::to_owned),
962 altrep: self.altrep.as_ref().map(Segments::to_owned),
963 x_parameters: self
964 .x_parameters
965 .iter()
966 .map(RawParameter::to_owned)
967 .collect(),
968 retained_parameters: self
969 .retained_parameters
970 .iter()
971 .map(Parameter::to_owned)
972 .collect(),
973 span: (),
974 }
975 }
976}
977
978simple_property_wrapper!(
979 pub Summary<S> => Text
981);
982
983impl Summary<String> {
984 #[must_use]
986 pub fn new(value: String) -> Self {
987 Self {
988 inner: Text::new(value),
989 span: (),
990 }
991 }
992}
993
994fn make_input(text: ValueText<Segments<'_>>) -> impl Input<'_, Token = char, Span = SimpleSpan> {
999 let eoi = text.span().into();
1001
1002 Stream::from_iter(text.into_spanned_chars().map(|(c, s)| (c, s.into())))
1004 .map(eoi, |(c, s)| (c, s))
1005}