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