pak_db/
pointer.rs

1use ordermap::OrderSet;
2use serde::{Deserialize, Serialize};
3
4use crate::{error::PakResult, item::PakItemDeserializeGroup, query::PakQueryExpression};
5
6//==============================================================================================
7//        PakPointer
8//==============================================================================================
9
10/// A pointer that points to a specific location in the pak file. It comes in two flavors, typed and untyped. This pointer is typically offset by the size of the header.
11#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
12pub enum PakPointer {
13    Typed(PakTypedPointer),
14    Untyped(PakUntypedPointer),
15}
16
17impl PakPointer {
18    pub fn new_typed<T>(offset : u64, size : u64) -> Self {
19        Self::Typed(PakTypedPointer::new(offset, size, std::any::type_name::<T>()))
20    }
21
22    pub fn new_untyped(offset : u64, size : u64) -> Self {
23        Self::Untyped(PakUntypedPointer::new(offset, size))
24    }
25    
26    pub fn offset(&self) -> u64 {
27        match self {
28            Self::Typed(ptr) => ptr.offset,
29            Self::Untyped(ptr) => ptr.offset,
30        }
31    }
32    
33    pub fn size(&self) -> u64 {
34        match self {
35            Self::Typed(ptr) => ptr.size,
36            Self::Untyped(ptr) => ptr.size,
37        }
38    }
39    
40    pub fn type_name(&self) -> &str {
41        match self {
42            Self::Typed(ptr) => &ptr.type_name,
43            Self::Untyped(_) => "Untyped",
44        }
45    }
46    
47    pub fn as_untyped(&self) -> PakUntypedPointer {
48        match self {
49            Self::Typed(ptr) => PakUntypedPointer::new(ptr.offset, ptr.size),
50            Self::Untyped(ptr) => *ptr,
51        }
52    }
53    
54    pub fn into_typed<T>(self) -> PakTypedPointer {
55        match self {
56            Self::Typed(ptr) => ptr,
57            Self::Untyped(ptr) => PakTypedPointer::new(ptr.offset, ptr.size, std::any::type_name::<T>()),
58        }
59    }
60    
61    pub fn type_is_match<T>(&self) -> bool {
62        match self {
63            Self::Typed(ptr) => ptr.type_name == std::any::type_name::<T>(),
64            Self::Untyped(_) => true,
65        }
66    }
67    
68    pub fn drop_type(&mut self) {
69        let pointer = PakPointer::Untyped(PakUntypedPointer { offset: self.offset(), size: self.size() });
70        *self = pointer
71    }
72}
73
74impl Clone for PakPointer {
75    fn clone(&self) -> Self {
76        match self {
77            Self::Typed(ptr) => Self::Typed(ptr.clone()),
78            Self::Untyped(ptr) => Self::Untyped(*ptr),
79        }
80    }
81}
82
83impl <T> PakQueryExpression<T> for PakPointer where T : PakItemDeserializeGroup {
84    fn execute(&self, _pak : &crate::Pak) -> PakResult<OrderSet<PakPointer>> {
85        Ok(OrderSet::from([self.clone()]))
86    }
87}
88
89//==============================================================================================
90//        PakTypedPointer
91//==============================================================================================
92
93/// A typed pointer. This tells you what rust type is stored at the location pointed to. You can check it with a type at runtime to fail requests that have a type mismatch.
94#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
95pub struct PakTypedPointer {
96    offset : u64,
97    size : u64,
98    type_name : String,
99}
100
101impl PakTypedPointer {
102    pub fn new(offset : u64, size : u64, type_name : &str) -> Self {
103        Self { offset, size, type_name : type_name.to_string() }
104    }
105    
106    pub fn into_pointer(self) -> PakPointer {
107        PakPointer::Typed(self)
108    }
109}
110
111//==============================================================================================
112//        PakUntypedPointer
113//==============================================================================================
114
115/// An untyped pointer. This tells you the offset and size of the data at the location pointed to. This is useful if you always know the type of the data at the location pointed to.
116#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
117pub struct PakUntypedPointer {
118    offset : u64,
119    size : u64,
120}
121
122impl PakUntypedPointer {
123    pub fn new(offset : u64, size : u64) -> Self {
124        Self { offset, size }
125    }
126    
127    pub fn as_pointer(&self) -> PakPointer {
128        PakPointer::Untyped(*self)
129    }
130}