Skip to content

Commit

Permalink
Add Term::as_str()
Browse files Browse the repository at this point in the history
  • Loading branch information
turboladen committed Sep 27, 2023
1 parent 5d67215 commit a982733
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 44 deletions.
1 change: 1 addition & 0 deletions api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
crates to create new types based on `Measurement`, `Unit`, etc. from this crate.
- New feature flag: `v2`. Adds the `v2` module, with revamped versions of traits--both fixing some
ergonomics and enabling easier downstream wrapping.
- Added `Term::as_str()` to allow getting the representing string as a `&str` or `String`.

### Changed

Expand Down
72 changes: 72 additions & 0 deletions api/src/parser/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ mod ucum_unit;
#[cfg(feature = "v2")]
mod v2;

use std::borrow::Cow;

use crate::parser::{Atom, Prefix};

/// A Term makes up an Atom (at its core) along with any Atom modifiers
Expand Down Expand Up @@ -119,6 +121,76 @@ impl Term {
pub fn factor_as_u32(&self) -> u32 {
self.factor.unwrap_or(1)
}

/// Depending on the `Term`, its string representation could be anywhere from a `&'static str`
/// to a combination of all of its fields as a `String`. For those former cases, we want to
/// allow borrowing the `&'static str` to save on allocations.
///
pub fn as_str<'a>(&'a self) -> Cow<'a, str> {
use crate::UcumSymbol;

if self.is_unity() && self.annotation.is_none() {
return Cow::Borrowed("1");
};

match (
self.factor,
self.prefix,
self.atom,
self.exponent,
self.annotation.as_deref(),
) {
(None, None, None, None, None) => Cow::Borrowed(""),
(None, None, None, None, Some(ann)) => Cow::Owned(format!("{{{ann}}}")),
(None, None, Some(atom), None, None) => Cow::Borrowed(atom.primary_code()),
(None, None, Some(atom), None, Some(ann)) => Cow::Owned(format!("{atom}{{{ann}}}")),
(None, None, Some(atom), Some(exp), None) if exp == 1 => {
Cow::Borrowed(atom.primary_code())
}
(None, None, Some(atom), Some(exp), None) => Cow::Owned(format!("{atom}{exp}")),
(None, None, Some(atom), Some(exp), Some(ann)) => {
Cow::Owned(format!("{atom}{exp}{{{ann}}}"))
}
(None, Some(prefix), Some(atom), None, None) => Cow::Owned(format!("{prefix}{atom}")),
(None, Some(prefix), Some(atom), None, Some(ann)) => {
Cow::Owned(format!("{prefix}{atom}{{{ann}}}"))
}
(None, Some(prefix), Some(atom), Some(exp), None) => {
Cow::Owned(format!("{prefix}{atom}{exp}"))
}
(None, Some(prefix), Some(atom), Some(exp), Some(ann)) => {
Cow::Owned(format!("{prefix}{atom}{exp}{{{ann}}}"))
}
(Some(factor), None, None, None, None) => Cow::Owned(factor.to_string()),
(Some(factor), None, None, None, Some(ann)) if factor == 1 => {
Cow::Owned(format!("{{{ann}}}"))
}
(Some(factor), None, None, None, Some(ann)) => Cow::Owned(format!("{factor}{{{ann}}}")),
(Some(factor), None, Some(atom), None, None) => Cow::Owned(format!("{factor}{atom}")),
(Some(factor), None, Some(atom), None, Some(ann)) => {
Cow::Owned(format!("{factor}{atom}{{{ann}}}"))
}
(Some(factor), None, Some(atom), Some(exp), None) => {
Cow::Owned(format!("{factor}{atom}{exp}"))
}
(Some(factor), None, Some(atom), Some(exp), Some(ann)) => {
Cow::Owned(format!("{factor}{atom}{exp}{{{ann}}}"))
}
(Some(factor), Some(prefix), Some(atom), None, None) => {
Cow::Owned(format!("{factor}{prefix}{atom}"))
}
(Some(factor), Some(prefix), Some(atom), None, Some(ann)) => {
Cow::Owned(format!("{factor}{prefix}{atom}{{{ann}}}"))
}
(Some(factor), Some(prefix), Some(atom), Some(exp), None) => {
Cow::Owned(format!("{factor}{prefix}{atom}{exp}"))
}
(Some(factor), Some(prefix), Some(atom), Some(exp), Some(ann)) => {
Cow::Owned(format!("{factor}{prefix}{atom}{exp}{{{ann}}}"))
}
_ => panic!("Invalid Term: {self:?}"),
}
}
}

#[cfg(test)]
Expand Down
45 changes: 1 addition & 44 deletions api/src/parser/term/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,7 @@ use std::fmt;

impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", extract_term_string(self))
}
}

fn extract_term_string(term: &Term) -> String {
if term.is_unity() && term.annotation.is_none() {
return String::from("1");
};

let mut term_string = String::new();
extract_term_string_factor(&mut term_string, term.factor);
extract_term_string_atom(&mut term_string, term);

if let Some(ref annotation) = term.annotation {
term_string.push_str(&format!("{{{annotation}}}"));
}

term_string
}

fn extract_term_string_factor(term_string: &mut String, term_factor: Option<u32>) {
if let Some(factor) = term_factor {
if factor != 1 {
term_string.push_str(&factor.to_string());
}
}
}

fn extract_term_string_atom(term_string: &mut String, term: &Term) {
if let Some(atom) = term.atom {
if let Some(prefix) = term.prefix {
term_string.push_str(&prefix.to_string());
}

match term.exponent {
Some(exponent) => {
if exponent == 1 {
term_string.push_str(&atom.to_string());
} else {
term_string.push_str(&format!("{atom}{exponent}"));
}
}
None => term_string.push_str(&atom.to_string()),
}
write!(f, "{}", self.as_str())
}
}

Expand Down

0 comments on commit a982733

Please sign in to comment.