1use std::convert::TryFrom;
2
3use lace_codebook::ColType;
4use lace_data::Datum;
5use serde::{Deserialize, Serialize};
6
7#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
9#[serde(rename_all = "snake_case")]
10pub enum FType {
11 Binary,
12 Continuous,
13 Categorical,
14 Count,
15}
16
17impl std::fmt::Display for FType {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 match self {
20 Self::Binary => write!(f, "Binary"),
21 Self::Continuous => write!(f, "Continuous"),
22 Self::Categorical => write!(f, "Categorical"),
23 Self::Count => write!(f, "Count"),
24 }
25 }
26}
27
28impl std::str::FromStr for FType {
29 type Err = String;
30
31 fn from_str(s: &str) -> Result<Self, Self::Err> {
32 match s {
33 "Binary" => Ok(FType::Binary),
34 "Continuous" => Ok(FType::Continuous),
35 "Categorical" => Ok(FType::Categorical),
36 "Count" => Ok(FType::Count),
37 invalid => Err(format!("Invalid ftype: '{invalid}'")),
38 }
39 }
40}
41
42impl From<FType> for String {
43 fn from(ftype: FType) -> Self {
44 ftype.to_string()
45 }
46}
47
48#[derive(Debug)]
50pub struct FTypeCompat {
51 pub ftype_req: FType,
53 pub ftype: FType,
55}
56
57impl TryFrom<&Datum> for FType {
58 type Error = ();
59
60 fn try_from(datum: &Datum) -> Result<Self, Self::Error> {
61 match datum {
62 Datum::Binary(_) => Ok(FType::Binary),
63 Datum::Categorical(_) => Ok(FType::Categorical),
64 Datum::Continuous(_) => Ok(FType::Continuous),
65 Datum::Count(_) => Ok(FType::Count),
66 Datum::Missing => Err(()),
67 }
68 }
69}
70
71impl FType {
72 pub fn from_coltype(coltype: &ColType) -> FType {
73 match coltype {
74 ColType::Continuous { .. } => FType::Continuous,
75 ColType::Categorical { .. } => FType::Categorical,
76 ColType::Count { .. } => FType::Count,
77 }
78 }
79
80 pub fn is_continuous(self) -> bool {
81 matches!(self, FType::Continuous)
82 }
83
84 pub fn is_categorical(self) -> bool {
85 matches!(self, FType::Categorical)
86 }
87
88 pub fn is_count(self) -> bool {
89 matches!(self, FType::Count)
90 }
91
92 pub fn datum_compatible(self, datum: &Datum) -> (bool, FTypeCompat) {
94 if let Ok(ftype_req) = FType::try_from(datum) {
95 let ok = ftype_req == self;
96 (
97 ok,
98 FTypeCompat {
99 ftype_req,
100 ftype: self,
101 },
102 )
103 } else {
104 (
106 true,
107 FTypeCompat {
108 ftype_req: self,
109 ftype: self,
110 },
111 )
112 }
113 }
114}
115
116