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