79219958

Date: 2024-11-24 11:41:54
Score: 1
Natty:
Report link

Thanks to kmdreko in the comments. It turns out that it isn't something you can do in Rust, however it was enough to constraint a single parameter type to the traits I needed. Now my quantity module has no actual mention of Quantity<D,U,V> while still operating on them.

Here's what it looks like :

#[derive(Debug)]
pub struct ParsedValue<L>
where
    L: FromStr + Debug + DefaultUnit,
{
    pub raw: String,
    pub parsed: L,
}

impl<L> ParsedValue<L>
where
    L: FromStr + Debug + DefaultUnit,
    <L as FromStr>::Err: Debug,
{
    // Constructor to create a new ParsedValue
    pub fn new(raw: &str) -> Result<Self, ParseError<L>> {
        if let Some(captures) = HAS_UNIT_RE.captures(raw) {
            let _is_reference = captures.get(1).is_some();
            let raw = format!(
                "{} {}",
                captures[2].to_string(),
                if let Some(unit) = captures.get(3) {
                    unit.as_str()
                } else {
                    L::DEFAULT_UNIT
                }
            );
            // Parse the string into L, or handle failure
            let parsed = raw
                .parse::<L>()
                .map_err(|e| ParseError::UnrecognizedQuantity(e))?;
            Ok(ParsedValue {
                raw: raw.to_string(),
                parsed,
            })
        } else {
            Err(ParseError::InvalidQuantityFormat(raw.to_string()))
        }
    }
}

use uom::si::f64 as si;

pub trait DefaultUnit {
    const DEFAULT_UNIT: &str;
}

/// Length (default: kilometers, since distances in geoscience are often measured in km)
pub type Length = ParsedValue<si::Length>;

impl DefaultUnit for si::Length {
    const DEFAULT_UNIT: &str = "km";
}


#[derive(Debug)]
pub enum ParseError<T> where T: FromStr, <T as FromStr>::Err: Debug {
    InvalidQuantityFormat(String),
    UnrecognizedQuantity(<T as FromStr>::Err)
}

use ParseError::*;

impl<T> Display for ParseError<T> where T: FromStr, <T as FromStr>::Err: Debug  {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                InvalidQuantityFormat(s) => format!("Invalid Quantity Format : {}", s),
                UnrecognizedQuantity(s) => format!("Unrecognized quantity : '{s:?}'. Check the unit and value.")
            }
        )
    }
}

impl<T> std::error::Error for ParseError<T> where  T: FromStr+Debug, <T as FromStr>::Err: Debug {
}


Reasons:
  • Blacklisted phrase (0.5): Thanks
  • Blacklisted phrase (0.5): I need
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Lyss