Skip to main content

android_manifest/resources/
any.rs

1use super::{
2    DrawableResource, Resource, ResourceType, StringResource, StyleResource, XmlResource,
3    parse_resource,
4};
5use crate::xml::{XmlDeserialize, XmlSerialize};
6use serde::{
7    Deserialize, Deserializer, Serialize, Serializer,
8    de::{self, Visitor},
9};
10use std::fmt;
11use std::io::{Read, Write};
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 XmlSerialize for AnyResource {
37    fn serialize<W: Write>(
38        &self,
39        writer: &mut crate::xml::ser::Serializer<W>,
40    ) -> Result<(), String> {
41        match self {
42            AnyResource::String(r) => XmlSerialize::serialize(r, writer),
43            AnyResource::Drawable(r) => XmlSerialize::serialize(r, writer),
44            AnyResource::Xml(r) => XmlSerialize::serialize(r, writer),
45            AnyResource::Style(r) => XmlSerialize::serialize(r, writer),
46        }
47    }
48}
49
50fn parse_any_resource(v: &str) -> Result<AnyResource, String> {
51    if v.is_empty() {
52        return Err("value of attribute is empty".to_string());
53    };
54    let (package, resource_type, name) = parse_resource(v)?;
55    let any = if StringResource::resource_type() == resource_type {
56        AnyResource::String(Resource::<StringResource>::new_with_package(&name, package))
57    } else if DrawableResource::resource_type() == resource_type {
58        AnyResource::Drawable(Resource::<DrawableResource>::new_with_package(
59            &name, package,
60        ))
61    } else if XmlResource::resource_type() == resource_type {
62        AnyResource::Xml(Resource::<XmlResource>::new_with_package(&name, package))
63    } else if StyleResource::resource_type() == resource_type {
64        AnyResource::Style(Resource::<StyleResource>::new_with_package(&name, package))
65    } else {
66        return Err(format!("unsuported resource type: {}", resource_type));
67    };
68    Ok(any)
69}
70
71struct AnyResourceVisitor;
72
73impl<'de> Visitor<'de> for AnyResourceVisitor {
74    type Value = AnyResource;
75
76    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
77        formatter.write_str("an resource in format @resource_type/resource_name")
78    }
79
80    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
81    where
82        E: de::Error,
83    {
84        parse_any_resource(v).map_err(|e| E::custom(e))
85    }
86}
87
88impl<'de> Deserialize<'de> for AnyResource {
89    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
90    where
91        D: Deserializer<'de>,
92    {
93        deserializer.deserialize_string(AnyResourceVisitor)
94    }
95}
96
97impl XmlDeserialize for AnyResource {
98    fn deserialize<R: Read>(reader: &mut crate::xml::de::Deserializer<R>) -> Result<Self, String> {
99        loop {
100            match reader.next_event()? {
101                xml::reader::XmlEvent::StartElement { .. } => {}
102                xml::reader::XmlEvent::Characters(ref v) => {
103                    return parse_any_resource(v);
104                }
105                _ => {
106                    break;
107                }
108            }
109        }
110        Err("Unable to parse attribute".to_string())
111    }
112}