android_manifest/resources/
mipmap_or_drawable.rs

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