diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:16:23 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:16:23 +0800 |
| commit | 748c8a3353df887ee4b01e0e1327aa95c1c7225a (patch) | |
| tree | ab84ee3fd6af53e8b03e73f9bdc5177f10606e4a /systems/sheet/src/mapping/parse.rs | |
| parent | 53141f612ab43136b4b1db7406ac71bb97284460 (diff) | |
Add remote flag to IndexSource and parsing support
Diffstat (limited to 'systems/sheet/src/mapping/parse.rs')
| -rw-r--r-- | systems/sheet/src/mapping/parse.rs | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/systems/sheet/src/mapping/parse.rs b/systems/sheet/src/mapping/parse.rs new file mode 100644 index 0000000..e203c96 --- /dev/null +++ b/systems/sheet/src/mapping/parse.rs @@ -0,0 +1,189 @@ +use just_fmt::fmt_path::fmt_path_str; + +use crate::{ + index_source::IndexSource, + mapping::{LocalMapping, LocalMappingForward, error::ParseMappingError}, +}; + +impl TryFrom<&str> for LocalMapping { + type Error = ParseMappingError; + + fn try_from(s: &str) -> Result<Self, Self::Error> { + // Remove surrounding quotes if present + let s = s.trim_matches('"'); + + // Helper function to remove quotes from a string + fn remove_quotes(s: &str) -> String { + // Simply remove all quotes from the string + s.replace('"', "").trim().to_string() + } + + // Helper function to split by operator, handling both spaced and non-spaced versions + fn split_by_operator<'a>(s: &'a str, operator: &'a str) -> Vec<&'a str> { + let mut result = Vec::new(); + let mut start = 0; + + // Find all occurrences of the operator + let mut search_from = 0; + while let Some(pos) = s[search_from..].find(operator) { + let actual_pos = search_from + pos; + result.push(&s[start..actual_pos]); + start = actual_pos + operator.len(); + search_from = start; + } + + if start < s.len() { + result.push(&s[start..]); + } + + result + } + + // Helper function to find operator position + fn find_operator<'a>(s: &'a str, operator: &'a str) -> Option<usize> { + s.find(operator) + } + + // Try to parse "path" => "source" == "version" pattern + if let Some(arrow_pos) = find_operator(s, "=>") { + let after_arrow = &s[arrow_pos + 2..]; + if let Some(equal_pos) = find_operator(after_arrow, "==") { + // Format: "path" => "source" == "version" + let path = remove_quotes(s[..arrow_pos].trim()); + let middle_part = after_arrow[..equal_pos].trim(); + let version_part = after_arrow[equal_pos + 2..].trim(); + + let middle = remove_quotes(middle_part); + let version_part_str = remove_quotes(version_part); + + let val = fmt_path_str(path) + .map_err(|_| ParseMappingError::InvalidMapping)? + .split('/') + .map(|s| s.to_string()) + .collect(); + + let source = IndexSource::try_from(middle.as_str()) + .map_err(|_| ParseMappingError::InvalidMapping)?; + + let version = version_part_str + .parse::<u16>() + .map_err(|_| ParseMappingError::InvalidMapping)?; + + return Ok(LocalMapping { + val, + source, + forward: LocalMappingForward::Version { version }, + }); + } + } + + // Split by "=>" to parse the format + let parts = split_by_operator(s, "=>"); + + match parts.len() { + 1 => { + // Check for "==" operator + if let Some(equal_pos) = find_operator(s, "==") { + // Format: "path" == "source" (when mapped_version equals version) + let path_raw = s[..equal_pos].trim(); + let source_part_raw = s[equal_pos + 2..].trim(); + let path = remove_quotes(path_raw); + let source_str = remove_quotes(source_part_raw); + + let val = fmt_path_str(path) + .map_err(|_| ParseMappingError::InvalidMapping)? + .split('/') + .map(|s| s.to_string()) + .collect(); + + let source = IndexSource::try_from(source_str.as_str()) + .map_err(|_| ParseMappingError::InvalidMapping)?; + + let version = source.version(); + + Ok(LocalMapping { + val, + source, + forward: LocalMappingForward::Version { version }, + }) + } else { + Err(ParseMappingError::InvalidMapping) + } + } + 2 => { + // Check if the second part contains "==" + if let Some(equal_pos) = find_operator(parts[1], "==") { + // Format: "path" => "source" == "version" + let path = remove_quotes(parts[0].trim()); + let middle_part = parts[1][..equal_pos].trim(); + let version_part = parts[1][equal_pos + 2..].trim(); + + let middle = remove_quotes(middle_part); + let version_part_str = remove_quotes(version_part); + + let val = fmt_path_str(path) + .map_err(|_| ParseMappingError::InvalidMapping)? + .split('/') + .map(|s| s.to_string()) + .collect(); + + let source = IndexSource::try_from(middle.as_str()) + .map_err(|_| ParseMappingError::InvalidMapping)?; + + let version = version_part_str + .parse::<u16>() + .map_err(|_| ParseMappingError::InvalidMapping)?; + + return Ok(LocalMapping { + val, + source, + forward: LocalMappingForward::Version { version }, + }); + } + + // Format: "path" => "source" + let path = remove_quotes(parts[0].trim()); + let source_str = remove_quotes(parts[1].trim()); + + let val = fmt_path_str(path) + .map_err(|_| ParseMappingError::InvalidMapping)? + .split('/') + .map(|s| s.to_string()) + .collect(); + + let source = IndexSource::try_from(source_str.as_str()) + .map_err(|_| ParseMappingError::InvalidMapping)?; + + Ok(LocalMapping { + val, + source, + forward: LocalMappingForward::Latest, + }) + } + 3 => { + // Format: "path" => "source" => "sheet_name" + let path = remove_quotes(parts[0].trim()); + let source_str = remove_quotes(parts[1].trim()); + let sheet_name = remove_quotes(parts[2].trim()); + + let val = fmt_path_str(path) + .map_err(|_| ParseMappingError::InvalidMapping)? + .split('/') + .map(|s| s.to_string()) + .collect(); + + let source = IndexSource::try_from(source_str.as_str()) + .map_err(|_| ParseMappingError::InvalidMapping)?; + + Ok(LocalMapping { + val, + source, + forward: LocalMappingForward::Ref { + sheet_name: sheet_name, + }, + }) + } + _ => Err(ParseMappingError::InvalidMapping), + } + } +} |
