realm_db_reader/table/
row.rs

1use std::{borrow::Cow, collections::HashMap};
2
3use crate::value::{Backlink, Value};
4
5/// A single row in a Realm table. This allows you to either extract [`Value`]s
6/// manually, or use [`realm_model!`](`crate::realm_model`) to convert them into
7/// your own structs.
8#[derive(Debug, Clone)]
9pub struct Row<'a> {
10    values: HashMap<Cow<'a, str>, Value>,
11    backlinks: Vec<Backlink>,
12}
13
14impl<'a> Row<'a> {
15    pub(crate) fn new(mut row: Vec<Value>, column_names: Vec<Cow<'a, str>>) -> Self {
16        let backlinks = row
17            .extract_if(.., |v| matches!(v, Value::BackLink(_)))
18            .map(|v| {
19                v.try_into()
20                    .expect("already matched the right value variant")
21            })
22            .collect();
23        let values = column_names
24            .into_iter()
25            .enumerate()
26            .rev()
27            .map(|(index, name)| (name, row.remove(index)))
28            .collect();
29
30        Self { values, backlinks }
31    }
32
33    /// Returns an iterator over the column names and values in this row.
34    pub fn entries(&self) -> impl Iterator<Item = (&Cow<'a, str>, &Value)> {
35        self.values.iter()
36    }
37
38    /// Returns an iterator over the values in this row.
39    pub fn values(&self) -> impl Iterator<Item = &Value> {
40        self.values.values()
41    }
42
43    /// Get the value of a column by its name. Returns `None` if the column does
44    /// not exist.
45    pub fn get(&self, column_name: &str) -> Option<&Value> {
46        self.values.get(column_name)
47    }
48
49    /// Take the value of a column by its name. Returns `None` if the column
50    /// does not exist. This method consumes the value, removing it from the
51    /// row. It is used by [`realm_model`](crate::realm_model) to transfer the
52    /// backlinks to your custom struct.
53    pub fn take(&mut self, column_name: &str) -> Option<Value> {
54        self.values.remove(column_name)
55    }
56
57    /// Returns an iterator over the [`Backlink`]s in this row.
58    pub fn backlinks(&self) -> impl Iterator<Item = &Backlink> {
59        self.backlinks.iter()
60    }
61
62    /// Take the [`Backlink`]s in this row. This method consumes the backlinks,
63    /// removing them from the row. It is used by
64    /// [`realm_model`](crate::realm_model) to transfer the backlinks to your
65    /// custom struct.
66    pub fn take_backlinks(&mut self) -> Vec<Backlink> {
67        std::mem::take(&mut self.backlinks)
68    }
69
70    /// Check if the row has a field with the given name.
71    pub fn has_field(&self, key: &str) -> bool {
72        self.values.contains_key(key)
73    }
74}
75
76impl Row<'_> {
77    /// Convert this row into an owned row.
78    ///
79    /// By default, when you [load a row](`crate::Table::get_row`), the names of
80    /// the columns are borrowed from the columns in the originating table. This
81    /// can be inconvenient for lifetime reasons, so this method allows you to
82    /// sever that connection, by cloning the column names.
83    ///
84    /// Note that this is only necessary if you want to interact with the row
85    /// manually. If you use [`realm_model!`](crate::realm_model), the column
86    /// names are no longer used.
87    pub fn into_owned(self) -> Row<'static> {
88        let values = self
89            .values
90            .into_iter()
91            .map(|(k, v)| (k.into_owned().into(), v))
92            .collect();
93
94        Row {
95            values,
96            backlinks: self.backlinks,
97        }
98    }
99}