142 lines
3.8 KiB
Rust
142 lines
3.8 KiB
Rust
//! RegexBox 🔍 - 正規表現
|
||
// Nyashの箱システムによる正規表現処理を提供します。
|
||
// 参考: 既存Boxの設計思想
|
||
|
||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||
use crate::boxes::array::ArrayBox;
|
||
use regex::Regex;
|
||
use std::any::Any;
|
||
use std::fmt::Debug;
|
||
use std::sync::Arc;
|
||
|
||
#[derive(Debug, Clone)]
|
||
pub struct RegexBox {
|
||
regex: Arc<Regex>,
|
||
pattern: Arc<String>,
|
||
base: BoxBase,
|
||
}
|
||
|
||
impl RegexBox {
|
||
pub fn new(pattern: &str) -> Result<Self, regex::Error> {
|
||
let regex = Regex::new(pattern)?;
|
||
Ok(RegexBox {
|
||
regex: Arc::new(regex),
|
||
pattern: Arc::new(pattern.to_string()),
|
||
base: BoxBase::new(),
|
||
})
|
||
}
|
||
pub fn is_match(&self, text: &str) -> bool {
|
||
self.regex.is_match(text)
|
||
}
|
||
pub fn pattern(&self) -> &str {
|
||
&self.pattern
|
||
}
|
||
|
||
/// パターンマッチテスト
|
||
pub fn test(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||
let text_str = text.to_string_box().value;
|
||
Box::new(BoolBox::new(self.is_match(&text_str)))
|
||
}
|
||
|
||
/// マッチ箇所を検索
|
||
pub fn find(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||
let text_str = text.to_string_box().value;
|
||
if let Some(mat) = self.regex.find(&text_str) {
|
||
Box::new(StringBox::new(mat.as_str()))
|
||
} else {
|
||
Box::new(crate::boxes::null_box::NullBox::new())
|
||
}
|
||
}
|
||
|
||
/// すべてのマッチを検索
|
||
pub fn find_all(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||
let text_str = text.to_string_box().value;
|
||
let array = ArrayBox::new();
|
||
|
||
for mat in self.regex.find_iter(&text_str) {
|
||
let _ = array.push(Box::new(StringBox::new(mat.as_str())));
|
||
}
|
||
|
||
Box::new(array)
|
||
}
|
||
|
||
/// 文字列置換
|
||
pub fn replace(
|
||
&self,
|
||
text: Box<dyn NyashBox>,
|
||
replacement: Box<dyn NyashBox>,
|
||
) -> Box<dyn NyashBox> {
|
||
let text_str = text.to_string_box().value;
|
||
let replacement_str = replacement.to_string_box().value;
|
||
let result = self.regex.replace_all(&text_str, replacement_str.as_str());
|
||
Box::new(StringBox::new(&result.to_string()))
|
||
}
|
||
|
||
/// 文字列分割
|
||
pub fn split(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||
let text_str = text.to_string_box().value;
|
||
let array = ArrayBox::new();
|
||
|
||
for part in self.regex.split(&text_str) {
|
||
let _ = array.push(Box::new(StringBox::new(part)));
|
||
}
|
||
|
||
Box::new(array)
|
||
}
|
||
}
|
||
|
||
impl NyashBox for RegexBox {
|
||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||
Box::new(self.clone())
|
||
}
|
||
|
||
/// 仮実装: clone_boxと同じ(後で修正)
|
||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||
self.clone_box()
|
||
}
|
||
|
||
fn to_string_box(&self) -> StringBox {
|
||
StringBox::new(format!("RegexBox({})", self.pattern.as_str()))
|
||
}
|
||
|
||
fn type_name(&self) -> &'static str {
|
||
"RegexBox"
|
||
}
|
||
|
||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||
if let Some(other_regex) = other.as_any().downcast_ref::<RegexBox>() {
|
||
BoolBox::new(self.pattern.as_str() == other_regex.pattern.as_str())
|
||
} else {
|
||
BoolBox::new(false)
|
||
}
|
||
}
|
||
}
|
||
|
||
impl BoxCore for RegexBox {
|
||
fn box_id(&self) -> u64 {
|
||
self.base.id
|
||
}
|
||
|
||
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
||
self.base.parent_type_id
|
||
}
|
||
|
||
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
write!(f, "RegexBox({})", self.pattern.as_str())
|
||
}
|
||
|
||
fn as_any(&self) -> &dyn Any {
|
||
self
|
||
}
|
||
|
||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||
self
|
||
}
|
||
}
|
||
|
||
impl std::fmt::Display for RegexBox {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
self.fmt_box(f)
|
||
}
|
||
}
|