icydb_core/db/response/
rows.rs1use crate::value::{OutputValue, render_output_value_text};
7
8use serde::Deserialize;
9
10#[derive(Clone, Debug, Deserialize, Eq, PartialEq, serde::Serialize)]
12#[cfg_attr(not(target_family = "wasm"), derive(ic_wire::Wire))]
13pub struct RowProjectionOutput {
14 pub entity: String,
16 pub columns: Vec<String>,
18 pub rows: Vec<Vec<OutputValue>>,
20 pub row_count: u32,
22}
23
24impl RowProjectionOutput {
25 #[must_use]
27 pub const fn len(&self) -> usize {
28 self.rows.len()
29 }
30
31 #[must_use]
33 pub const fn is_empty(&self) -> bool {
34 self.rows.is_empty()
35 }
36
37 #[must_use]
39 pub fn rendered_rows(&self) -> Vec<Vec<String>> {
40 self.rows
41 .iter()
42 .map(|row| row.iter().map(render_output_value_text).collect())
43 .collect()
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[derive(serde::Serialize)]
52 struct FrozenRowProjectionOutputWire {
53 entity: String,
54 columns: Vec<String>,
55 rows: Vec<Vec<OutputValue>>,
56 row_count: u32,
57 }
58
59 #[test]
60 fn row_projection_output_preserves_the_frozen_wire_record_shape() {
61 let current = RowProjectionOutput {
62 entity: "example".to_string(),
63 columns: vec!["id".to_string()],
64 rows: Vec::new(),
65 row_count: 0,
66 };
67 let frozen = FrozenRowProjectionOutputWire {
68 entity: current.entity.clone(),
69 columns: current.columns.clone(),
70 rows: current.rows.clone(),
71 row_count: current.row_count,
72 };
73
74 assert_eq!(current.len(), 0);
75 assert!(current.is_empty());
76
77 assert_eq!(
78 icydb_schema::wire::encode_one(¤t).expect("current row projection should encode"),
79 icydb_schema::wire::encode_one(&frozen).expect("frozen row projection should encode"),
80 );
81 }
82}