android_manifest/resources/
res_or_string.rs1use super::{parse_resource_with_type, Resource, ResourceType, ResourceVisitor, StringResource};
2use serde::{
3 de::{self, Visitor},
4 Deserialize, Deserializer, Serialize, Serializer,
5};
6use std::fmt;
7use std::io::{Read, Write};
8use yaserde::{YaDeserialize, YaSerialize};
9
10#[derive(Debug, PartialEq, Eq, Clone)]
12pub enum StringResourceOrString {
13 StringResource(Resource<StringResource>),
14 String(String),
15}
16
17impl StringResourceOrString {
18 pub fn resource(name: &str, package: Option<String>) -> StringResourceOrString {
19 Self::StringResource(StringResource::new(name, package))
20 }
21
22 pub fn string(s: &str) -> StringResourceOrString {
23 Self::String(s.to_string())
24 }
25}
26
27impl ToString for StringResourceOrString {
28 fn to_string(&self) -> String {
29 match self {
30 Self::StringResource(r) => r.to_string(),
31 Self::String(v) => v.clone(),
32 }
33 }
34}
35
36impl Serialize for StringResourceOrString {
37 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38 where
39 S: Serializer,
40 {
41 match self {
42 StringResourceOrString::StringResource(resource) => {
43 Serialize::serialize(&resource, serializer)
44 }
45 StringResourceOrString::String(value) => serializer.serialize_str(value),
46 }
47 }
48}
49
50impl YaSerialize for StringResourceOrString {
51 fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
52 match self {
53 StringResourceOrString::StringResource(resource) => {
54 YaSerialize::serialize(resource, writer)?;
55 }
56 StringResourceOrString::String(value) => {
57 let _ret = writer.write(xml::writer::XmlEvent::characters(value));
58 }
59 }
60 Ok(())
61 }
62
63 fn serialize_attributes(
64 &self,
65 attributes: Vec<xml::attribute::OwnedAttribute>,
66 namespace: xml::namespace::Namespace,
67 ) -> Result<
68 (
69 Vec<xml::attribute::OwnedAttribute>,
70 xml::namespace::Namespace,
71 ),
72 String,
73 > {
74 Ok((attributes, namespace))
75 }
76}
77
78struct StringResourceOrStringVisitor;
79
80impl<'de> Visitor<'de> for StringResourceOrStringVisitor {
81 type Value = StringResourceOrString;
82
83 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
84 formatter.write_str("an string resource in format @string/resource_name or string")
85 }
86
87 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
88 where
89 E: de::Error,
90 {
91 if v.is_empty() {
92 return Err(E::custom("value of attribute is empty"));
93 };
94 if v.starts_with('@') {
95 Ok(StringResourceOrString::StringResource(
96 ResourceVisitor::<StringResource>::new().visit_str(v)?,
97 ))
98 } else {
99 Ok(StringResourceOrString::String(v.to_owned()))
100 }
101 }
102}
103
104impl<'de> Deserialize<'de> for StringResourceOrString {
105 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106 where
107 D: Deserializer<'de>,
108 {
109 deserializer.deserialize_string(StringResourceOrStringVisitor)
110 }
111}
112
113impl YaDeserialize for StringResourceOrString {
114 fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
115 loop {
116 match reader.next_event()? {
117 xml::reader::XmlEvent::StartElement { .. } => {}
118 xml::reader::XmlEvent::Characters(text_content) => {
119 if text_content.is_empty() {
120 return Err("value of attribute is empty".to_string());
121 };
122 if text_content.starts_with('@') {
123 return Ok(StringResourceOrString::StringResource(
124 parse_resource_with_type(&text_content)?,
125 ));
126 } else {
127 return Ok(StringResourceOrString::String(text_content));
128 }
129 }
130 _ => {
131 break;
132 }
133 }
134 }
135 Err("Unable to parse attribute".to_string())
136 }
137}