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 #[tarpaulin::skip]
63 _ => Err("Unknown image type"),
64 }
65 }
66}
67impl From<&str> for ImageType {
68 fn from(s: &str) -> Self {
69 ImageType::from_str(s.to_uppercase().as_str()).unwrap_or(ImageType::PNG)
70 }
71}
72impl fmt::Display for ImageType {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 let name = match self {
75 ImageType::PNG => "PNG",
76 ImageType::JPG => "JPG",
77 ImageType::WEBP => "WEBP",
78 ImageType::GIF => "GIF",
79 ImageType::AVIF => "AVIF",
80 ImageType::SVG => "SVG",
81 ImageType::BMP => "BMP",
82 ImageType::RAW => "RAW",
83 ImageType::UNKNOWN => "UNKNOWN",
84 };
85 write!(f, "{}", name)
86 }
87}
88
89#[derive(Debug, Default, Clone, PartialEq)]
91pub struct ImageData {
92 pub name: String,
94 pub image_type: ImageType,
96 pub width: u32,
98 pub height: u32,
100 pub image: Vec<u8>,
102}
103impl ImageData {
104 pub fn new(
106 name: String,
107 image_type: ImageType,
108 width: u32,
109 height: u32,
110 image: Vec<u8>,
111 ) -> Self {
112 Self { name, image_type, width, height, image }
113 }
114}
115impl ProtoRead for ImageData {
116 fn read(&mut self, tag: u64, pb: &mut Protobuf) {
117 match tag {
118 1 => self.image_type = pb.read_varint::<ImageType>(),
119 2 => self.width = pb.read_varint(),
120 3 => self.height = pb.read_varint(),
121 4 => self.image = pb.read_bytes(),
122 5 => self.name = pb.read_string(),
123 #[tarpaulin::skip]
124 _ => panic!("unknown tag: {}", tag),
125 }
126 }
127}
128impl ProtoWrite for ImageData {
129 fn write(&self, pb: &mut Protobuf) {
130 pb.write_varint_field(1, self.image_type);
131 pb.write_varint_field(2, self.width);
132 pb.write_varint_field(3, self.height);
133 pb.write_bytes_field(4, &self.image);
134 pb.write_string_field(5, &self.name);
135 }
136}