lcc_user_validated 0.1.0

This crate is mini-version of User Input Validation.
Documentation
use std::io;
use regex::Regex;

/// 驗證身分證字號:
/// 1. 總長度必須為 10
/// 2. 第 1 碼為英文字母
/// 3. 第 2~10 碼為數字

pub struct TaiwanIdValidation(String);

impl TaiwanIdValidation {
    pub fn validate_id(id: &str) -> Result<Self, String>{
    // 移除前後空白與換行符號
    let id = id.trim();

    // 字串長度驗證
    if id.len() != 10 {
        return Err("身分證字號長度必須為 10 碼".to_string());
    }

    // UTF-8字串轉換成位元組
    let mut chars = id.chars();

    // 第1碼驗證,使用迭代器與next。
    match chars.next(){
        Some(c) if c.is_ascii_alphabetic() => {} //配對守護
        _ => return Err("身分證字號第1碼必須是英文字母".to_string()),
    }
    
    // 第9至第10碼驗證,接續迭代器。
    if !chars.all(|c: char| c.is_ascii_digit()) {
        return Err("身分證字號第 2~10 碼必須為數字".to_string());
    }

    Ok(TaiwanIdValidation(id.to_string()))
    }

    // 在外部空間讀取內部的字串內容
    pub fn id_value(&self) -> &str {
        &self.0
    }
}


/// 驗證手機號碼:
/// 1. 必須以 09 開頭
/// 2. 將"-"連字號分隔的號碼也納入
/// 3. 告知正確格式

pub struct PhoneValidation(String);

impl PhoneValidation{
    pub fn validate_phone(id: &str) -> Result<Self, String>{
        let id = id.trim();

        // 編譯 Regex
        let re = Regex::new(r"^09\d{2}-?\d{3}-?\d{3}$").unwrap();
        
        // 字串格式驗證
        if re.is_match(id) {
            Ok(PhoneValidation(id.to_string())) 
        } else {
            Err("手機號碼格式錯誤,請輸入 09xxxxxxxx 或 09xx-xxx-xxx".to_string())
        }
    }

    // 在外部空間讀取內部的字串內容
    pub fn phone_value(&self) -> &str {
        &self.0
    }

}

/// 驗證電子信箱:
/// 1. 必須包括 "@" 符號
/// 2. 將大小寫英文與數字都納入
/// 3. 告知 "." 符號
pub struct MailValidation(String);

impl MailValidation{
    pub fn validate_mail(id: &str) -> Result<Self, String>{
        let id = id.trim();

        // 編譯 Regex
        let re = Regex::new(r"^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.com$").unwrap();
        
        // 字串格式驗證
        if re.is_match(id) {
            Ok(MailValidation(id.to_string())) 
        } else {
            Err("信箱格式錯誤,請輸入 xxx@example.com".to_string())
        }
    }

    // 在外部空間讀取內部的字串內容
    pub fn mail_value(&self) -> &str {
        &self.0
    }

}

fn main() {
    // 身分證字號
    println!("請輸入身分證字號10碼 (1 碼字母 + 9 碼數字):");

    let mut id = String::new();

    io::stdin()
    .read_line(&mut id)
    .expect("讀取身分證失敗");

    // 驗證身分證
    match TaiwanIdValidation::validate_id(&id){
        Ok(valid) => {
            println!("驗證成功,你輸入的身分證字號是:{}", valid.id_value());
        }
        Err(e) => {
            println!("驗證失敗:{}", e)
        }

    }

    // 手機號碼
    println!("請輸入手機號碼 (如: 0912345678, 0912-345-678):");

    let mut id= String::new();
    
    io::stdin()
    .read_line(&mut id)
    .expect("讀取手機號碼失敗");

    match PhoneValidation::validate_phone(&id){
        Ok(valid) => {
            println!("驗證成功,你輸入的手機號碼是:{}", valid.phone_value());
        }
        Err(e) => {
            println!("驗證失敗:{}", e)
        }

    }

    // 電子信箱
    println!("請輸入電子信箱 (如: XXX@example.com):");

    let mut id= String::new();
    
    io::stdin()
    .read_line(&mut id)
    .expect("讀取電子信箱失敗");

    match MailValidation::validate_mail(&id){
        Ok(valid) => {
            println!("驗證成功,你輸入的電子信箱是:{}", valid.mail_value());
        }
        Err(e) => {
            println!("驗證失敗:{}", e)
        }

    }
}