Skip to content

Commit 359bb20

Browse files
authored
Merge pull request #250 from posit-dev/bugfix/variable-dims
Fix lengths of tabular objects in variables pane
2 parents 7a2c4fa + 935cf13 commit 359bb20

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

crates/ark/src/data_explorer/r_data_explorer.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use amalthea::comm::data_explorer_comm::TableState;
2424
use amalthea::comm::event::CommManagerEvent;
2525
use amalthea::socket::comm::CommInitiator;
2626
use amalthea::socket::comm::CommSocket;
27+
use anyhow::anyhow;
2728
use anyhow::bail;
2829
use crossbeam::channel::Sender;
2930
use harp::exec::RFunction;
@@ -34,6 +35,7 @@ use harp::utils::r_is_object;
3435
use harp::utils::r_is_s4;
3536
use harp::utils::r_typeof;
3637
use harp::vector::formatted_vector::FormattedVector;
38+
use harp::TableInfo;
3739
use libr::*;
3840
use serde::Deserialize;
3941
use serde::Serialize;
@@ -195,6 +197,8 @@ impl RDataExplorer {
195197
let table = self.table.get().clone();
196198
let object = *table;
197199

200+
let info = table_info_or_bail(object)?;
201+
198202
let harp::TableInfo {
199203
kind,
200204
dims:
@@ -203,7 +207,7 @@ impl RDataExplorer {
203207
num_cols: total_num_columns,
204208
},
205209
col_names: column_names,
206-
} = harp::table_info(object)?;
210+
} = info;
207211

208212
let lower_bound = cmp::min(start_index, total_num_columns) as isize;
209213
let upper_bound = cmp::min(total_num_columns, start_index + num_columns) as isize;
@@ -258,7 +262,7 @@ impl RDataExplorer {
258262
num_cols: num_columns,
259263
},
260264
col_names: _,
261-
} = harp::table_info(object)?;
265+
} = table_info_or_bail(object)?;
262266

263267
let state = TableState {
264268
table_shape: TableShape {
@@ -280,14 +284,16 @@ impl RDataExplorer {
280284
let table = self.table.get().clone();
281285
let object = *table;
282286

287+
let info = table_info_or_bail(object)?;
288+
283289
let harp::TableInfo {
284290
dims:
285291
harp::TableDim {
286292
num_rows: total_num_rows,
287293
num_cols: total_num_cols,
288294
},
289295
..
290-
} = harp::table_info(object)?;
296+
} = info;
291297

292298
let lower_bound = cmp::min(row_start_index, total_num_rows) as isize;
293299
let upper_bound = cmp::min(row_start_index + num_rows, total_num_rows) as isize;
@@ -405,6 +411,10 @@ fn display_type(x: SEXP) -> ColumnSchemaTypeDisplay {
405411
}
406412
}
407413

414+
fn table_info_or_bail(x: SEXP) -> anyhow::Result<TableInfo> {
415+
harp::table_info(x).ok_or(anyhow!("Unsupported type for data viewer"))
416+
}
417+
408418
#[harp::register]
409419
pub unsafe extern "C" fn ps_view_data_frame(x: SEXP, title: SEXP) -> anyhow::Result<SEXP> {
410420
let x = RObject::new(x);

crates/ark/src/variables/variable.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -547,29 +547,25 @@ impl PositronVariable {
547547
}
548548

549549
fn variable_length(x: SEXP) -> usize {
550+
// Check for tabular data
551+
if let Some(info) = harp::table_info(x) {
552+
return info.dims.num_cols as usize;
553+
}
554+
555+
// Otherwise treat as vector
550556
let rtype = r_typeof(x);
551557
match rtype {
552-
LGLSXP | RAWSXP | INTSXP | REALSXP | CPLXSXP | STRSXP => unsafe {
558+
LGLSXP | RAWSXP | INTSXP | REALSXP | CPLXSXP | STRSXP | LISTSXP => unsafe {
553559
Rf_xlength(x) as usize
554560
},
555561
VECSXP => unsafe {
556-
if r_inherits(x, "POSIXlt") {
562+
// TODO: Support vctrs types like record vectors
563+
if r_inherits(x, "POSIXlt") && r_typeof(x) == VECSXP && r_length(x) > 0 {
557564
Rf_xlength(VECTOR_ELT(x, 0)) as usize
558-
} else if r_is_data_frame(x) {
559-
let dim = RFunction::new("base", "dim.data.frame")
560-
.add(x)
561-
.call()
562-
.unwrap();
563-
564-
INTEGER_ELT(*dim, 0) as usize
565565
} else {
566566
Rf_xlength(x) as usize
567567
}
568568
},
569-
LISTSXP => match pairlist_size(x) {
570-
Ok(n) => n as usize,
571-
Err(_) => 0,
572-
},
573569
_ => 0,
574570
}
575571
}

crates/harp/src/table.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use libr::*;
22

33
use crate::exec::RFunction;
44
use crate::exec::RFunctionExt;
5+
use crate::object::r_length;
56
use crate::utils::r_is_data_frame;
67
use crate::utils::r_is_matrix;
78
use crate::utils::r_typeof;
@@ -19,17 +20,19 @@ pub struct TableInfo {
1920
pub col_names: ColumnNames,
2021
}
2122

22-
pub fn table_info(x: SEXP) -> anyhow::Result<TableInfo> {
23+
// TODO: Might want to encode as types with methods so that we can make
24+
// assumptions about memory layout more safely. Also makes it possible
25+
// to compute properties more lazily.
26+
pub fn table_info(x: SEXP) -> Option<TableInfo> {
2327
if r_is_data_frame(x) {
24-
return df_info(x);
28+
return df_info(x).ok();
2529
}
2630

2731
if r_is_matrix(x) {
28-
return mat_info(x);
32+
return mat_info(x).ok();
2933
}
3034

31-
// TODO: better error message
32-
anyhow::bail!("Unsupported type for data viewer");
35+
None
3336
}
3437

3538
pub fn df_info(x: SEXP) -> anyhow::Result<TableInfo> {
@@ -81,6 +84,14 @@ pub fn mat_dim(x: SEXP) -> TableDim {
8184
unsafe {
8285
let dims = Rf_getAttrib(x, R_DimSymbol);
8386

87+
// Might want to return an error instead, or take a strongly typed input
88+
if r_typeof(dims) != INTSXP || r_length(dims) != 2 {
89+
return TableDim {
90+
num_rows: r_length(x) as i32,
91+
num_cols: 1,
92+
};
93+
}
94+
8495
TableDim {
8596
num_rows: INTEGER_ELT(dims, 0),
8697
num_cols: INTEGER_ELT(dims, 1),

0 commit comments

Comments
 (0)