msg_tool\ext/
psb.rs

1//!Extensions for emote_psb crate.
2use emote_psb::VirtualPsb;
3use emote_psb::header::PsbHeader;
4use emote_psb::types::collection::*;
5use emote_psb::types::number::*;
6use emote_psb::types::reference::*;
7use emote_psb::types::string::*;
8use emote_psb::types::*;
9#[cfg(feature = "json")]
10use json::JsonValue;
11use serde::ser::SerializeStruct;
12use serde::{Deserialize, Serialize};
13use std::cmp::PartialEq;
14use std::collections::{BTreeMap, HashMap};
15use std::ops::{Index, IndexMut};
16
17const NONE: PsbValueFixed = PsbValueFixed::None;
18
19#[derive(Debug, Serialize, Deserialize)]
20/// Represents of a PSB value.
21pub enum PsbValueFixed {
22    /// No value.
23    None,
24    /// Represents a null value.
25    Null,
26    /// Represents a boolean value.
27    Bool(bool),
28    /// Represents a number value.
29    Number(PsbNumber),
30    /// Represents an array of integers.
31    IntArray(PsbUintArray),
32    /// Represents a string value.
33    String(PsbString),
34    /// Represents a list of PSB values.
35    List(PsbListFixed),
36    /// Represents an object with key-value pairs.
37    Object(PsbObjectFixed),
38    /// Represents a resource reference.
39    Resource(PsbResourceRef),
40    /// Represents an extra resource reference.
41    ExtraResource(PsbExtraRef),
42    /// Represents a compiler number.
43    CompilerNumber,
44    /// Represents a compiler string.
45    CompilerString,
46    /// Represents a compiler resource.
47    CompilerResource,
48    /// Represents a compiler decimal.
49    CompilerDecimal,
50    /// Represents a compiler array.
51    CompilerArray,
52    /// Represents a compiler boolean.
53    CompilerBool,
54    /// Represents a compiler binary tree.
55    CompilerBinaryTree,
56}
57
58impl From<String> for PsbValueFixed {
59    fn from(value: String) -> Self {
60        PsbValueFixed::String(PsbString::from(value))
61    }
62}
63
64impl From<bool> for PsbValueFixed {
65    fn from(value: bool) -> Self {
66        PsbValueFixed::Bool(value)
67    }
68}
69
70impl From<i64> for PsbValueFixed {
71    fn from(value: i64) -> Self {
72        PsbValueFixed::Number(PsbNumber::Integer(value))
73    }
74}
75
76impl From<f64> for PsbValueFixed {
77    fn from(value: f64) -> Self {
78        PsbValueFixed::Number(PsbNumber::Double(value))
79    }
80}
81
82impl From<f32> for PsbValueFixed {
83    fn from(value: f32) -> Self {
84        PsbValueFixed::Number(PsbNumber::Float(value))
85    }
86}
87
88impl From<PsbObjectFixed> for PsbValueFixed {
89    fn from(value: PsbObjectFixed) -> Self {
90        PsbValueFixed::Object(value)
91    }
92}
93
94impl From<PsbListFixed> for PsbValueFixed {
95    fn from(value: PsbListFixed) -> Self {
96        PsbValueFixed::List(value)
97    }
98}
99
100impl From<&[PsbValueFixed]> for PsbValueFixed {
101    fn from(value: &[PsbValueFixed]) -> Self {
102        PsbValueFixed::List(PsbListFixed {
103            values: value.to_vec(),
104        })
105    }
106}
107
108impl PsbValueFixed {
109    /// Converts this value to original PSB value type.
110    pub fn to_psb(self, warn_on_none: bool) -> PsbValue {
111        match self {
112            PsbValueFixed::None => {
113                if warn_on_none {
114                    eprintln!("Warning: PSB value is None, output script may broken.");
115                    crate::COUNTER.inc_warning();
116                }
117                PsbValue::None
118            }
119            PsbValueFixed::Null => PsbValue::Null,
120            PsbValueFixed::Bool(b) => PsbValue::Bool(b),
121            PsbValueFixed::Number(n) => PsbValue::Number(n),
122            PsbValueFixed::IntArray(arr) => PsbValue::IntArray(arr),
123            PsbValueFixed::String(s) => PsbValue::String(s),
124            PsbValueFixed::List(l) => PsbValue::List(l.to_psb(warn_on_none)),
125            PsbValueFixed::Object(o) => PsbValue::Object(o.to_psb(warn_on_none)),
126            PsbValueFixed::Resource(r) => PsbValue::Resource(r),
127            PsbValueFixed::ExtraResource(er) => PsbValue::ExtraResource(er),
128            PsbValueFixed::CompilerNumber => PsbValue::CompilerNumber,
129            PsbValueFixed::CompilerString => PsbValue::CompilerString,
130            PsbValueFixed::CompilerResource => PsbValue::CompilerResource,
131            PsbValueFixed::CompilerDecimal => PsbValue::CompilerDecimal,
132            PsbValueFixed::CompilerArray => PsbValue::CompilerArray,
133            PsbValueFixed::CompilerBool => PsbValue::CompilerBool,
134            PsbValueFixed::CompilerBinaryTree => PsbValue::CompilerBinaryTree,
135        }
136    }
137
138    /// Returns true if this value is a list.
139    pub fn is_list(&self) -> bool {
140        matches!(self, PsbValueFixed::List(_))
141    }
142
143    /// Returns true if this value is an object.
144    pub fn is_object(&self) -> bool {
145        matches!(self, PsbValueFixed::Object(_))
146    }
147
148    /// Returns true if this value is a string or null.
149    pub fn is_string_or_null(&self) -> bool {
150        self.is_string() || self.is_null()
151    }
152
153    /// Returns true if this value is a string.
154    pub fn is_string(&self) -> bool {
155        matches!(self, PsbValueFixed::String(_))
156    }
157
158    /// Returns true if this value is none.
159    pub fn is_none(&self) -> bool {
160        matches!(self, PsbValueFixed::None)
161    }
162
163    /// Returns true if this value is null.
164    pub fn is_null(&self) -> bool {
165        matches!(self, PsbValueFixed::Null)
166    }
167
168    /// Find the resource's key in object
169    pub fn find_resource_key<'a>(
170        &'a self,
171        resource_id: u64,
172        now: Vec<&'a str>,
173    ) -> Option<Vec<&'a str>> {
174        match self {
175            PsbValueFixed::List(l) => l.find_resource_key(resource_id, now),
176            PsbValueFixed::Object(o) => o.find_resource_key(resource_id, now),
177            _ => None,
178        }
179    }
180
181    /// Find the extra resource's key in object
182    pub fn find_extra_resource_key<'a>(
183        &'a self,
184        extra_resource_id: u64,
185        now: Vec<&'a str>,
186    ) -> Option<Vec<&'a str>> {
187        match self {
188            PsbValueFixed::List(l) => l.find_extra_resource_key(extra_resource_id, now),
189            PsbValueFixed::Object(o) => o.find_extra_resource_key(extra_resource_id, now),
190            _ => None,
191        }
192    }
193
194    /// Sets the value of this PSB value to a new integer.
195    pub fn set_i64(&mut self, value: i64) {
196        *self = PsbValueFixed::Number(PsbNumber::Integer(value));
197    }
198
199    /// Sets the value of this PSB value to a new object
200    pub fn set_obj(&mut self, value: PsbObjectFixed) {
201        *self = PsbValueFixed::Object(value);
202    }
203
204    /// Sets the value of this PSB value to a new string.
205    pub fn set_str(&mut self, value: &str) {
206        match self {
207            PsbValueFixed::String(s) => {
208                let s = s.string_mut();
209                s.clear();
210                s.push_str(value);
211            }
212            _ => {
213                *self = PsbValueFixed::String(PsbString::from(value.to_owned()));
214            }
215        }
216    }
217
218    /// Sets the value of this PSB value to a new string.
219    pub fn set_string(&mut self, value: String) {
220        self.set_str(&value);
221    }
222
223    /// Returns the value as a boolean, if it is a boolean.
224    pub fn as_u8(&self) -> Option<u8> {
225        self.as_i64().map(|n| n.try_into().ok()).flatten()
226    }
227
228    /// Returns the value as a [u32], if it is a number.
229    pub fn as_u32(&self) -> Option<u32> {
230        self.as_i64().map(|n| n as u32)
231    }
232
233    /// Returns the value as a [i64], if it is a number.
234    pub fn as_i64(&self) -> Option<i64> {
235        match self {
236            PsbValueFixed::Number(n) => match n {
237                PsbNumber::Integer(n) => Some(*n),
238                _ => None,
239            },
240            _ => None,
241        }
242    }
243
244    /// Returns the value as a string, if it is a string.
245    pub fn as_str(&self) -> Option<&str> {
246        match self {
247            PsbValueFixed::String(s) => Some(s.string()),
248            _ => None,
249        }
250    }
251
252    /// Returns the lengtho of a list or object.
253    pub fn len(&self) -> usize {
254        match self {
255            PsbValueFixed::List(l) => l.len(),
256            PsbValueFixed::Object(o) => o.values.len(),
257            _ => 0,
258        }
259    }
260
261    /// Returns a iterator over the entries of an object.
262    pub fn entries(&self) -> ObjectIter<'_> {
263        match self {
264            PsbValueFixed::Object(o) => o.iter(),
265            _ => ObjectIter::empty(),
266        }
267    }
268
269    /// Returns a mutable iterator over the entries of an object.
270    pub fn entries_mut(&mut self) -> ObjectIterMut<'_> {
271        match self {
272            PsbValueFixed::Object(o) => o.iter_mut(),
273            _ => ObjectIterMut::empty(),
274        }
275    }
276
277    /// Returns a iterator over the members of a list.
278    pub fn members(&self) -> ListIter<'_> {
279        match self {
280            PsbValueFixed::List(l) => l.iter(),
281            _ => ListIter::empty(),
282        }
283    }
284
285    /// Returns a mutable iterator over the members of a list.
286    pub fn members_mut(&mut self) -> ListIterMut<'_> {
287        match self {
288            PsbValueFixed::List(l) => l.iter_mut(),
289            _ => ListIterMut::empty(),
290        }
291    }
292
293    /// Pushes a new member to a list. If this value is not a list, it will be converted to a list.
294    pub fn push_member<T: Into<PsbValueFixed>>(&mut self, value: T) {
295        match self {
296            PsbValueFixed::List(l) => {
297                l.values.push(value.into());
298            }
299            _ => {
300                *self = PsbValueFixed::List(PsbListFixed {
301                    values: vec![value.into()],
302                });
303            }
304        }
305    }
306
307    /// Clears all members in a list. If this value is not a list, it will be converted to an empty list.
308    pub fn clear_members(&mut self) {
309        match self {
310            PsbValueFixed::List(l) => {
311                l.clear();
312            }
313            _ => {
314                *self = PsbValueFixed::List(PsbListFixed { values: vec![] });
315            }
316        }
317    }
318
319    /// Inserts a new member at the specified index in a list. If this value is not a list, it will be converted to a list.
320    /// If the index is out of bounds, the value will be appended to the end of the list.
321    pub fn insert_member<T: Into<PsbValueFixed>>(&mut self, index: usize, value: T) {
322        match self {
323            PsbValueFixed::List(l) => {
324                l.insert(index, value);
325            }
326            _ => {
327                *self = PsbValueFixed::List(PsbListFixed {
328                    values: vec![value.into()],
329                });
330            }
331        }
332    }
333
334    /// Returns the resource ID if this value is a resource reference.
335    pub fn resource_id(&self) -> Option<u64> {
336        match self {
337            PsbValueFixed::Resource(r) => Some(r.resource_ref),
338            _ => None,
339        }
340    }
341
342    /// Returns the extra resource ID if this value is an extra resource reference.
343    pub fn extra_resource_id(&self) -> Option<u64> {
344        match self {
345            PsbValueFixed::ExtraResource(er) => Some(er.extra_resource_ref),
346            _ => None,
347        }
348    }
349
350    /// Converts this value to a JSON value, if possible.
351    #[cfg(feature = "json")]
352    pub fn to_json(&self) -> Option<JsonValue> {
353        match self {
354            PsbValueFixed::Null => Some(JsonValue::Null),
355            PsbValueFixed::Bool(b) => Some(JsonValue::Boolean(*b)),
356            PsbValueFixed::Number(n) => match n {
357                PsbNumber::Integer(i) => Some(JsonValue::Number((*i).into())),
358                PsbNumber::Float(f) => Some(JsonValue::Number((*f).into())),
359                PsbNumber::Double(d) => Some(JsonValue::Number((*d).into())),
360            },
361            PsbValueFixed::String(s) => Some(JsonValue::String(s.string().to_owned())),
362            PsbValueFixed::Resource(s) => {
363                Some(JsonValue::String(format!("#resource#{}", s.resource_ref)))
364            }
365            PsbValueFixed::ExtraResource(s) => Some(JsonValue::String(format!(
366                "#resource@{}",
367                s.extra_resource_ref
368            ))),
369            PsbValueFixed::IntArray(arr) => Some(JsonValue::Array(
370                arr.iter().map(|n| JsonValue::Number((*n).into())).collect(),
371            )),
372            PsbValueFixed::List(l) => Some(l.to_json()),
373            PsbValueFixed::Object(o) => Some(o.to_json()),
374            _ => None,
375        }
376    }
377
378    /// Converts a JSON value to a PSB value.
379    #[cfg(feature = "json")]
380    pub fn from_json(obj: &JsonValue) -> Self {
381        match obj {
382            JsonValue::Null => PsbValueFixed::Null,
383            JsonValue::Boolean(b) => PsbValueFixed::Bool(*b),
384            JsonValue::Number(n) => {
385                let data: f64 = (*n).into();
386                if data.fract() == 0.0 {
387                    PsbValueFixed::Number(PsbNumber::Integer(data as i64))
388                } else {
389                    PsbValueFixed::Number(PsbNumber::Float(data as f32))
390                }
391            }
392            JsonValue::String(s) => {
393                if s.starts_with("#resource#") {
394                    if let Ok(id) = s[10..].parse::<u64>() {
395                        return PsbValueFixed::Resource(PsbResourceRef { resource_ref: id });
396                    }
397                } else if s.starts_with("#resource@") {
398                    if let Ok(id) = s[10..].parse::<u64>() {
399                        return PsbValueFixed::ExtraResource(PsbExtraRef {
400                            extra_resource_ref: id,
401                        });
402                    }
403                }
404                PsbValueFixed::String(PsbString::from(s.clone()))
405            }
406            JsonValue::Array(arr) => {
407                let values: Vec<PsbValueFixed> = arr.iter().map(PsbValueFixed::from_json).collect();
408                PsbValueFixed::List(PsbListFixed { values })
409            }
410            JsonValue::Object(obj) => {
411                let mut values = BTreeMap::new();
412                for (key, value) in obj.iter() {
413                    values.insert(key.to_owned(), PsbValueFixed::from_json(value));
414                }
415                PsbValueFixed::Object(PsbObjectFixed { values })
416            }
417            JsonValue::Short(n) => {
418                let s = n.as_str();
419                if s.starts_with("#resource#") {
420                    if let Ok(id) = s[10..].parse::<u64>() {
421                        return PsbValueFixed::Resource(PsbResourceRef { resource_ref: id });
422                    }
423                } else if s.starts_with("#resource@") {
424                    if let Ok(id) = s[10..].parse::<u64>() {
425                        return PsbValueFixed::ExtraResource(PsbExtraRef {
426                            extra_resource_ref: id,
427                        });
428                    }
429                }
430                PsbValueFixed::String(PsbString::from(s.to_owned()))
431            }
432        }
433    }
434}
435
436impl Index<usize> for PsbValueFixed {
437    type Output = PsbValueFixed;
438
439    fn index(&self, index: usize) -> &Self::Output {
440        match self {
441            PsbValueFixed::List(l) => &l[index],
442            _ => &NONE,
443        }
444    }
445}
446
447impl IndexMut<usize> for PsbValueFixed {
448    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
449        match self {
450            PsbValueFixed::List(l) => {
451                if index < l.values.len() {
452                    &mut l.values[index]
453                } else {
454                    l.values.push(NONE);
455                    l.values.last_mut().unwrap()
456                }
457            }
458            _ => {
459                *self = PsbValueFixed::List(PsbListFixed { values: vec![NONE] });
460                self.index_mut(0)
461            }
462        }
463    }
464}
465
466impl<'a> Index<&'a str> for PsbValueFixed {
467    type Output = PsbValueFixed;
468
469    fn index(&self, index: &'a str) -> &Self::Output {
470        match self {
471            PsbValueFixed::Object(o) => &o[index],
472            _ => &NONE,
473        }
474    }
475}
476
477impl<'a> Index<&'a String> for PsbValueFixed {
478    type Output = PsbValueFixed;
479
480    fn index(&self, index: &'a String) -> &Self::Output {
481        self.index(index.as_str())
482    }
483}
484
485impl Index<String> for PsbValueFixed {
486    type Output = PsbValueFixed;
487
488    fn index(&self, index: String) -> &Self::Output {
489        self.index(index.as_str())
490    }
491}
492
493impl IndexMut<&str> for PsbValueFixed {
494    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
495        match self {
496            PsbValueFixed::Object(o) => o.index_mut(index),
497            _ => {
498                *self = PsbValueFixed::Object(PsbObjectFixed {
499                    values: BTreeMap::new(),
500                });
501                self.index_mut(index)
502            }
503        }
504    }
505}
506
507impl IndexMut<&String> for PsbValueFixed {
508    fn index_mut(&mut self, index: &String) -> &mut Self::Output {
509        self.index_mut(index.as_str())
510    }
511}
512
513impl IndexMut<String> for PsbValueFixed {
514    fn index_mut(&mut self, index: String) -> &mut Self::Output {
515        self.index_mut(index.as_str())
516    }
517}
518
519impl Clone for PsbValueFixed {
520    fn clone(&self) -> Self {
521        match self {
522            PsbValueFixed::None => PsbValueFixed::None,
523            PsbValueFixed::Null => PsbValueFixed::Null,
524            PsbValueFixed::Bool(b) => PsbValueFixed::Bool(*b),
525            PsbValueFixed::Number(n) => PsbValueFixed::Number(n.clone()),
526            PsbValueFixed::IntArray(arr) => PsbValueFixed::IntArray(arr.clone()),
527            PsbValueFixed::String(s) => PsbValueFixed::String(PsbString::from(s.string().clone())),
528            PsbValueFixed::List(l) => PsbValueFixed::List(l.clone()),
529            PsbValueFixed::Object(o) => PsbValueFixed::Object(o.clone()),
530            PsbValueFixed::Resource(r) => PsbValueFixed::Resource(r.clone()),
531            PsbValueFixed::ExtraResource(er) => PsbValueFixed::ExtraResource(er.clone()),
532            PsbValueFixed::CompilerNumber => PsbValueFixed::CompilerNumber,
533            PsbValueFixed::CompilerString => PsbValueFixed::CompilerString,
534            PsbValueFixed::CompilerResource => PsbValueFixed::CompilerResource,
535            PsbValueFixed::CompilerDecimal => PsbValueFixed::CompilerDecimal,
536            PsbValueFixed::CompilerArray => PsbValueFixed::CompilerArray,
537            PsbValueFixed::CompilerBool => PsbValueFixed::CompilerBool,
538            PsbValueFixed::CompilerBinaryTree => PsbValueFixed::CompilerBinaryTree,
539        }
540    }
541}
542
543impl PartialEq<String> for PsbValueFixed {
544    fn eq(&self, other: &String) -> bool {
545        self == other.as_str()
546    }
547}
548
549impl PartialEq<str> for PsbValueFixed {
550    fn eq(&self, other: &str) -> bool {
551        match self {
552            PsbValueFixed::String(s) => s.string() == other,
553            _ => false,
554        }
555    }
556}
557
558impl<'a> PartialEq<&'a str> for PsbValueFixed {
559    fn eq(&self, other: &&'a str) -> bool {
560        self == *other
561    }
562}
563
564/// Trait to convert a PSB value to a fixed PSB value.
565pub trait PsbValueExt {
566    /// Converts this PSB value to a fixed PSB value.
567    fn to_psb_fixed(self) -> PsbValueFixed;
568}
569
570impl PsbValueExt for PsbValue {
571    fn to_psb_fixed(self) -> PsbValueFixed {
572        match self {
573            PsbValue::None => PsbValueFixed::None,
574            PsbValue::Null => PsbValueFixed::Null,
575            PsbValue::Bool(b) => PsbValueFixed::Bool(b),
576            PsbValue::Number(n) => PsbValueFixed::Number(n),
577            PsbValue::IntArray(arr) => PsbValueFixed::IntArray(arr),
578            PsbValue::String(s) => PsbValueFixed::String(s),
579            PsbValue::List(l) => PsbValueFixed::List(PsbList::to_psb_fixed(l)),
580            PsbValue::Object(o) => PsbValueFixed::Object(PsbObject::to_psb_fixed(o)),
581            PsbValue::Resource(r) => PsbValueFixed::Resource(r),
582            PsbValue::ExtraResource(er) => PsbValueFixed::ExtraResource(er),
583            PsbValue::CompilerNumber => PsbValueFixed::CompilerNumber,
584            PsbValue::CompilerString => PsbValueFixed::CompilerString,
585            PsbValue::CompilerResource => PsbValueFixed::CompilerResource,
586            PsbValue::CompilerDecimal => PsbValueFixed::CompilerDecimal,
587            PsbValue::CompilerArray => PsbValueFixed::CompilerArray,
588            PsbValue::CompilerBool => PsbValueFixed::CompilerBool,
589            PsbValue::CompilerBinaryTree => PsbValueFixed::CompilerBinaryTree,
590        }
591    }
592}
593
594#[derive(Clone, Debug, Serialize, Deserialize)]
595#[serde(transparent)]
596/// Represents a PSB list of PSB values.
597pub struct PsbListFixed {
598    /// The values in the list.
599    pub values: Vec<PsbValueFixed>,
600}
601
602impl PsbListFixed {
603    /// Converts this PSB list to a original PSB list.
604    pub fn to_psb(self, warn_on_none: bool) -> PsbList {
605        let v: Vec<_> = self
606            .values
607            .into_iter()
608            .map(|v| v.to_psb(warn_on_none))
609            .collect();
610        PsbList::from(v)
611    }
612
613    /// Find the resource's key in object
614    pub fn find_resource_key<'a>(
615        &'a self,
616        resource_id: u64,
617        now: Vec<&'a str>,
618    ) -> Option<Vec<&'a str>> {
619        for value in &self.values {
620            if let Some(key) = value.find_resource_key(resource_id, now.clone()) {
621                return Some(key);
622            }
623        }
624        None
625    }
626
627    /// Find the extra resource's key in object
628    pub fn find_extra_resource_key<'a>(
629        &'a self,
630        extra_resource_id: u64,
631        now: Vec<&'a str>,
632    ) -> Option<Vec<&'a str>> {
633        for value in &self.values {
634            if let Some(key) = value.find_extra_resource_key(extra_resource_id, now.clone()) {
635                return Some(key);
636            }
637        }
638        None
639    }
640
641    /// Returns a iterator over the values in the list.
642    pub fn iter(&self) -> ListIter<'_> {
643        ListIter {
644            inner: self.values.iter(),
645        }
646    }
647
648    /// Returns a mutable iterator over the values in the list.
649    pub fn iter_mut(&mut self) -> ListIterMut<'_> {
650        ListIterMut {
651            inner: self.values.iter_mut(),
652        }
653    }
654
655    /// Returns a reference to the values in the list.
656    pub fn values(&self) -> &Vec<PsbValueFixed> {
657        &self.values
658    }
659
660    /// Returns the length of the list.
661    pub fn len(&self) -> usize {
662        self.values.len()
663    }
664
665    /// Clears all values in the list.
666    pub fn clear(&mut self) {
667        self.values.clear();
668    }
669
670    /// Inserts a new value at the specified index in the list.
671    /// If the index is out of bounds, the value will be appended to the end of the list.
672    pub fn insert<V: Into<PsbValueFixed>>(&mut self, index: usize, value: V) {
673        if index <= self.values.len() {
674            self.values.insert(index, value.into());
675        } else {
676            self.values.push(value.into());
677        }
678    }
679
680    /// Converts this PSB list to a JSON value.
681    #[cfg(feature = "json")]
682    pub fn to_json(&self) -> JsonValue {
683        let data: Vec<_> = self.values.iter().filter_map(|v| v.to_json()).collect();
684        JsonValue::Array(data)
685    }
686}
687
688impl Index<usize> for PsbListFixed {
689    type Output = PsbValueFixed;
690
691    fn index(&self, index: usize) -> &Self::Output {
692        self.values.get(index).unwrap_or(&NONE)
693    }
694}
695
696impl IndexMut<usize> for PsbListFixed {
697    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
698        if index < self.values.len() {
699            &mut self.values[index]
700        } else {
701            self.values.push(NONE);
702            self.values.last_mut().unwrap()
703        }
704    }
705}
706
707/// Iterator for a slice of PSB values in a list.
708pub struct ListIter<'a> {
709    inner: std::slice::Iter<'a, PsbValueFixed>,
710}
711
712impl<'a> ListIter<'a> {
713    /// Creates an empty iterator.
714    pub fn empty() -> Self {
715        ListIter {
716            inner: Default::default(),
717        }
718    }
719}
720
721impl<'a> Iterator for ListIter<'a> {
722    type Item = &'a PsbValueFixed;
723
724    #[inline(always)]
725    fn next(&mut self) -> Option<Self::Item> {
726        self.inner.next()
727    }
728}
729
730impl<'a> ExactSizeIterator for ListIter<'a> {
731    fn len(&self) -> usize {
732        self.inner.len()
733    }
734}
735
736impl<'a> DoubleEndedIterator for ListIter<'a> {
737    #[inline(always)]
738    fn next_back(&mut self) -> Option<Self::Item> {
739        self.inner.next_back()
740    }
741}
742
743/// Mutable iterator for a slice of PSB values in a list.
744pub struct ListIterMut<'a> {
745    inner: std::slice::IterMut<'a, PsbValueFixed>,
746}
747
748impl<'a> ListIterMut<'a> {
749    /// Creates an empty mutable iterator.
750    pub fn empty() -> Self {
751        ListIterMut {
752            inner: Default::default(),
753        }
754    }
755}
756
757impl<'a> Iterator for ListIterMut<'a> {
758    type Item = &'a mut PsbValueFixed;
759
760    #[inline(always)]
761    fn next(&mut self) -> Option<Self::Item> {
762        self.inner.next()
763    }
764}
765
766impl<'a> ExactSizeIterator for ListIterMut<'a> {
767    fn len(&self) -> usize {
768        self.inner.len()
769    }
770}
771
772impl<'a> DoubleEndedIterator for ListIterMut<'a> {
773    #[inline(always)]
774    fn next_back(&mut self) -> Option<Self::Item> {
775        self.inner.next_back()
776    }
777}
778
779/// Trait to convert a PSB list to a fixed PSB list.
780pub trait PsbListExt {
781    /// Converts this PSB list to a fixed PSB list.
782    fn to_psb_fixed(self) -> PsbListFixed;
783}
784
785impl PsbListExt for PsbList {
786    fn to_psb_fixed(self) -> PsbListFixed {
787        let values: Vec<_> = self
788            .unwrap()
789            .into_iter()
790            .map(PsbValue::to_psb_fixed)
791            .collect();
792        PsbListFixed { values }
793    }
794}
795
796#[derive(Clone, Debug, Serialize, Deserialize)]
797#[serde(transparent)]
798/// Represents a PSB object with key-value pairs.
799pub struct PsbObjectFixed {
800    /// The key-value pairs in the object.
801    pub values: BTreeMap<String, PsbValueFixed>,
802}
803
804impl PsbObjectFixed {
805    pub fn new() -> Self {
806        Self {
807            values: BTreeMap::new(),
808        }
809    }
810
811    /// Creates a new empty PSB object.
812    pub fn to_psb(self, warn_on_none: bool) -> PsbObject {
813        let mut hash_map = HashMap::new();
814        for (key, value) in self.values {
815            hash_map.insert(key, value.to_psb(warn_on_none));
816        }
817        PsbObject::from(hash_map)
818    }
819
820    /// Gets a reference of value in the object by key.
821    pub fn get_value(&self, key: &str) -> Option<&PsbValueFixed> {
822        self.values.get(key)
823    }
824
825    /// Find the resource's key in object
826    pub fn find_resource_key<'a>(
827        &'a self,
828        resource_id: u64,
829        now: Vec<&'a str>,
830    ) -> Option<Vec<&'a str>> {
831        for (key, value) in &self.values {
832            let mut now = now.clone();
833            now.push(key);
834            if let Some(id) = value.resource_id() {
835                if id == resource_id {
836                    return Some(now);
837                }
838            }
839            if let Some(key) = value.find_resource_key(resource_id, now) {
840                return Some(key);
841            }
842        }
843        None
844    }
845
846    /// Find the extra resource's key in object
847    pub fn find_extra_resource_key<'a>(
848        &'a self,
849        extra_resource_id: u64,
850        now: Vec<&'a str>,
851    ) -> Option<Vec<&'a str>> {
852        for (key, value) in &self.values {
853            let mut now = now.clone();
854            now.push(key);
855            if let Some(id) = value.extra_resource_id() {
856                if id == extra_resource_id {
857                    return Some(now);
858                }
859            }
860            if let Some(key) = value.find_extra_resource_key(extra_resource_id, now) {
861                return Some(key);
862            }
863        }
864        None
865    }
866
867    /// Returns a iterator over the entries of the object.
868    pub fn iter(&self) -> ObjectIter<'_> {
869        ObjectIter {
870            inner: self.values.iter(),
871        }
872    }
873
874    /// Returns a mutable iterator over the entries of the object.
875    pub fn iter_mut(&mut self) -> ObjectIterMut<'_> {
876        ObjectIterMut {
877            inner: self.values.iter_mut(),
878        }
879    }
880
881    /// Converts this PSB object to a JSON value.
882    #[cfg(feature = "json")]
883    pub fn to_json(&self) -> JsonValue {
884        let mut obj = json::object::Object::new();
885        for (key, value) in &self.values {
886            if let Some(json_value) = value.to_json() {
887                obj.insert(key, json_value);
888            }
889        }
890        JsonValue::Object(obj)
891    }
892
893    /// Converts a JSON object to a PSB object.
894    #[cfg(feature = "json")]
895    pub fn from_json(obj: &JsonValue) -> Self {
896        let mut values = BTreeMap::new();
897        for (key, value) in obj.entries() {
898            values.insert(key.to_owned(), PsbValueFixed::from_json(value));
899        }
900        PsbObjectFixed { values }
901    }
902}
903
904impl<'a> Index<&'a str> for PsbObjectFixed {
905    type Output = PsbValueFixed;
906
907    fn index(&self, index: &'a str) -> &Self::Output {
908        self.values.get(index).unwrap_or(&NONE)
909    }
910}
911
912impl<'a> Index<&'a String> for PsbObjectFixed {
913    type Output = PsbValueFixed;
914
915    fn index(&self, index: &'a String) -> &Self::Output {
916        self.index(index.as_str())
917    }
918}
919
920impl Index<String> for PsbObjectFixed {
921    type Output = PsbValueFixed;
922
923    fn index(&self, index: String) -> &Self::Output {
924        self.index(index.as_str())
925    }
926}
927
928impl<'a> IndexMut<&'a str> for PsbObjectFixed {
929    fn index_mut(&mut self, index: &'a str) -> &mut Self::Output {
930        self.values.entry(index.to_string()).or_insert(NONE)
931    }
932}
933
934impl<'a> IndexMut<&'a String> for PsbObjectFixed {
935    fn index_mut(&mut self, index: &'a String) -> &mut Self::Output {
936        self.index_mut(index.as_str())
937    }
938}
939
940impl IndexMut<String> for PsbObjectFixed {
941    fn index_mut(&mut self, index: String) -> &mut Self::Output {
942        self.values.entry(index).or_insert(NONE)
943    }
944}
945
946/// Trait to convert a PSB object to a fixed PSB object.
947pub trait PsbObjectExt {
948    /// Converts this PSB object to a fixed PSB object.
949    fn to_psb_fixed(self) -> PsbObjectFixed;
950}
951
952impl PsbObjectExt for PsbObject {
953    fn to_psb_fixed(self) -> PsbObjectFixed {
954        let mut hash_map = BTreeMap::new();
955        for (key, value) in self.unwrap() {
956            hash_map.insert(key, PsbValue::to_psb_fixed(value));
957        }
958        PsbObjectFixed { values: hash_map }
959    }
960}
961
962/// Iterator for a slice of PSB values in an object.
963pub struct ObjectIter<'a> {
964    inner: std::collections::btree_map::Iter<'a, String, PsbValueFixed>,
965}
966
967impl<'a> ObjectIter<'a> {
968    /// Creates an empty iterator.
969    pub fn empty() -> Self {
970        ObjectIter {
971            inner: Default::default(),
972        }
973    }
974}
975
976impl<'a> Iterator for ObjectIter<'a> {
977    type Item = (&'a String, &'a PsbValueFixed);
978
979    #[inline(always)]
980    fn next(&mut self) -> Option<Self::Item> {
981        self.inner.next()
982    }
983}
984
985impl<'a> ExactSizeIterator for ObjectIter<'a> {
986    fn len(&self) -> usize {
987        self.inner.len()
988    }
989}
990
991impl<'a> DoubleEndedIterator for ObjectIter<'a> {
992    #[inline(always)]
993    fn next_back(&mut self) -> Option<Self::Item> {
994        self.inner.next_back()
995    }
996}
997
998/// Mutable iterator for a slice of PSB values in an object.
999pub struct ObjectIterMut<'a> {
1000    inner: std::collections::btree_map::IterMut<'a, String, PsbValueFixed>,
1001}
1002
1003impl<'a> ObjectIterMut<'a> {
1004    /// Creates an empty mutable iterator.
1005    pub fn empty() -> Self {
1006        ObjectIterMut {
1007            inner: Default::default(),
1008        }
1009    }
1010}
1011
1012impl<'a> Iterator for ObjectIterMut<'a> {
1013    type Item = (&'a String, &'a mut PsbValueFixed);
1014
1015    #[inline(always)]
1016    fn next(&mut self) -> Option<Self::Item> {
1017        self.inner.next()
1018    }
1019}
1020
1021impl<'a> ExactSizeIterator for ObjectIterMut<'a> {
1022    fn len(&self) -> usize {
1023        self.inner.len()
1024    }
1025}
1026
1027impl<'a> DoubleEndedIterator for ObjectIterMut<'a> {
1028    #[inline(always)]
1029    fn next_back(&mut self) -> Option<Self::Item> {
1030        self.inner.next_back()
1031    }
1032}
1033
1034/// Represents a fixed version of a virtual PSB.
1035#[derive(Clone, Debug)]
1036pub struct VirtualPsbFixed {
1037    header: PsbHeader,
1038    resources: Vec<Vec<u8>>,
1039    extra: Vec<Vec<u8>>,
1040    root: PsbObjectFixed,
1041}
1042
1043impl Serialize for VirtualPsbFixed {
1044    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1045    where
1046        S: serde::Serializer,
1047    {
1048        let mut state = serializer.serialize_struct("VirtualPsbFixed", 3)?;
1049        state.serialize_field("version", &self.header.version)?;
1050        state.serialize_field("encryption", &self.header.encryption)?;
1051        state.serialize_field("data", &self.root)?;
1052        state.end()
1053    }
1054}
1055
1056#[derive(Deserialize)]
1057pub struct VirtualPsbFixedData {
1058    version: u16,
1059    encryption: u16,
1060    data: PsbObjectFixed,
1061}
1062
1063impl VirtualPsbFixed {
1064    /// Creates a new fixed virtual PSB.
1065    pub fn new(
1066        header: PsbHeader,
1067        resources: Vec<Vec<u8>>,
1068        extra: Vec<Vec<u8>>,
1069        root: PsbObjectFixed,
1070    ) -> Self {
1071        Self {
1072            header,
1073            resources,
1074            extra,
1075            root,
1076        }
1077    }
1078
1079    /// Returns the header of the PSB.
1080    pub fn header(&self) -> PsbHeader {
1081        self.header
1082    }
1083
1084    /// Returns a reference to the resources of the PSB.
1085    pub fn resources(&self) -> &Vec<Vec<u8>> {
1086        &self.resources
1087    }
1088
1089    /// Returns a mutable reference to the resources of the PSB.
1090    pub fn resources_mut(&mut self) -> &mut Vec<Vec<u8>> {
1091        &mut self.resources
1092    }
1093
1094    /// Returns a reference to the extra resources of the PSB.
1095    pub fn extra(&self) -> &Vec<Vec<u8>> {
1096        &self.extra
1097    }
1098
1099    /// Returns a mutable reference to the extra resources of the PSB.
1100    pub fn extra_mut(&mut self) -> &mut Vec<Vec<u8>> {
1101        &mut self.extra
1102    }
1103
1104    /// Returns a reference to the root object of the PSB.
1105    pub fn root(&self) -> &PsbObjectFixed {
1106        &self.root
1107    }
1108
1109    /// Returns a mutable reference to the root object of the PSB.
1110    pub fn root_mut(&mut self) -> &mut PsbObjectFixed {
1111        &mut self.root
1112    }
1113
1114    /// Sets the root of the PSB.
1115    pub fn set_root(&mut self, root: PsbObjectFixed) {
1116        self.root = root;
1117    }
1118
1119    /// Unwraps the PSB into its components.
1120    pub fn unwrap(self) -> (PsbHeader, Vec<Vec<u8>>, Vec<Vec<u8>>, PsbObjectFixed) {
1121        (self.header, self.resources, self.extra, self.root)
1122    }
1123
1124    /// Converts this fixed PSB to a virtual PSB.
1125    pub fn to_psb(self, warn_on_none: bool) -> VirtualPsb {
1126        let (header, resources, extra, root) = self.unwrap();
1127        VirtualPsb::new(header, resources, extra, root.to_psb(warn_on_none))
1128    }
1129
1130    /// Converts json object to a fixed PSB.
1131    #[cfg(feature = "json")]
1132    pub fn from_json(&mut self, obj: &JsonValue) -> Result<(), anyhow::Error> {
1133        let version = obj["version"]
1134            .as_u16()
1135            .ok_or_else(|| anyhow::anyhow!("Invalid PSB version"))?;
1136        let encryption = obj["encryption"]
1137            .as_u16()
1138            .ok_or_else(|| anyhow::anyhow!("Invalid PSB encryption"))?;
1139        self.header.version = version;
1140        self.header.encryption = encryption;
1141        self.root = PsbObjectFixed::from_json(&obj["data"]);
1142        Ok(())
1143    }
1144
1145    #[cfg(feature = "json")]
1146    /// Creates a fixed PSB from a JSON object.
1147    pub fn with_json(obj: &JsonValue) -> Result<Self, anyhow::Error> {
1148        let version = obj["version"]
1149            .as_u16()
1150            .ok_or_else(|| anyhow::anyhow!("Invalid PSB version"))?;
1151        let encryption = obj["encryption"]
1152            .as_u16()
1153            .ok_or_else(|| anyhow::anyhow!("Invalid PSB encryption"))?;
1154        let root = PsbObjectFixed::from_json(&obj["data"]);
1155        Ok(Self {
1156            header: PsbHeader {
1157                version,
1158                encryption,
1159            },
1160            resources: Vec::new(),
1161            extra: Vec::new(),
1162            root,
1163        })
1164    }
1165
1166    pub fn set_data(&mut self, data: VirtualPsbFixedData) {
1167        self.header.version = data.version;
1168        self.header.encryption = data.encryption;
1169        self.root = data.data;
1170    }
1171
1172    /// Converts this fixed PSB to a JSON object.
1173    #[cfg(feature = "json")]
1174    pub fn to_json(&self) -> JsonValue {
1175        json::object! {
1176            "version": self.header.version,
1177            "encryption": self.header.encryption,
1178            "data": self.root.to_json(),
1179        }
1180    }
1181}
1182
1183/// Trait to convert a virtual PSB to a fixed PSB.
1184pub trait VirtualPsbExt {
1185    /// Converts this virtual PSB to a fixed PSB.
1186    fn to_psb_fixed(self) -> VirtualPsbFixed;
1187}
1188
1189impl VirtualPsbExt for VirtualPsb {
1190    fn to_psb_fixed(self) -> VirtualPsbFixed {
1191        let (header, resources, extra, root) = self.unwrap();
1192        VirtualPsbFixed::new(header, resources, extra, root.to_psb_fixed())
1193    }
1194}