steel_registry/data_components/components/
compostable.rs1use std::io::{Cursor, Result, Write};
4
5use simdnbt::owned::{NbtCompound, NbtTag};
6use simdnbt::{FromNbtTag, ToNbtTag};
7use steel_utils::Identifier;
8use steel_utils::hash::{ComponentHasher, HashComponent, HashEntry};
9use steel_utils::serial::{ReadFrom, WriteTo};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct Compostable {
15 pub layers: Identifier,
16}
17
18impl Compostable {
19 #[must_use]
20 pub const fn new(layers: Identifier) -> Self {
21 Self { layers }
22 }
23}
24
25impl WriteTo for Compostable {
26 fn write(&self, writer: &mut impl Write) -> Result<()> {
27 self.layers.write(writer)
28 }
29}
30
31impl ReadFrom for Compostable {
32 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
33 Ok(Self {
34 layers: Identifier::read(data)?,
35 })
36 }
37}
38
39impl ToNbtTag for Compostable {
40 fn to_nbt_tag(self) -> NbtTag {
41 let mut compound = NbtCompound::new();
42 compound.insert("layers", self.layers.to_nbt_tag());
43 NbtTag::Compound(compound)
44 }
45}
46
47impl FromNbtTag for Compostable {
48 fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
49 let compound = tag.compound()?;
50 let layers = Identifier::from_nbt_tag(compound.get("layers")?)?;
51 Some(Self { layers })
52 }
53}
54
55impl HashComponent for Compostable {
56 fn hash_component(&self, hasher: &mut ComponentHasher) {
57 let mut key_hasher = ComponentHasher::new();
58 key_hasher.put_string("layers");
59 let mut value_hasher = ComponentHasher::new();
60 self.layers.hash_component(&mut value_hasher);
61 let entry = HashEntry::new(key_hasher, value_hasher);
62
63 hasher.start_map();
64 hasher.put_raw_bytes(&entry.key_bytes);
65 hasher.put_raw_bytes(&entry.value_bytes);
66 hasher.end_map();
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use std::io::Cursor;
73
74 use simdnbt::FromNbtTag as _;
75 use simdnbt::ToNbtTag as _;
76 use simdnbt::borrow::read_tag;
77 use simdnbt::owned::NbtTag;
78 use steel_utils::Identifier;
79 use steel_utils::serial::{ReadFrom as _, WriteTo as _};
80
81 use super::Compostable;
82
83 fn parse(tag: NbtTag) -> Option<Compostable> {
84 let mut bytes = Vec::new();
85 tag.write(&mut bytes);
86 let borrowed = read_tag(&mut Cursor::new(bytes.as_slice())).ok()?;
87 Compostable::from_nbt_tag(borrowed.as_tag())
88 }
89
90 #[test]
91 fn round_trips_both_codecs() {
92 let value = Compostable::new(Identifier::vanilla_static("compostable/low"));
93
94 let nbt = value.clone().to_nbt_tag();
95 assert_eq!(parse(nbt), Some(value.clone()));
96
97 let mut network = Vec::new();
98 value
99 .write(&mut network)
100 .expect("compostable should encode");
101 assert_eq!(
102 Compostable::read(&mut Cursor::new(network.as_slice()))
103 .expect("compostable should decode"),
104 value
105 );
106 }
107}