oxyroot/
lib.rs

1/*!
2This crate aims to provide a way to open and write  data in [ROOT](https://root.cern.ch/) file format
3and particularly `Tree` and `Branch` inside `Tree`.
4This crate is in fact a port of [groot](https://pkg.go.dev/go-hep.org/x/hep/groot) written
5in Go and  [uproot](https://github.com/scikit-hep/uproot5) written in Python.
6
7To read from a branch and write to a branch, the API is iterator based :
8- by branch:
9    - [`as_iter`](enum.Branch.html#method.as_iter) to read from a branch. The type to read is provided as a type parameter.
10    This type has to implement `Unmarshaler` trait.
11    - [`new_branch`](type.WriterTree.html#method.new_branch) from [`WriterTree`](type.WriterTree.html) to write to a branch. The method
12    [`write`](type.WriterTree.html#method.write) from [`WriterTree`](crate::WriterTree) is used
13    to write the data to the file by exhausting provided iterators. The type to write has to implement
14    [`Marshaler`](crate::Marshaler) trait. The type is deduced from the iterator.
15- by Tree, by creating struct from several branches, thanks to the [`ReadFromTree`](trait.ReadFromTree.html) and [`WriteToTree`](trait.WriteToTree.html) traits. These traits
16can be automatically derived with the `derive` feature which provides macros [`ReadFromTree`](derive.ReadFromTree.html) and [`WriteToTree`](derive.WriteToTree.html).
17
18# Example: Iter over a branch tree containing `i32` values
19
20```rust
21use oxyroot::RootFile;
22let s = "examples/from_uproot/data/simple.root";
23let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
24let one = tree.branch("one").unwrap().as_iter::<i32>().expect("wrong type");
25one.for_each(|v| println!("v = {v}"));
26```
27
28# Example : Read custom struct from branches
29```no_run
30use oxyroot::{ReadFromTree, RootFile};
31
32#[derive(ReadFromTree)]
33struct MyStruct {
34     a: i32,     // will be read from branch "a" as 32 bits integer
35     s: String,  // will be read from branch "s" as String
36}
37let tree = RootFile::open("in.root").unwrap().get_tree("tree").unwrap();
38MyStruct::from_tree(&tree).unwrap().map(|m: MyStruct | {  /* do something with m */ });
39```
40
41More information and examples here : [`ReadFromTree`](derive.ReadFromTree.html)
42
43# Example: Show branches from a tree
44
45```rust
46use oxyroot::RootFile;
47let s = "examples/from_uproot/data/simple.root";
48let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
49tree.show();
50```
51
52will display
53
54```ignore
55name                           | typename                       | interpretation
56-------------------------------+-------------------------------+-------------------------------
57one                            | int32_t                        | i32
58two                            | float                          | f32
59three                          | char*                          | String
60```
61
62
63
64# Example: Write i32 values in a branch
65
66```rust
67use oxyroot::{RootFile, WriterTree};
68let s = "/tmp/simple.root";
69let mut file = RootFile::create(s).expect("Can not create file");
70let mut tree = WriterTree::new("mytree");
71let it = (0..15);
72tree.new_branch("it", it);
73tree.write(&mut file).expect("Can not write tree");
74file.close().expect("Can not close file");
75```
76
77# Example: Iter over a branch tree containing `Vec<i32>`  (aka `std::vector<int32_t>`) values
78
79```rust
80use oxyroot::RootFile;
81let s = "tests/stl_containers/stl_containers.root";
82let tree = RootFile::open(s).expect("Can not open file").get_tree("tree").unwrap();
83let vector_int32 = tree.branch("vector_int32")
84                   .unwrap().as_iter::<Vec<i32>>().expect("wrong type")
85                   .collect::<Vec<_>>();
86assert_eq!(
87    vector_int32,
88    [
89        vec![1],
90        vec![1, 2],
91        vec![1, 2, 3],
92        vec![1, 2, 3, 4],
93        vec![1, 2, 3, 4, 5]
94    ]
95);
96```
97
98# Which types can be read from a branch?
99
100## Primitives and C++ STL standards
101
102oxyroot can iterate over  branch which contains :
103- primitive types like i32, f64, bool...
104- String (from TString, char* or std::string)
105- Vec (from std::vector or array)
106- HashMap
107
108
109| C++ | Rust |
110|---------|---------|
111| std::string     | [String](String)     |
112| std::vector     | [Vec](Vec)     |
113| std::map     | [HashMap](std::collections::HashMap)    |
114| std::set     | [HashSet](std::collections::HashSet)      |
115| T*     | [`Slice<T>`](Slice)    |
116| T\[N\]     | [array]     |
117| TString     | [String]     |
118
119
120Examples can be found in tests.
121
122## Structures
123Structure serialized in `Branch` can be also read but the parsing code has to be written :
124
125```C++
126struct sd_t {
127         Int_t a;
128         Int_t b;
129};
130
131sd_t sd;
132tree->Branch("v_i",&sd, 3200000, 0);
133```
134
135The `sd` struct can be read with a code like this :
136
137
138```no_run
139use oxyroot::RBuffer;
140use oxyroot::RootFile;
141struct Sd {
142    a: i32,
143    b: i32,
144};
145
146let parse = |r: &mut RBuffer| Sd {
147    a: r.read_i32().unwrap(),
148    b: r.read_i32().unwrap(),
149};
150
151
152let s = "tests_data/doc/struct_sd.root";
153let tree = RootFile::open(s).expect("Can not open file").get_tree("T").unwrap();
154
155// branch v_i contains v_i which will be zipped.
156let mut b = tree.branch("v_i").unwrap().get_basket(parse);
157
158for i in -10..10 {
159    let sd = b.next().unwrap();
160}
161```
162
163# Which types can be written to a branch?
164
165## Primitives and C++ STL standards
166
167oxyroot can iterate over  branch which contains :
168- primitive types like i32, f64, bool...
169- String (will appear as a char*)
170- Vec (to std::vector)
171- HashMap (not yet implemented)
172
173
174 */
175
176#![allow(dead_code)]
177#![deny(unused_must_use)]
178// #![deny(unused_imports)]
179
180// Show which crate feature enables conditionally compiled APIs in documentation.
181#![cfg_attr(doc_cfg, feature(doc_cfg))]
182
183extern crate core;
184
185mod error;
186mod gen_factory;
187pub mod rbase;
188
189mod rbytes;
190mod rcolors;
191mod rcompress;
192pub mod rcont;
193mod rdict;
194mod riofs;
195mod rmeta;
196mod root;
197pub mod rtree;
198mod rtypes;
199mod rusty;
200mod rvers;
201mod utils;
202
203pub use riofs::file::RootFile;
204pub use rtree::branch::Branch;
205pub use rtree::tree::reader::ReaderTree;
206
207pub use rtree::tree::traits::ReadFromTree;
208pub use rtree::tree::traits::ReadFromTreeResult;
209pub use rtree::tree::traits::WriteToTree;
210
211pub use rtree::tree::WriterTree;
212// pub use rtree::tree::Tree;
213
214pub use rbytes::rbuffer::RBuffer;
215pub use rbytes::Unmarshaler;
216pub use rbytes::UnmarshalerInto;
217
218pub use rbytes::Marshaler;
219
220pub use rusty::SizedSlice;
221pub use rusty::Slice;
222
223pub use root::traits::Named;
224pub use root::traits::Object;
225
226pub use error::Result;
227
228/// Derive macro available if oxyroot is built with `features = ["derive"]`.
229#[cfg(feature = "derive")]
230#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
231pub use oxyroot_derive::{ReadFromTree, WriteToTree};
232
233pub use rtree::tree::branch_name::BranchName;
234pub use rtree::tree::StateCallBack;