duckling 0.4.0

A Rust port of Facebook's Duckling library for parsing natural language into structured data
Documentation
pub mod ar;
pub mod bg;
pub mod ca;
pub mod en;
pub mod es;
pub mod fr;
pub mod ga;
pub mod he;
pub mod hr;
pub mod id;
pub mod it;
pub mod ka;
pub mod ko;
pub mod mn;
pub mod nb;
pub mod nl;
pub mod pt;
pub mod ro;
pub mod ru;
pub mod sv;
pub mod tr;
pub mod vi;
pub mod zh;

use crate::types::{DimensionValue, MeasurementPoint, MeasurementValue};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(clippy::upper_case_acronyms)]
pub enum Currency {
    // Ambiguous
    Cent,
    Dinar,
    Dollar,
    Pound,
    Rial,
    Riyal,
    Unnamed,
    // Specific
    AED,
    AUD,
    BGN,
    BRL,
    BYN,
    CAD,
    CHF,
    CNY,
    CZK,
    DKK,
    EGP,
    EUR,
    GBP,
    GEL,
    HKD,
    HRK,
    IDR,
    ILS,
    INR,
    IQD,
    JMD,
    JOD,
    JPY,
    KRW,
    KWD,
    LBP,
    MAD,
    MNT,
    MYR,
    NOK,
    NZD,
    PKR,
    PLN,
    PTS,
    QAR,
    RON,
    RUB,
    SAR,
    SEK,
    SGD,
    THB,
    TTD,
    UAH,
    USD,
    VND,
    ZAR,
    TRY,
}

impl Currency {
    pub fn as_str(&self) -> &'static str {
        match self {
            Currency::Cent => "cent",
            Currency::Dinar => "dinar",
            Currency::Dollar => "USD",
            Currency::Pound => "GBP",
            Currency::Rial => "rial",
            Currency::Riyal => "riyal",
            Currency::Unnamed => "USD",
            Currency::AED => "AED",
            Currency::AUD => "AUD",
            Currency::BGN => "BGN",
            Currency::BRL => "BRL",
            Currency::BYN => "BYN",
            Currency::CAD => "CAD",
            Currency::CHF => "CHF",
            Currency::CNY => "CNY",
            Currency::CZK => "CZK",
            Currency::DKK => "DKK",
            Currency::EGP => "EGP",
            Currency::EUR => "EUR",
            Currency::GBP => "GBP",
            Currency::GEL => "GEL",
            Currency::HKD => "HKD",
            Currency::HRK => "HRK",
            Currency::IDR => "IDR",
            Currency::ILS => "ILS",
            Currency::INR => "INR",
            Currency::IQD => "IQD",
            Currency::JMD => "JMD",
            Currency::JOD => "JOD",
            Currency::JPY => "JPY",
            Currency::KRW => "KRW",
            Currency::KWD => "KWD",
            Currency::LBP => "LBP",
            Currency::MAD => "MAD",
            Currency::MNT => "MNT",
            Currency::MYR => "MYR",
            Currency::NOK => "NOK",
            Currency::NZD => "NZD",
            Currency::PKR => "PKR",
            Currency::PLN => "PLN",
            Currency::PTS => "PTS",
            Currency::QAR => "QAR",
            Currency::RON => "RON",
            Currency::RUB => "RUB",
            Currency::SAR => "SAR",
            Currency::SEK => "SEK",
            Currency::SGD => "SGD",
            Currency::THB => "THB",
            Currency::TTD => "TTD",
            Currency::UAH => "UAH",
            Currency::USD => "USD",
            Currency::VND => "VND",
            Currency::ZAR => "ZAR",
            Currency::TRY => "TRY",
        }
    }
}

#[derive(Debug, Clone)]
pub struct AmountOfMoneyData {
    pub value: Option<f64>,
    pub currency: Currency,
    pub min_value: Option<f64>,
    pub max_value: Option<f64>,
    pub latent: bool,
}

impl AmountOfMoneyData {
    pub fn currency_only(c: Currency) -> Self {
        AmountOfMoneyData {
            value: None,
            currency: c,
            min_value: None,
            max_value: None,
            latent: false,
        }
    }

    pub fn with_value(mut self, v: f64) -> Self {
        self.value = Some(v);
        self
    }

    pub fn with_cents(self, c: f64) -> Self {
        match self.value {
            Some(v) => AmountOfMoneyData {
                value: Some(v + c / 100.0),
                ..self
            },
            None => AmountOfMoneyData {
                value: Some(c),
                currency: Currency::Cent,
                min_value: None,
                max_value: None,
                latent: false,
            },
        }
    }

    pub fn with_interval(mut self, from: f64, to: f64) -> Self {
        self.min_value = Some(from);
        self.max_value = Some(to);
        self.value = None;
        self
    }

    pub fn with_min(mut self, v: f64) -> Self {
        self.min_value = Some(v);
        self
    }

    pub fn with_max(mut self, v: f64) -> Self {
        self.max_value = Some(v);
        self
    }
}

pub fn resolve(data: &AmountOfMoneyData, with_latent: bool) -> Option<DimensionValue> {
    // Latent tokens filtered when with_latent=false
    if data.latent && !with_latent {
        return None;
    }
    // Currency-only tokens don't resolve
    if data.value.is_none() && data.min_value.is_none() && data.max_value.is_none() {
        return None;
    }

    let unit = data.currency.as_str().to_string();

    let mv = if let Some(value) = data.value {
        MeasurementValue::Value { value, unit }
    } else if let (Some(from), Some(to)) = (data.min_value, data.max_value) {
        MeasurementValue::Interval {
            from: Some(MeasurementPoint {
                value: from,
                unit: unit.clone(),
            }),
            to: Some(MeasurementPoint { value: to, unit }),
        }
    } else if let Some(from) = data.min_value {
        MeasurementValue::Interval {
            from: Some(MeasurementPoint { value: from, unit }),
            to: None,
        }
    } else if let Some(to) = data.max_value {
        MeasurementValue::Interval {
            from: None,
            to: Some(MeasurementPoint { value: to, unit }),
        }
    } else {
        return None;
    };
    Some(DimensionValue::AmountOfMoney(mv))
}