Advertisement
Guest User

Untitled

a guest
Jul 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.18 KB | None | 0 0
  1. use std::convert::TryFrom;
  2. mod openxml {
  3. use regex::Captures;
  4. use regex::Regex;
  5. use std::convert::TryFrom;
  6.  
  7. const CELL_PATTERN: &'static str =
  8. r"^(?P<cDollar>\$?)(?P<col>[A-Za-z]{1,3})(?P<rDollar>\$?)(?P<row>\d+)$";
  9.  
  10. const COL_MASK: u64 = 0x0000_FFFF_0000_0000;
  11. const ROW_MASK: u64 = 0x0000_0000_FFFF_FFFF;
  12.  
  13. pub const COL_MAX: u16 = 0x4000;
  14. pub const ROW_MAX: u32 = 0x0010_0000;
  15.  
  16. #[derive(Debug)]
  17. pub enum CellRangeError {
  18. ColError(u16),
  19. RowError(u32),
  20. }
  21.  
  22. #[derive(Debug)]
  23. pub struct CellAddress {
  24. val: u64,
  25. }
  26.  
  27. fn get_col_num(col: &str) -> u16 {
  28. let mut sum: u16 = 0;
  29. let col_upper = col.to_uppercase();
  30. let col_bytes = col_upper.as_bytes();
  31.  
  32. for c in col_bytes {
  33. sum *= 26;
  34. sum += *c as u16 - 65 + 1;
  35. }
  36. sum
  37. }
  38.  
  39. impl CellAddress {
  40. pub fn from_default() -> CellAddress {
  41. CellAddress {
  42. val: 0x0000_0001_0000_0001,
  43. }
  44. }
  45.  
  46. pub fn new(col: u16, row: u32) -> std::result::Result<CellAddress, CellRangeError> {
  47. if col < 1 || col > COL_MAX {
  48. return Err(CellRangeError::ColError(col));
  49. }
  50. if row < 1 || row > ROW_MAX {
  51. return Err(CellRangeError::RowError(row));
  52. }
  53. Ok(CellAddress {
  54. val: (u64::from(col) << 32) | u64::from(row),
  55. })
  56. }
  57.  
  58. pub fn get_row(&self) -> u32 {
  59. (self.val & ROW_MASK) as u32
  60. }
  61.  
  62. pub fn get_col(&self) -> u16 {
  63. ((self.val & COL_MASK) >> 32) as u16
  64. }
  65.  
  66. pub fn get_col_str(&self) -> String {
  67. let mut dividend = ((self.val & COL_MASK) >> 32) as i32;
  68. let mut modulo: i32;
  69. let mut col_name = String::with_capacity(3);
  70. let mut tmp_char: Option<char>;
  71.  
  72. while dividend > 0 {
  73. modulo = (dividend - 1) % 26;
  74. tmp_char = std::char::from_u32(modulo as u32 + 65);
  75.  
  76. col_name.insert(0, tmp_char.expect("Could not convert u32 value to char"));
  77. dividend = (dividend - modulo) / 26;
  78. }
  79. col_name
  80. }
  81. }
  82.  
  83. impl TryFrom<String> for CellAddress {
  84. type Error = &'static str;
  85.  
  86. fn try_from(value: String) -> Result<CellAddress, <CellAddress as TryFrom<String>>::Error> {
  87. if value.is_empty() {
  88. return Err("value cannot be empty");
  89. }
  90. let re = Regex::new(CELL_PATTERN).unwrap();
  91. let caps = re.captures(&value);
  92.  
  93. if caps.is_none() {
  94. return Err("value failed validation");
  95. }
  96. let u_caps = caps.unwrap();
  97. let col_name = u_caps.name("col").unwrap().as_str();
  98. let row_num = u_caps.name("row").unwrap().as_str();
  99.  
  100. let row: u32 = row_num.parse::<u32>().unwrap();
  101. let col: u16 = get_col_num(col_name);
  102.  
  103. if col < 1 || col > COL_MAX {
  104. return Err("Column out of range");
  105. }
  106. if row < 1 || row > ROW_MAX {
  107. return Err("Row out of range");
  108. }
  109. Ok(CellAddress::new(col, row).unwrap())
  110. }
  111. }
  112. impl TryFrom<&str> for CellAddress {
  113. type Error = &'static str;
  114.  
  115. fn try_from(value: &str) -> Result<CellAddress, <CellAddress as TryFrom<&str>>::Error> {
  116. if value.is_empty() {
  117. return Err("value cannot be empty");
  118. }
  119. let re = Regex::new(CELL_PATTERN).unwrap();
  120. let caps = re.captures(value);
  121.  
  122. if caps.is_none() {
  123. return Err("value failed validation");
  124. }
  125. let u_caps = caps.unwrap();
  126. let col_name = u_caps.name("col").unwrap().as_str();
  127. let row_num = u_caps.name("row").unwrap().as_str();
  128.  
  129. let row: u32 = row_num.parse::<u32>().unwrap();
  130. let col: u16 = get_col_num(col_name);
  131.  
  132. if col < 1 || col > COL_MAX {
  133. return Err("Column out of range");
  134. }
  135. if row < 1 || row > ROW_MAX {
  136. return Err("Row out of range");
  137. }
  138. Ok(CellAddress::new(col, row).unwrap())
  139. }
  140. }
  141.  
  142. impl std::fmt::Display for CellAddress {
  143. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  144. write!(
  145. f,
  146. "{}{}",
  147. self.get_col_str(),
  148. (self.val & ROW_MASK).to_string()
  149. )
  150. }
  151. }
  152. }
  153.  
  154. fn main() {
  155. let sample_address = openxml::CellAddress::new(28, 1).unwrap();
  156. println!("Cell Column Name: {}", sample_address.get_col_str());
  157. println!("Cell Column Num: {}", sample_address.get_col().to_string());
  158. println!("Cell Row Num: {}", sample_address.get_row().to_string());
  159. println!("Cell Address: {}", sample_address.to_string());
  160.  
  161. let sample2 = openxml::CellAddress::try_from("A11");
  162. if sample2.is_ok() {
  163. let addr = sample2.unwrap();
  164. println!("Sample2 parse successful");
  165. println!("Sample2 Column Name: {}", addr.get_col_str());
  166. println!("Sample2 Row: {}", addr.get_row().to_string());
  167. }
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement