printobserver_types/
adjustable.rs1use core::fmt;
4use core::str::FromStr;
5use std::borrow::Cow;
6
7use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
8use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
9
10const TOOL_TARGET: &str = "tool_target";
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub enum Adjustable {
21 Feedrate,
23 Flowrate,
25 ToolTarget {
27 tool: i64,
29 },
30 BedTarget,
32 Fan,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct AdjustableError {
39 detail: String,
41}
42
43impl AdjustableError {
44 #[must_use]
46 pub fn detail(&self) -> &str {
47 &self.detail
48 }
49}
50
51impl fmt::Display for AdjustableError {
52 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(formatter, "not an adjustable: {}", self.detail)
54 }
55}
56
57impl core::error::Error for AdjustableError {}
58
59impl fmt::Display for Adjustable {
60 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61 match self {
62 Self::Feedrate => formatter.write_str("feedrate"),
63 Self::Flowrate => formatter.write_str("flowrate"),
64 Self::ToolTarget { tool } => write!(formatter, "{TOOL_TARGET}:{tool}"),
65 Self::BedTarget => formatter.write_str("bed_target"),
66 Self::Fan => formatter.write_str("fan"),
67 }
68 }
69}
70
71impl FromStr for Adjustable {
72 type Err = AdjustableError;
73
74 fn from_str(text: &str) -> Result<Self, Self::Err> {
75 match text {
76 "feedrate" => return Ok(Self::Feedrate),
77 "flowrate" => return Ok(Self::Flowrate),
78 "bed_target" => return Ok(Self::BedTarget),
79 "fan" => return Ok(Self::Fan),
80 _ => {}
81 }
82 let Some(number) = text.strip_prefix(concat!("tool_target", ":")) else {
83 return Err(AdjustableError {
84 detail: format!("{text:?} names no adjustable"),
85 });
86 };
87 number
88 .parse()
89 .map(|tool| Self::ToolTarget { tool })
90 .map_err(|error| AdjustableError {
91 detail: format!("{text:?} carries no tool number: {error}"),
92 })
93 }
94}
95
96impl Serialize for Adjustable {
97 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
98 serializer.collect_str(self)
99 }
100}
101
102impl<'de> Deserialize<'de> for Adjustable {
103 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
104 let text = String::deserialize(deserializer)?;
105 text.parse().map_err(D::Error::custom)
106 }
107}
108
109impl JsonSchema for Adjustable {
110 fn schema_name() -> Cow<'static, str> {
111 Cow::Borrowed("Adjustable")
112 }
113
114 fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
115 json_schema!({
116 "type": "string",
117 "title": "Adjustable",
118 "description": "One thing an adjustment may change.",
119 "pattern": "^(feedrate|flowrate|bed_target|fan|tool_target:-?[0-9]+)$"
120 })
121 }
122}