osrscache/definition/osrs.rs
1mod inv_def;
2#[allow(clippy::too_many_lines)]
3mod item_def;
4mod loc_def;
5mod map_def;
6mod npc_def;
7#[allow(clippy::too_many_lines)]
8mod obj_def;
9mod varbit_def;
10
11pub use inv_def::*;
12pub use item_def::*;
13pub use loc_def::*;
14pub use map_def::*;
15pub use npc_def::*;
16pub use obj_def::*;
17pub use varbit_def::*;
18
19use std::collections::HashMap;
20
21use crate::Cache;
22use runefs::{ArchiveFileGroup, IndexMetadata, REFERENCE_TABLE_ID};
23
24/// Marker trait for definitions.
25pub trait Definition: Sized {
26 fn new(id: u16, buffer: &[u8]) -> crate::Result<Self>;
27}
28
29/// Adds definition fetching from the cache to every struct that implements `Definition`.
30///
31/// The main difference between `fetch_from_index` and `fetch_from_archive`:
32/// - `fetch_from_index` will get only 1 definition from each archive making it a 1:1 relation.
33/// - `fetch_from_archive` will get multiple definitions from each archive making it a N:1 relation
34/// where N is atleast 1.
35pub trait FetchDefinition: Definition {
36 // TODO: finish documentation with example.
37 /// Fetches multiple definitions from every archive in the index.
38 ///
39 /// Note: every archive contains only one definition. (1:1)
40 ///
41 /// # Errors
42 ///
43 /// Can return multiple errors: if reading, decoding or parsing definition buffers fail.
44 fn fetch_from_index<D>(cache: &Cache, index_id: u8) -> crate::Result<HashMap<u16, D>>
45 where
46 D: Definition,
47 {
48 let buffer = cache.read(REFERENCE_TABLE_ID, index_id as u32)?.decode()?;
49 let archives = IndexMetadata::try_from(buffer)?;
50 let mut definitions = HashMap::new();
51 for archive in &archives {
52 let buffer = cache.read(index_id, archive.id)?.decode()?;
53
54 definitions.insert(archive.id as u16, D::new(archive.id as u16, &buffer)?);
55 }
56
57 Ok(definitions)
58 }
59
60 /// Fetches multiple definitions from a single archive.
61 ///
62 /// Note: every archive contains multiple definitions. (N:1)
63 ///
64 /// # Errors
65 ///
66 /// Can return multiple errors: if reading, decoding or parsing definition buffers fail.
67 ///
68 /// # Examples
69 ///
70 /// ```
71 /// # use std::collections::HashMap;
72 /// # use osrscache::Cache;
73 /// use osrscache::definition::osrs::{
74 /// FetchDefinition,
75 /// ItemDefinition,
76 /// };
77 ///
78 /// # fn main() -> Result<(), osrscache::Error> {
79 /// # let cache = Cache::new("./data/osrs_cache")?;
80 /// let index_id = 2; // Config index.
81 /// let archive_id = 10; // Archive containing item definitions.
82 ///
83 /// let item_defs: HashMap<u16, ItemDefinition>
84 /// = ItemDefinition::fetch_from_archive(&cache, index_id, archive_id)?;
85 /// # Ok(())
86 /// # }
87 /// ```
88 fn fetch_from_archive<D>(
89 cache: &Cache,
90 index_id: u8,
91 archive_id: u32,
92 ) -> crate::Result<HashMap<u16, D>>
93 where
94 D: Definition,
95 {
96 let buffer = cache.read(REFERENCE_TABLE_ID, index_id as u32)?.decode()?;
97 let archives = IndexMetadata::try_from(buffer)?;
98 let entry_count = archives[archive_id as usize - 1].entry_count;
99 let buffer = cache.read(index_id, archive_id)?.decode()?;
100
101 let archive_group = ArchiveFileGroup::from_buffer(&buffer, entry_count);
102
103 let mut definitions = HashMap::new();
104 for archive_file in archive_group {
105 definitions.insert(
106 archive_file.id as u16,
107 D::new(archive_file.id as u16, &archive_file.data)?,
108 );
109 }
110
111 Ok(definitions)
112 }
113}
114
115impl<D: Definition> FetchDefinition for D {}