android_manifest/resources/
mipmap_or_drawable.rs1use 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#[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}