android_manifest/resources/
mipmap_or_drawable.rs1use super::{
2 DrawableResource, MipmapResource, Resource, ResourceType, ResourceVisitor,
3 parse_resource_with_type,
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#[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 fmt::Display for MipmapOrDrawableResource {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 Self::Mipmap(r) => write!(f, "{}", r),
34 Self::Drawable(r) => write!(f, "{}", r),
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 XmlSerialize for MipmapOrDrawableResource {
52 fn serialize<W: Write>(
53 &self,
54 writer: &mut crate::xml::ser::Serializer<W>,
55 ) -> Result<(), String> {
56 match self {
57 Self::Mipmap(r) => XmlSerialize::serialize(r, writer),
58 Self::Drawable(r) => XmlSerialize::serialize(r, writer),
59 }
60 }
61}
62
63struct MipmapOrDrawableResourceVisitor;
64
65impl<'de> Visitor<'de> for MipmapOrDrawableResourceVisitor {
66 type Value = MipmapOrDrawableResource;
67
68 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
69 formatter
70 .write_str("an resource in format @mipmap/resource_name or @drawable/resource_name")
71 }
72
73 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
74 where
75 E: de::Error,
76 {
77 if v.is_empty() {
78 return Err(E::custom("value of attribute is empty"));
79 };
80 if v.starts_with("@mipmap") {
81 Ok(MipmapOrDrawableResource::Mipmap(
82 ResourceVisitor::<MipmapResource>::new().visit_str(v)?,
83 ))
84 } else if v.starts_with("@drawable") {
85 Ok(MipmapOrDrawableResource::Drawable(
86 ResourceVisitor::<DrawableResource>::new().visit_str(v)?,
87 ))
88 } else {
89 Err(E::custom(format!("wrong resource type: {}", v)))
90 }
91 }
92}
93
94impl<'de> Deserialize<'de> for MipmapOrDrawableResource {
95 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96 where
97 D: Deserializer<'de>,
98 {
99 deserializer.deserialize_string(MipmapOrDrawableResourceVisitor)
100 }
101}
102
103impl XmlDeserialize for MipmapOrDrawableResource {
104 fn deserialize<R: Read>(reader: &mut crate::xml::de::Deserializer<R>) -> Result<Self, String> {
105 loop {
106 match reader.next_event()? {
107 xml::reader::XmlEvent::StartElement { .. } => {}
108 xml::reader::XmlEvent::Characters(text_content) => {
109 if text_content.is_empty() {
110 return Err("value of attribute is empty".to_string());
111 };
112 if text_content.starts_with("@mipmap") {
113 return Ok(MipmapOrDrawableResource::Mipmap(parse_resource_with_type(
114 &text_content,
115 )?));
116 } else if text_content.starts_with("@drawable") {
117 return Ok(MipmapOrDrawableResource::Drawable(
118 parse_resource_with_type(&text_content)?,
119 ));
120 } else {
121 return Err(format!("wrong resource type: {}", text_content));
122 }
123 }
124 _ => {
125 break;
126 }
127 }
128 }
129 Err("Unable to parse attribute".to_string())
130 }
131}