use alloc::{fmt, str::FromStr, string::String, vec::Vec};
use pbf::{BitCast, ProtoRead, ProtoWrite, Protobuf};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
pub enum ImageType {
#[default]
PNG = 0,
JPG = 1,
WEBP = 2,
GIF = 3,
AVIF = 4,
SVG = 5,
BMP = 6,
RAW = 7,
UNKNOWN = 8,
}
impl BitCast for ImageType {
fn to_u64(&self) -> u64 {
(*self) as u64
}
fn from_u64(value: u64) -> Self {
match value {
0 => ImageType::PNG,
1 => ImageType::JPG,
2 => ImageType::WEBP,
3 => ImageType::GIF,
4 => ImageType::AVIF,
5 => ImageType::SVG,
6 => ImageType::BMP,
7 => ImageType::RAW,
8 => ImageType::UNKNOWN,
_ => panic!("unknown value: {}", value),
}
}
}
impl FromStr for ImageType {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_uppercase().as_str() {
"PNG" => Ok(ImageType::PNG),
"JPG" | "JPEG" => Ok(ImageType::JPG),
"WEBP" => Ok(ImageType::WEBP),
"GIF" => Ok(ImageType::GIF),
"AVIF" => Ok(ImageType::AVIF),
"SVG" => Ok(ImageType::SVG),
"BMP" => Ok(ImageType::BMP),
"RAW" => Ok(ImageType::RAW),
"UNKNOWN" => Ok(ImageType::UNKNOWN),
_ => Err("Unknown image type"),
}
}
}
impl From<&str> for ImageType {
fn from(s: &str) -> Self {
ImageType::from_str(s.to_uppercase().as_str()).unwrap_or(ImageType::PNG)
}
}
impl fmt::Display for ImageType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
ImageType::PNG => "PNG",
ImageType::JPG => "JPG",
ImageType::WEBP => "WEBP",
ImageType::GIF => "GIF",
ImageType::AVIF => "AVIF",
ImageType::SVG => "SVG",
ImageType::BMP => "BMP",
ImageType::RAW => "RAW",
ImageType::UNKNOWN => "UNKNOWN",
};
write!(f, "{}", name)
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ImageData {
pub name: String,
pub image_type: ImageType,
pub width: u32,
pub height: u32,
pub image: Vec<u8>,
}
impl ImageData {
pub fn new(
name: String,
image_type: ImageType,
width: u32,
height: u32,
image: Vec<u8>,
) -> Self {
Self { name, image_type, width, height, image }
}
}
impl ProtoRead for ImageData {
fn read(&mut self, tag: u64, pb: &mut Protobuf) {
match tag {
1 => self.image_type = pb.read_varint::<ImageType>(),
2 => self.width = pb.read_varint(),
3 => self.height = pb.read_varint(),
4 => self.image = pb.read_bytes(),
5 => self.name = pb.read_string(),
_ => panic!("unknown tag: {}", tag),
}
}
}
impl ProtoWrite for ImageData {
fn write(&self, pb: &mut Protobuf) {
pb.write_varint_field(1, self.image_type);
pb.write_varint_field(2, self.width);
pb.write_varint_field(3, self.height);
pb.write_bytes_field(4, &self.image);
pb.write_string_field(5, &self.name);
}
}