android_manifest/resources/
any.rs

1use super::{
2    parse_resource, DrawableResource, Resource, ResourceType, StringResource, StyleResource,
3    XmlResource,
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 any of available resources.
14#[derive(Debug, PartialEq, Eq, Clone)]
15pub enum AnyResource {
16    String(Resource<StringResource>),
17    Drawable(Resource<DrawableResource>),
18    Xml(Resource<XmlResource>),
19    Style(Resource<StyleResource>),
20}
21
22impl Serialize for AnyResource {
23    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24    where
25        S: Serializer,
26    {
27        match self {
28            AnyResource::String(r) => Serialize::serialize(&r, serializer),
29            AnyResource::Drawable(r) => Serialize::serialize(&r, serializer),
30            AnyResource::Xml(r) => Serialize::serialize(&r, serializer),
31            AnyResource::Style(r) => Serialize::serialize(&r, serializer),
32        }
33    }
34}
35
36impl YaSerialize for AnyResource {
37    fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
38        match self {
39            AnyResource::String(r) => YaSerialize::serialize(r, writer),
40            AnyResource::Drawable(r) => YaSerialize::serialize(r, writer),
41            AnyResource::Xml(r) => YaSerialize::serialize(r, writer),
42            AnyResource::Style(r) => YaSerialize::serialize(r, writer),
43        }
44    }
45
46    fn serialize_attributes(
47        &self,
48        attributes: Vec<xml::attribute::OwnedAttribute>,
49        namespace: xml::namespace::Namespace,
50    ) -> Result<
51        (
52            Vec<xml::attribute::OwnedAttribute>,
53            xml::namespace::Namespace,
54        ),
55        String,
56    > {
57        Ok((attributes, namespace))
58    }
59}
60
61fn parse_any_resource(v: &str) -> Result<AnyResource, String> {
62    if v.is_empty() {
63        return Err("value of attribute is empty".to_string());
64    };
65    let (package, resource_type, name) = parse_resource(v)?;
66    let any = if StringResource::resource_type() == resource_type {
67        AnyResource::String(Resource::<StringResource>::new_with_package(&name, package))
68    } else if DrawableResource::resource_type() == resource_type {
69        AnyResource::Drawable(Resource::<DrawableResource>::new_with_package(
70            &name, package,
71        ))
72    } else if XmlResource::resource_type() == resource_type {
73        AnyResource::Xml(Resource::<XmlResource>::new_with_package(&name, package))
74    } else if StyleResource::resource_type() == resource_type {
75        AnyResource::Style(Resource::<StyleResource>::new_with_package(&name, package))
76    } else {
77        return Err(format!("unsuported resource type: {}", resource_type));
78    };
79    Ok(any)
80}
81
82struct AnyResourceVisitor;
83
84impl<'de> Visitor<'de> for AnyResourceVisitor {
85    type Value = AnyResource;
86
87    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
88        formatter.write_str("an resource in format @resource_type/resource_name")
89    }
90
91    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
92    where
93        E: de::Error,
94    {
95        parse_any_resource(v).map_err(|e| E::custom(e))
96    }
97}
98
99impl<'de> Deserialize<'de> for AnyResource {
100    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
101    where
102        D: Deserializer<'de>,
103    {
104        deserializer.deserialize_string(AnyResourceVisitor)
105    }
106}
107
108impl YaDeserialize for AnyResource {
109    fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
110        loop {
111            match reader.next_event()? {
112                xml::reader::XmlEvent::StartElement { .. } => {}
113                xml::reader::XmlEvent::Characters(ref v) => {
114                    return parse_any_resource(v);
115                }
116                _ => {
117                    break;
118                }
119            }
120        }
121        Err("Unable to parse attribute".to_string())
122    }
123}