realm_db_reader/
group.rs

1use tracing::{instrument, warn};
2
3use crate::array::{Array, ArrayStringShort};
4use crate::table::Table;
5use crate::traits::ArrayLike;
6
7/// The group is the central root of a Realm database. It contains all the
8/// tables and their names.
9///
10/// The main way to interact with the Realm database, is by opening the
11/// [`Realm`](crate::Realm::open), and calling
12/// [`realm.into_group`][`crate::Realm::into_group`]. The resulting [`Group`]
13/// can then be used to access tables.
14///
15/// ```no_run
16/// use realm_db_reader::{Realm, Group};
17///
18/// let realm = Realm::open("example.realm").unwrap();
19/// let group = realm.into_group().unwrap();
20///
21/// let table = group.get_table(0).unwrap();
22/// let row = table.get_row(0).unwrap();
23/// ```
24#[derive(Debug)]
25pub struct Group {
26    tables_array: Array,
27    table_names: Vec<String>,
28}
29
30impl Group {
31    #[instrument(level = "debug")]
32    pub(crate) fn build(array: Array) -> anyhow::Result<Self> {
33        let table_names = {
34            let array: ArrayStringShort = array.get_node(0)?.unwrap();
35            array.get_all()?
36        };
37
38        let tables_array = array.get_node(1)?.unwrap();
39
40        Ok(Self {
41            tables_array,
42            table_names,
43        })
44    }
45}
46
47impl Group {
48    /// Get the [`Table`] with the given number (starting from 0).
49    ///
50    /// Panics if the table number is out of bounds.
51    #[instrument(level = "debug", skip(self), fields(table_names = ?self.table_names))]
52    pub fn get_table(&self, table_number: usize) -> anyhow::Result<Table> {
53        let table_array = self.tables_array.get_node(table_number)?.unwrap();
54
55        let table = Table::build(table_array, table_number)?;
56
57        Ok(table)
58    }
59
60    /// Get the [`Table`] with the given name.
61    ///
62    /// Panics if the table name is not found.
63    #[instrument(level = "debug", skip(self), fields(table_names = ?self.table_names))]
64    pub fn get_table_by_name(&self, name: &str) -> anyhow::Result<Table> {
65        let table_number = self
66            .table_names
67            .iter()
68            .position(|n| n == name)
69            .ok_or(anyhow::anyhow!("No table with name {name}"))?;
70
71        self.get_table(table_number)
72    }
73
74    /// Get the number of tables in the group.
75    pub fn table_count(&self) -> usize {
76        self.table_names.len()
77    }
78
79    /// Get the name of the table at the given index.
80    ///
81    /// Panics if the index is out of bounds.
82    pub fn get_table_name(&self, index: usize) -> &str {
83        &self.table_names[index]
84    }
85
86    /// Get the names of all tables in the group.
87    pub fn get_table_names(&self) -> &[String] {
88        &self.table_names
89    }
90}