1use crate::Error;
4use cerno_types::{Answer, SystemOneResponse, Usage};
5
6#[derive(Debug, Clone)]
11pub struct Answers {
12 response: SystemOneResponse,
13}
14
15fn name_of(answer: &Answer) -> &'static str {
16 match answer {
17 Answer::Noul { .. } => "noul",
18 Answer::Choice { .. } => "choice",
19 Answer::Score { .. } => "score",
20 }
21}
22
23impl From<SystemOneResponse> for Answers {
27 fn from(response: SystemOneResponse) -> Self {
28 Self { response }
29 }
30}
31
32impl Answers {
33 pub(crate) fn new(response: SystemOneResponse) -> Self {
34 Self { response }
35 }
36
37 pub fn model(&self) -> &str {
39 &self.response.model
40 }
41
42 pub fn usage(&self) -> Usage {
43 self.response.usage
44 }
45
46 pub fn timing_ms(&self) -> u64 {
47 self.response.timing_ms.total
48 }
49
50 pub fn get(&self, id: &str) -> Result<&Answer, Error> {
52 self.response
53 .answers
54 .get(id)
55 .ok_or_else(|| Error::MissingAnswer(id.to_string()))
56 }
57
58 pub fn noul(&self, id: &str) -> Result<f64, Error> {
60 match self.get(id)? {
61 Answer::Noul { noul, .. } => Ok(*noul),
62 other => Err(self.wrong_type(id, "noul", other)),
63 }
64 }
65
66 pub fn choice(&self, id: &str) -> Result<&str, Error> {
68 match self.get(id)? {
69 Answer::Choice { choice, .. } => Ok(choice),
70 other => Err(self.wrong_type(id, "choice", other)),
71 }
72 }
73
74 pub fn index(&self, id: &str) -> Result<usize, Error> {
76 match self.get(id)? {
77 Answer::Choice { index, .. } => Ok(*index),
78 other => Err(self.wrong_type(id, "choice", other)),
79 }
80 }
81
82 pub fn score(&self, id: &str) -> Result<u8, Error> {
84 match self.get(id)? {
85 Answer::Score { score, .. } => Ok(*score),
86 other => Err(self.wrong_type(id, "score", other)),
87 }
88 }
89
90 pub fn expected_score(&self, id: &str) -> Result<f64, Error> {
92 match self.get(id)? {
93 Answer::Score { expected_score, .. } => Ok(*expected_score),
94 other => Err(self.wrong_type(id, "score", other)),
95 }
96 }
97
98 pub fn legend(&self, id: &str) -> Result<&str, Error> {
100 match self.get(id)? {
101 Answer::Score { legend, .. } => Ok(legend),
102 other => Err(self.wrong_type(id, "score", other)),
103 }
104 }
105
106 pub fn confidence(&self, id: &str) -> Result<f64, Error> {
109 let answer = self.get(id)?;
110 answer
111 .confidence()
112 .ok_or_else(|| self.wrong_type(id, "choice or score", answer))
113 }
114
115 pub fn truncated(&self, id: &str) -> Result<bool, Error> {
118 Ok(self.get(id)?.truncated())
119 }
120
121 pub fn label_mass(&self, id: &str) -> Result<f64, Error> {
125 Ok(self.get(id)?.label_mass())
126 }
127
128 pub fn truncated_labels(&self, id: &str) -> Result<&[String], Error> {
131 Ok(self.get(id)?.truncated_labels())
132 }
133
134 pub fn ids(&self) -> impl Iterator<Item = &str> {
135 self.response.answers.keys().map(String::as_str)
136 }
137
138 pub fn into_inner(self) -> SystemOneResponse {
139 self.response
140 }
141
142 fn wrong_type(&self, id: &str, expected: &'static str, actual: &Answer) -> Error {
143 Error::WrongType {
144 id: id.to_string(),
145 expected,
146 actual: name_of(actual),
147 }
148 }
149}