pak_db/
pointer.rs

1use ordermap::OrderSet;
2use serde::{Deserialize, Serialize};
3
4use crate::{error::PakResult, group::{DeserializeGroup}, 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 : DeserializeGroup {
84    fn execute(&self, _pak : &crate::Pak) -> PakResult<OrderSet<PakPointer>> {
85        Ok(OrderSet::from([self.clone()]))
86    }
87}
88
89impl From<PakUntypedPointer> for PakPointer {
90    fn from(value: PakUntypedPointer) -> Self {
91        PakPointer::Untyped(value)
92    }
93}
94
95impl From<PakTypedPointer> for PakPointer {
96    fn from(value: PakTypedPointer) -> Self {
97        PakPointer::Typed(value)
98    }
99}
100
101//==============================================================================================
102//        PakTypedPointer
103//==============================================================================================
104
105/// 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.
106#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
107pub struct PakTypedPointer {
108    offset : u64,
109    size : u64,
110    type_name : String,
111}
112
113impl PakTypedPointer {
114    pub fn new(offset : u64, size : u64, type_name : &str) -> Self {
115        Self { offset, size, type_name : type_name.to_string() }
116    }
117    
118    pub fn into_pointer(self) -> PakPointer {
119        PakPointer::Typed(self)
120    }
121}
122
123//==============================================================================================
124//        PakUntypedPointer
125//==============================================================================================
126
127/// 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.
128#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Serialize, Deserialize, Hash)]
129pub struct PakUntypedPointer {
130    offset : u64,
131    size : u64,
132}
133
134impl PakUntypedPointer {
135    pub fn new(offset : u64, size : u64) -> Self {
136        Self { offset, size }
137    }
138    
139    pub fn as_pointer(&self) -> PakPointer {
140        PakPointer::Untyped(*self)
141    }
142}