1use rdll::*;
2use protect::stackp::*;
3use traits::*;
4use error::*;
5use std::ffi::CString;
6use rtype::*;
7
8pub trait RDim: RAttribute+RSize {
9 type Output;
10 fn dim(&self) -> Vec<usize> {
11 if !self.is_matrix() && !self.is_array() {
12 return Vec::new();
13 }
14 unsafe {
15 let res = Shield::new(Rf_getAttrib(self.s(), R_DimSymbol));
16 Vec::urnew(res.s())
17 }
18 }
19 fn set_dim(&mut self, x: &[usize]) -> RResult<()> {
20 if self.rsize() == 0{
21 return rraise("can not set 0 length vector");
22 }
23 let lens = x.iter().fold(1,|sum,i| sum * i );
24 if self.rsize() as usize != lens {
25 return rraise(format!("length is {} , can not set dimension {:?}",self.rsize(),lens));
26 }
27 unsafe {
28 Rf_setAttrib(self.s(), R_DimSymbol, x.uintor());
29 }
30 Ok(())
31 }
32 fn nrow(&self) -> usize {
33 if !self.is_matrix() {
34 return 0;
35 }
36 self.dim()[0]
37 }
38 fn ncol(&self) -> usize {
39 if !self.is_matrix() {
40 return 0;
41 }
42 self.dim()[1]
43 }
44 fn dimnamec(&self, side: usize) -> Vec<CString> {
45 if !self.is_matrix() && !self.is_array() {
46 return Vec::new();
47 }
48 unsafe {
49 let dims = self.dim();
50 if dims.len() < side {
51 return Vec::new();
52 }
53 let dimnames = Rf_getAttrib(self.s(), R_DimNamesSymbol);
54 if Rf_isNull(dimnames) == Rboolean::TRUE {
55 return Vec::new();
56 }
57 let res = VECTOR_ELT(dimnames, (side - 1) as R_xlen_t);
58 Vec::urnew(res.s())
59 }
60 }
61 fn dimname(&self, side: usize) -> RResult<Vec<String>> {
62 if !self.is_matrix() && !self.is_array() {
63 return Ok(Vec::new());
64 }
65 unsafe {
66 let dims = self.dim();
67 if dims.len() < side {
68 return Ok(Vec::new());
69 }
70 let dimnames = Rf_getAttrib(self.s(), R_DimNamesSymbol);
71 if Rf_isNull(dimnames) == Rboolean::TRUE {
72 return Ok(Vec::new());
73 }
74 let res = VECTOR_ELT(dimnames, (side - 1) as R_xlen_t);
75 Vec::rnew(res.s())
76 }
77 }
78 fn set_dimname(&mut self, side: usize, x: &[String]) -> RResult<()> {
80 unsafe {
81 if x.len() == 0 {
82 Rf_setAttrib(self.s(), R_DimNamesSymbol, R_NilValue);
83 Ok(())
84 } else {
85 let dims = self.dim();
86 if dims.len() < side || dims[side - 1] != x.len() {
87 return rraise(format!("dimension extent is {} the length of names is {}",
88 dims.len(),
89 x.len()));
90 }
91
92 let dimnames = Rf_getAttrib(self.s(), R_DimNamesSymbol);
93 if Rf_isNull(dimnames) == Rboolean::TRUE {
94 let new_dimnames = Shield::new(Rf_allocVector(VECSXP, dims.len() as R_xlen_t))
95 .s();
96 SET_VECTOR_ELT(new_dimnames, (side - 1) as R_xlen_t, try!(x.intor()));
97 Rf_setAttrib(self.s(), R_DimNamesSymbol, new_dimnames);
98 } else {
99 SET_VECTOR_ELT(dimnames, (side - 1) as R_xlen_t, try!(x.intor()));
100 }
101 Ok(())
102 }
103 }
104 }
105}