use std::path::PathBuf;
pub trait OptionFrom<T> {
fn to_opt(self) -> Option<T>;
}
impl OptionFrom<String> for &str {
fn to_opt(self) -> Option<String> {
Some(self.to_string())
}
}
impl OptionFrom<String> for String {
fn to_opt(self) -> Option<String> {
Some(self)
}
}
impl OptionFrom<PathBuf> for &str {
fn to_opt(self) -> Option<PathBuf> {
Some(PathBuf::from(self))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn test_str_to_string_option() {
let result: Option<String> = "hello".to_opt();
assert_eq!(result, Some("hello".to_string()));
let result: Option<String> = "".to_opt();
assert_eq!(result, Some("".to_string()));
let result: Option<String> = "hello\nworld\t!".to_opt();
assert_eq!(result, Some("hello\nworld\t!".to_string()));
let result: Option<String> = "你好,世界!".to_opt();
assert_eq!(result, Some("你好,世界!".to_string()));
let long_str = "a".repeat(1000);
let result: Option<String> = long_str.as_str().to_opt();
assert_eq!(result, Some(long_str));
}
#[test]
fn test_string_to_string_option() {
let s = String::from("hello");
let result: Option<String> = s.to_opt();
assert_eq!(result, Some("hello".to_string()));
let s = String::new();
let result: Option<String> = s.to_opt();
assert_eq!(result, Some(String::new()));
let s = String::from("hello\nworld\t!");
let result: Option<String> = s.to_opt();
assert_eq!(result, Some("hello\nworld\t!".to_string()));
let s = String::from("你好,世界!");
let result: Option<String> = s.to_opt();
assert_eq!(result, Some("你好,世界!".to_string()));
let long_string = "a".repeat(1000);
let expected = long_string.clone();
let result: Option<String> = long_string.to_opt();
assert_eq!(result, Some(expected));
}
#[test]
fn test_str_to_pathbuf_option() {
let result: Option<PathBuf> = "/tmp/test".to_opt();
assert_eq!(result, Some(PathBuf::from("/tmp/test")));
let result: Option<PathBuf> = "./test/file.txt".to_opt();
assert_eq!(result, Some(PathBuf::from("./test/file.txt")));
let result: Option<PathBuf> = "C:\\Windows\\System32".to_opt();
assert_eq!(result, Some(PathBuf::from("C:\\Windows\\System32")));
let result: Option<PathBuf> = "".to_opt();
assert_eq!(result, Some(PathBuf::from("")));
let result: Option<PathBuf> = "/tmp/test with spaces/file.txt".to_opt();
assert_eq!(
result,
Some(PathBuf::from("/tmp/test with spaces/file.txt"))
);
let result: Option<PathBuf> = "/tmp/测试目录/文件.txt".to_opt();
assert_eq!(result, Some(PathBuf::from("/tmp/测试目录/文件.txt")));
}
#[test]
fn test_pathbuf_properties() {
let path_str = "/tmp/test.txt";
let result: Option<PathBuf> = path_str.to_opt();
assert!(result.is_some());
let pathbuf = result.unwrap();
assert_eq!(pathbuf, PathBuf::from(path_str));
assert_eq!(pathbuf.as_path(), Path::new(path_str));
assert_eq!(pathbuf.to_str(), Some(path_str));
assert!(pathbuf.is_absolute());
assert_eq!(pathbuf.file_name(), Some("test.txt".as_ref()));
assert_eq!(pathbuf.extension(), Some("txt".as_ref()));
}
#[test]
fn test_string_equality() {
let original = "test string";
let result1: Option<String> = original.to_opt();
let result2: Option<String> = original.to_string().to_opt();
assert_eq!(result1, result2);
assert_eq!(result1.unwrap(), result2.unwrap());
}
#[test]
fn test_type_consistency() {
let str_input = "test";
let string_input = String::from("test");
let str_result: Option<String> = str_input.to_opt();
let string_result: Option<String> = string_input.to_opt();
assert_eq!(str_result, string_result);
let path_result: Option<PathBuf> = str_input.to_opt();
assert!(path_result.is_some());
assert_eq!(path_result.unwrap(), PathBuf::from(str_input));
}
#[test]
fn test_edge_cases() {
let result: Option<String> = "a".to_opt();
assert_eq!(result, Some("a".to_string()));
let result: Option<String> = " \t\n\r".to_opt();
assert_eq!(result, Some(" \t\n\r".to_string()));
let result: Option<PathBuf> = ".".to_opt();
assert_eq!(result, Some(PathBuf::from(".")));
let result: Option<PathBuf> = "..".to_opt();
assert_eq!(result, Some(PathBuf::from("..")));
let result: Option<PathBuf> = "tmp///test".to_opt();
assert_eq!(result, Some(PathBuf::from("tmp///test")));
}
#[test]
fn test_memory_efficiency() {
let large_str = "x".repeat(10000);
let result1: Option<String> = large_str.as_str().to_opt();
assert_eq!(result1.unwrap(), large_str);
let result2: Option<String> = large_str.clone().to_opt();
assert_eq!(result2.unwrap(), large_str);
let result3: Option<PathBuf> = large_str.as_str().to_opt();
assert_eq!(result3.unwrap(), PathBuf::from(&large_str));
}
#[test]
fn test_trait_object_safety() {
fn use_trait<T, U: OptionFrom<T>>(input: U) -> Option<T> {
input.to_opt()
}
let result = use_trait::<String, _>("test");
assert_eq!(result, Some("test".to_string()));
let result = use_trait::<String, _>("test".to_string());
assert_eq!(result, Some("test".to_string()));
let result = use_trait::<PathBuf, _>("/tmp/test");
assert_eq!(result, Some(PathBuf::from("/tmp/test")));
}
}