use super::mesh::Mesh;
use crate::{errors::ParseError, utils::item_metadata::ItemMetadata};
use serde_llsd_benthic::{auto_from_str, converter::get};
use std::{
collections::HashMap,
str::{from_utf8, FromStr},
};
use uuid::Uuid;
#[derive(Debug, Default, Clone)]
pub struct Item {
pub metadata: ItemMetadata,
pub data: Option<ItemData>,
}
impl Item {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
Ok(Item {
metadata: ItemMetadata::from_bytes(bytes)?,
data: Some(ItemData::from_bytes(bytes)?),
})
}
}
#[derive(Debug, Default, Clone)]
pub struct ItemData {
pub version: u32,
pub parameters: HashMap<i32, f32>,
pub textures: HashMap<TextureSlot, Uuid>,
pub mesh: Option<Mesh>,
}
impl ItemData {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
let data = from_utf8(bytes)?;
let llsd = auto_from_str(data).map_err(|e| ParseError::Message(e.to_string()))?;
let map = llsd.as_map().ok_or(ParseError::LLSDError())?;
Ok(ItemData {
version: get("version", map),
parameters: get("parameters", map),
textures: get("textures", map),
mesh: None,
})
}
}
#[derive(Debug)]
pub struct Texture {
pub texture_slot: TextureSlot,
pub id: Uuid,
}
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub enum TextureSlot {
Head = 0,
UpperBody = 1,
LowerBody = 2,
Eyes = 3,
Hair = 4,
Shirt = 5,
Pants = 6,
Shoes = 7,
Socks = 8,
Jacket = 9,
Unknown = 99,
}
impl FromStr for TextureSlot {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"0" => Ok(TextureSlot::Head),
"1" => Ok(TextureSlot::UpperBody),
"2" => Ok(TextureSlot::LowerBody),
"3" => Ok(TextureSlot::Eyes),
"4" => Ok(TextureSlot::Hair),
"5" => Ok(TextureSlot::Shirt),
"6" => Ok(TextureSlot::Pants),
"7" => Ok(TextureSlot::Shoes),
"8" => Ok(TextureSlot::Socks),
"9" => Ok(TextureSlot::Jacket),
_ => Ok(TextureSlot::Unknown),
}
}
}