steel_registry/data_components/components/
brewing_fuel.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, sort_map_entries};
9use steel_utils::serial::{ReadFrom, WriteTo};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct BrewingFuel {
15 pub uses: Identifier,
16 pub speed_multiplier: Identifier,
17}
18
19impl BrewingFuel {
20 #[must_use]
21 pub const fn new(uses: Identifier, speed_multiplier: Identifier) -> Self {
22 Self {
23 uses,
24 speed_multiplier,
25 }
26 }
27}
28
29impl WriteTo for BrewingFuel {
30 fn write(&self, writer: &mut impl Write) -> Result<()> {
31 self.uses.write(writer)?;
32 self.speed_multiplier.write(writer)
33 }
34}
35
36impl ReadFrom for BrewingFuel {
37 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
38 Ok(Self {
39 uses: Identifier::read(data)?,
40 speed_multiplier: Identifier::read(data)?,
41 })
42 }
43}
44
45impl ToNbtTag for BrewingFuel {
46 fn to_nbt_tag(self) -> NbtTag {
47 let mut compound = NbtCompound::new();
48 compound.insert("uses", self.uses.to_nbt_tag());
49 compound.insert("speed_multiplier", self.speed_multiplier.to_nbt_tag());
50 NbtTag::Compound(compound)
51 }
52}
53
54impl FromNbtTag for BrewingFuel {
55 fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
56 let compound = tag.compound()?;
57 let uses = Identifier::from_nbt_tag(compound.get("uses")?)?;
58 let speed_multiplier = Identifier::from_nbt_tag(compound.get("speed_multiplier")?)?;
59 Some(Self {
60 uses,
61 speed_multiplier,
62 })
63 }
64}
65
66impl HashComponent for BrewingFuel {
67 fn hash_component(&self, hasher: &mut ComponentHasher) {
68 let mut entries = Vec::with_capacity(2);
69 push_hash_entry(&mut entries, "uses", &self.uses);
70 push_hash_entry(&mut entries, "speed_multiplier", &self.speed_multiplier);
71 sort_map_entries(&mut entries);
72 hasher.start_map();
73 for entry in entries {
74 hasher.put_raw_bytes(&entry.key_bytes);
75 hasher.put_raw_bytes(&entry.value_bytes);
76 }
77 hasher.end_map();
78 }
79}
80
81fn push_hash_entry<T: HashComponent + ?Sized>(entries: &mut Vec<HashEntry>, key: &str, value: &T) {
82 let mut key_hasher = ComponentHasher::new();
83 key_hasher.put_string(key);
84 let mut value_hasher = ComponentHasher::new();
85 value.hash_component(&mut value_hasher);
86 entries.push(HashEntry::new(key_hasher, value_hasher));
87}
88
89#[cfg(test)]
90mod tests {
91 use std::io::Cursor;
92
93 use simdnbt::FromNbtTag as _;
94 use simdnbt::ToNbtTag as _;
95 use simdnbt::borrow::read_tag;
96 use simdnbt::owned::NbtTag;
97 use steel_utils::Identifier;
98 use steel_utils::serial::{ReadFrom as _, WriteTo as _};
99
100 use super::BrewingFuel;
101
102 fn parse(tag: NbtTag) -> Option<BrewingFuel> {
103 let mut bytes = Vec::new();
104 tag.write(&mut bytes);
105 let borrowed = read_tag(&mut Cursor::new(bytes.as_slice())).ok()?;
106 BrewingFuel::from_nbt_tag(borrowed.as_tag())
107 }
108
109 #[test]
110 fn round_trips_both_codecs() {
111 let value = BrewingFuel::new(
112 Identifier::vanilla_static("brewing/uses_default"),
113 Identifier::vanilla_static("brewing/speed_default"),
114 );
115
116 let nbt = value.clone().to_nbt_tag();
117 assert_eq!(parse(nbt), Some(value.clone()));
118
119 let mut network = Vec::new();
120 value.write(&mut network).expect("fuel should encode");
121 assert_eq!(
122 BrewingFuel::read(&mut Cursor::new(network.as_slice())).expect("fuel should decode"),
123 value
124 );
125 }
126}