pak_db/
pointer.rs

1use ordermap::OrderSet;
2use serde::{Deserialize, Serialize};
3
4use crate::{error::PakResult, 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
69impl Clone for PakPointer {
70    fn clone(&self) -> Self {
71        match self {
72            Self::Typed(ptr) => Self::Typed(ptr.clone()),
73            Self::Untyped(ptr) => Self::Untyped(*ptr),
74        }
75    }
76}
77
78impl PakQueryExpression for PakPointer {
79    fn execute(&self, _pak : &crate::Pak) -> PakResult<OrderSet<PakPointer>> {
80        Ok(OrderSet::from([self.clone()]))
81    }
82}
83
84//==============================================================================================
85//        PakTypedPointer
86//==============================================================================================
87
88/// 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.
89#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
90pub struct PakTypedPointer {
91    offset : u64,
92    size : u64,
93    type_name : String,
94}
95
96impl PakTypedPointer {
97    pub fn new(offset : u64, size : u64, type_name : &str) -> Self {
98        Self { offset, size, type_name : type_name.to_string() }
99    }
100    
101    pub fn into_pointer(self) -> PakPointer {
102        PakPointer::Typed(self)
103    }
104}
105
106//==============================================================================================
107//        PakUntypedPointer
108//==============================================================================================
109
110/// 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.
111#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
112pub struct PakUntypedPointer {
113    offset : u64,
114    size : u64,
115}
116
117impl PakUntypedPointer {
118    pub fn new(offset : u64, size : u64) -> Self {
119        Self { offset, size }
120    }
121    
122    pub fn as_pointer(&self) -> PakPointer {
123        PakPointer::Untyped(*self)
124    }
125}