1use alloc::{fmt, str::FromStr, string::String, vec::Vec};
2use pbf::{BitCast, ProtoRead, ProtoWrite, Protobuf};
3
4#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
8pub enum ImageType {
9 #[default]
11 PNG = 0,
12 JPG = 1,
14 WEBP = 2,
16 GIF = 3,
18 AVIF = 4,
20 SVG = 5,
22 BMP = 6,
24 RAW = 7,
26 UNKNOWN = 8,
28}
29impl BitCast for ImageType {
30 fn to_u64(&self) -> u64 {
31 (*self) as u64
32 }
33 fn from_u64(value: u64) -> Self {
34 match value {
35 0 => ImageType::PNG,
36 1 => ImageType::JPG,
37 2 => ImageType::WEBP,
38 3 => ImageType::GIF,
39 4 => ImageType::AVIF,
40 5 => ImageType::SVG,
41 6 => ImageType::BMP,
42 7 => ImageType::RAW,
43 8 => ImageType::UNKNOWN,
44 _ => panic!("unknown value: {}", value),
45 }
46 }
47}
48impl FromStr for ImageType {
49 type Err = &'static str;
50
51 fn from_str(s: &str) -> Result<Self, Self::Err> {
52 match s.to_uppercase().as_str() {
53 "PNG" => Ok(ImageType::PNG),
54 "JPG" | "JPEG" => Ok(ImageType::JPG),
55 "WEBP" => Ok(ImageType::WEBP),
56 "GIF" => Ok(ImageType::GIF),
57 "AVIF" => Ok(ImageType::AVIF),
58 "SVG" => Ok(ImageType::SVG),
59 "BMP" => Ok(ImageType::BMP),
60 "RAW" => Ok(ImageType::RAW),
61 "UNKNOWN" => Ok(ImageType::UNKNOWN),
62 _ => Err("Unknown image type"),
63 }
64 }
65}
66impl From<&str> for ImageType {
67 fn from(s: &str) -> Self {
68 ImageType::from_str(s.to_uppercase().as_str()).unwrap_or(ImageType::PNG)
69 }
70}
71impl fmt::Display for ImageType {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 let name = match self {
74 ImageType::PNG => "PNG",
75 ImageType::JPG => "JPG",
76 ImageType::WEBP => "WEBP",
77 ImageType::GIF => "GIF",
78 ImageType::AVIF => "AVIF",
79 ImageType::SVG => "SVG",
80 ImageType::BMP => "BMP",
81 ImageType::RAW => "RAW",
82 ImageType::UNKNOWN => "UNKNOWN",
83 };
84 write!(f, "{}", name)
85 }
86}
87
88#[derive(Debug, Default, Clone, PartialEq)]
90pub struct ImageData {
91 pub name: String,
93 pub image_type: ImageType,
95 pub width: u32,
97 pub height: u32,
99 pub image: Vec<u8>,
101}
102impl ImageData {
103 pub fn new(
105 name: String,
106 image_type: ImageType,
107 width: u32,
108 height: u32,
109 image: Vec<u8>,
110 ) -> Self {
111 Self { name, image_type, width, height, image }
112 }
113}
114impl ProtoRead for ImageData {
115 fn read(&mut self, tag: u64, pb: &mut Protobuf) {
116 match tag {
117 1 => self.image_type = pb.read_varint::<ImageType>(),
118 2 => self.width = pb.read_varint(),
119 3 => self.height = pb.read_varint(),
120 4 => self.image = pb.read_bytes(),
121 5 => self.name = pb.read_string(),
122 _ => panic!("unknown tag: {}", tag),
123 }
124 }
125}
126impl ProtoWrite for ImageData {
127 fn write(&self, pb: &mut Protobuf) {
128 pb.write_varint_field(1, self.image_type);
129 pb.write_varint_field(2, self.width);
130 pb.write_varint_field(3, self.height);
131 pb.write_bytes_field(4, &self.image);
132 pb.write_string_field(5, &self.name);
133 }
134}