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}