Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::convert::TryFrom;
- mod openxml {
- use regex::Captures;
- use regex::Regex;
- use std::convert::TryFrom;
- const CELL_PATTERN: &'static str =
- r"^(?P<cDollar>\$?)(?P<col>[A-Za-z]{1,3})(?P<rDollar>\$?)(?P<row>\d+)$";
- const COL_MASK: u64 = 0x0000_FFFF_0000_0000;
- const ROW_MASK: u64 = 0x0000_0000_FFFF_FFFF;
- pub const COL_MAX: u16 = 0x4000;
- pub const ROW_MAX: u32 = 0x0010_0000;
- #[derive(Debug)]
- pub enum CellRangeError {
- ColError(u16),
- RowError(u32),
- }
- #[derive(Debug)]
- pub struct CellAddress {
- val: u64,
- }
- fn get_col_num(col: &str) -> u16 {
- let mut sum: u16 = 0;
- let col_upper = col.to_uppercase();
- let col_bytes = col_upper.as_bytes();
- for c in col_bytes {
- sum *= 26;
- sum += *c as u16 - 65 + 1;
- }
- sum
- }
- impl CellAddress {
- pub fn from_default() -> CellAddress {
- CellAddress {
- val: 0x0000_0001_0000_0001,
- }
- }
- pub fn new(col: u16, row: u32) -> std::result::Result<CellAddress, CellRangeError> {
- if col < 1 || col > COL_MAX {
- return Err(CellRangeError::ColError(col));
- }
- if row < 1 || row > ROW_MAX {
- return Err(CellRangeError::RowError(row));
- }
- Ok(CellAddress {
- val: (u64::from(col) << 32) | u64::from(row),
- })
- }
- pub fn get_row(&self) -> u32 {
- (self.val & ROW_MASK) as u32
- }
- pub fn get_col(&self) -> u16 {
- ((self.val & COL_MASK) >> 32) as u16
- }
- pub fn get_col_str(&self) -> String {
- let mut dividend = ((self.val & COL_MASK) >> 32) as i32;
- let mut modulo: i32;
- let mut col_name = String::with_capacity(3);
- let mut tmp_char: Option<char>;
- while dividend > 0 {
- modulo = (dividend - 1) % 26;
- tmp_char = std::char::from_u32(modulo as u32 + 65);
- col_name.insert(0, tmp_char.expect("Could not convert u32 value to char"));
- dividend = (dividend - modulo) / 26;
- }
- col_name
- }
- }
- impl TryFrom<String> for CellAddress {
- type Error = &'static str;
- fn try_from(value: String) -> Result<CellAddress, <CellAddress as TryFrom<String>>::Error> {
- if value.is_empty() {
- return Err("value cannot be empty");
- }
- let re = Regex::new(CELL_PATTERN).unwrap();
- let caps = re.captures(&value);
- if caps.is_none() {
- return Err("value failed validation");
- }
- let u_caps = caps.unwrap();
- let col_name = u_caps.name("col").unwrap().as_str();
- let row_num = u_caps.name("row").unwrap().as_str();
- let row: u32 = row_num.parse::<u32>().unwrap();
- let col: u16 = get_col_num(col_name);
- if col < 1 || col > COL_MAX {
- return Err("Column out of range");
- }
- if row < 1 || row > ROW_MAX {
- return Err("Row out of range");
- }
- Ok(CellAddress::new(col, row).unwrap())
- }
- }
- impl TryFrom<&str> for CellAddress {
- type Error = &'static str;
- fn try_from(value: &str) -> Result<CellAddress, <CellAddress as TryFrom<&str>>::Error> {
- if value.is_empty() {
- return Err("value cannot be empty");
- }
- let re = Regex::new(CELL_PATTERN).unwrap();
- let caps = re.captures(value);
- if caps.is_none() {
- return Err("value failed validation");
- }
- let u_caps = caps.unwrap();
- let col_name = u_caps.name("col").unwrap().as_str();
- let row_num = u_caps.name("row").unwrap().as_str();
- let row: u32 = row_num.parse::<u32>().unwrap();
- let col: u16 = get_col_num(col_name);
- if col < 1 || col > COL_MAX {
- return Err("Column out of range");
- }
- if row < 1 || row > ROW_MAX {
- return Err("Row out of range");
- }
- Ok(CellAddress::new(col, row).unwrap())
- }
- }
- impl std::fmt::Display for CellAddress {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(
- f,
- "{}{}",
- self.get_col_str(),
- (self.val & ROW_MASK).to_string()
- )
- }
- }
- }
- fn main() {
- let sample_address = openxml::CellAddress::new(28, 1).unwrap();
- println!("Cell Column Name: {}", sample_address.get_col_str());
- println!("Cell Column Num: {}", sample_address.get_col().to_string());
- println!("Cell Row Num: {}", sample_address.get_row().to_string());
- println!("Cell Address: {}", sample_address.to_string());
- let sample2 = openxml::CellAddress::try_from("A11");
- if sample2.is_ok() {
- let addr = sample2.unwrap();
- println!("Sample2 parse successful");
- println!("Sample2 Column Name: {}", addr.get_col_str());
- println!("Sample2 Row: {}", addr.get_row().to_string());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement