lib_efo/entity/implementations/
from_impl.rs1use crate::{
4 entity::{EffectBounds, EntityDuration, EntityIdentifier},
5 error::EpochError,
6};
7
8use std::{ops::Range, str::FromStr};
9
10impl FromStr for EntityDuration {
13 type Err = EpochError;
14
15 fn from_str(s: &str) -> Result<Self, Self::Err> {
16 let raw = s.trim().to_ascii_lowercase();
18
19 match raw.as_str() {
20 "permanent" | "perm" => Ok(EntityDuration::Permanent),
21 "done" => Ok(EntityDuration::Done),
22
23 _ if raw.starts_with("duration:") => {
25 let num_part = &raw["duration:".len()..];
26 match num_part.parse::<usize>() {
27 Ok(v) => Ok(EntityDuration::Duration(v)),
28 Err(_) => Err(EpochError::ParsingDuration(
29 "Invalid duration value",
30 num_part.to_string(),
31 )),
32 }
33 }
34
35 _ if raw.chars().all(|c| c.is_ascii_digit()) => match raw.parse::<usize>() {
37 Ok(v) => Ok(EntityDuration::Duration(v)),
38 Err(_) => Err(EpochError::ParsingDuration("Could not parse number", raw)),
39 },
40
41 _ => Err(EpochError::ParsingDuration("Invalid EntityDuration", raw)),
43 }
44 }
45}
46
47impl FromStr for EffectBounds {
48 type Err = EpochError;
49
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
58 let raw = s.trim();
60
61 fn parse_pair(raw: &str, delim: char) -> Result<(usize, usize), EpochError> {
63 let parts: Vec<&str> = raw.split(delim).collect();
64 if parts.len() != 2 {
65 return Err(EpochError::ParsingBounds(
66 "Invalid EffectBounds format",
67 raw.to_string(),
68 ));
69 }
70 let min = parts[0].trim().parse::<usize>().map_err(|_| {
71 EpochError::ParsingBounds("Could not parse number", raw.to_string())
72 })?;
73 let max = parts[1].trim().parse::<usize>().map_err(|_| {
74 EpochError::ParsingBounds("Could not parse number", raw.to_string())
75 })?;
76 Ok((min, max))
77 }
78
79 if raw.find(':').is_some() {
81 let (min, max) = parse_pair(raw, ':')?;
82 return Ok(EffectBounds { min, max });
83 }
84
85 if raw.find('-').is_some() {
87 let (min, max) = parse_pair(raw, '-')?;
88 return Ok(EffectBounds { min, max });
89 }
90
91 Err(EpochError::ParsingBounds(
93 "Invalid EffectBounds",
94 raw.to_string(),
95 ))
96 }
97}
98
99impl FromStr for EntityIdentifier {
100 type Err = EpochError;
101
102 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 match s.strip_prefix('@') {
109 Some(uuid) if !uuid.is_empty() => Ok(EntityIdentifier::Id(uuid.to_string())),
110 Some(_) => Err(EpochError::EmptyIdentifier),
111 None => Ok(EntityIdentifier::Name(s.to_string())),
112 }
113 }
114}
115
116impl From<(usize, usize)> for EffectBounds {
117 fn from(value: (usize, usize)) -> Self {
118 Self {
119 min: value.0,
120 max: value.1,
121 }
122 }
123}
124
125impl From<Range<usize>> for EffectBounds {
126 fn from(value: Range<usize>) -> Self {
127 Self {
128 min: value.start,
129 max: value.end,
130 }
131 }
132}