1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*!
Types for reading and writing League of Legends
property bin files (`.bin`).
Property bins are hierarchical data structures used throughout League's
game data. They contain objects with typed properties that can reference
other objects and external files.
## Quick Start
### Reading a bin file
```no_run
use std::fs::File;
use ltk_meta::Bin;
let mut file = File::open("data.bin")?;
let tree = Bin::from_reader(&mut file)?;
for (path_hash, object) in &tree.objects {
println!("Object {:08x} has {} properties", path_hash, object.properties.len());
}
# Ok::<(), Box<dyn std::error::Error>>(())
```
### Creating a bin file programmatically
```
use ltk_meta::{Bin, BinObject};
use ltk_meta::property::{values, NoMeta};
// Using the builder pattern
let tree = Bin::builder()
.dependency("common.bin")
.object(
BinObject::<NoMeta>::builder(0x12345678, 0xABCDEF00)
.property(0x1111, values::I32::new(42))
.property(0x2222, values::String::from("hello"))
.build()
)
.build();
// Or using the simple constructor
let tree = Bin::new(
[BinObject::<NoMeta>::new(0x1234, 0x5678)],
["dependency.bin"],
);
```
### Modifying a bin file
```no_run
use std::fs::File;
use std::io::Cursor;
use ltk_meta::{Bin, BinObject};
let mut file = File::open("data.bin")?;
let mut tree = Bin::from_reader(&mut file)?;
// Add a new object
tree.add_object(BinObject::new(0x11112222, 0x33334444));
// Remove an object
tree.remove_object(0x55556666);
// Write back
let mut output = Cursor::new(Vec::new());
tree.to_writer(&mut output)?;
# Ok::<(), Box<dyn std::error::Error>>(())
```
### Reading an override bin
Some bins are `PTCH` files: a patch of deletions, extra objects and property patch
records applied over one base bin. They are [`BinOverride`], not [`Bin`].
```no_run
use std::fs::File;
use ltk_meta::BinOverride;
let mut file = File::open("uiflipped.bin")?;
let patch_bin = BinOverride::from_reader(&mut file)?;
for patch in &patch_bin.patches {
// e.g. `4a47c414 Position.Anchors.Anchor = Vector2`
println!("{:08x} {} = {:?}", patch.object_hash, patch.path, patch.kind());
}
# Ok::<(), Box<dyn std::error::Error>>(())
```
### Reading a `.bin` of unknown kind
The extension does not say which kind a file is, so either read it as a [`BinFile`] and
match on what came back, or ask [`BinKind::identify_from_reader`] and call the reader you
want. It leaves the magic in place, so the same reader can be handed straight on.
```no_run
use std::fs::File;
use ltk_meta::{Bin, BinFile, BinKind, BinOverride};
let mut file = File::open("unknown.bin")?;
match BinFile::from_reader(&mut file)? {
BinFile::Prop(bin) => println!("{} objects", bin.objects.len()),
BinFile::Override(patch_bin) => println!("{} patches", patch_bin.patches.len()),
}
let mut file = File::open("unknown.bin")?;
match BinKind::identify_from_reader(&mut file)? {
BinKind::Prop => { let bin = Bin::from_reader(&mut file)?; }
BinKind::Override => { let patch_bin = BinOverride::from_reader(&mut file)?; }
}
# Ok::<(), Box<dyn std::error::Error>>(())
```
*/
pub use ;
pub use *;
pub use ;
pub use ;
pub use *;