snops_common/state/
height_request.rs1use std::str::FromStr;
2
3use snops_checkpoint::RetentionSpan;
4
5use crate::format::{DataFormat, DataFormatReader, DataHeaderOf, DataReadError};
6
7#[derive(Debug, Copy, Default, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
13#[serde(rename_all = "lowercase", untagged)]
14pub enum DocHeightRequest {
15 #[default]
16 #[serde(with = "super::strings::top")]
18 Top,
19 Absolute(u32),
22 Checkpoint(snops_checkpoint::RetentionSpan),
24 }
28
29impl FromStr for DocHeightRequest {
30 type Err = String;
31
32 fn from_str(s: &str) -> Result<Self, Self::Err> {
33 match s {
34 "top" => Ok(DocHeightRequest::Top),
35 s => {
36 if let Ok(height) = s.parse() {
37 Ok(DocHeightRequest::Absolute(height))
38 } else if let Ok(span) = s.parse() {
39 Ok(DocHeightRequest::Checkpoint(span))
40 } else {
41 Err(format!("invalid DocHeightRequest: {}", s))
42 }
43 }
44 }
45 }
46}
47
48impl DataFormat for DocHeightRequest {
49 type Header = (u8, DataHeaderOf<RetentionSpan>);
50 const LATEST_HEADER: Self::Header = (1, RetentionSpan::LATEST_HEADER);
51
52 fn write_data<W: std::io::prelude::Write>(
53 &self,
54 writer: &mut W,
55 ) -> Result<usize, crate::format::DataWriteError> {
56 match self {
57 DocHeightRequest::Top => 0u8.write_data(writer),
58 DocHeightRequest::Absolute(height) => {
59 Ok(1u8.write_data(writer)? + height.write_data(writer)?)
60 }
61 DocHeightRequest::Checkpoint(retention) => {
62 Ok(2u8.write_data(writer)? + retention.write_data(writer)?)
63 }
64 }
65 }
66
67 fn read_data<R: std::io::prelude::Read>(
68 reader: &mut R,
69 header: &Self::Header,
70 ) -> Result<Self, DataReadError> {
71 if header.0 != Self::LATEST_HEADER.0 {
72 return Err(DataReadError::unsupported(
73 "DocHeightRequest",
74 Self::LATEST_HEADER.0,
75 header.0,
76 ));
77 }
78 match reader.read_data(&())? {
79 0u8 => Ok(DocHeightRequest::Top),
80 1u8 => Ok(DocHeightRequest::Absolute(reader.read_data(&())?)),
81 2u8 => Ok(DocHeightRequest::Checkpoint(reader.read_data(&header.1)?)),
82 n => Err(DataReadError::Custom(format!(
83 "invalid DocHeightRequest discrminant: {n}"
84 ))),
85 }
86 }
87}
88
89#[derive(Debug, Default, Copy, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
90#[serde(rename_all = "lowercase")]
91pub enum HeightRequest {
92 #[default]
93 Top,
95 Absolute(u32),
98 Checkpoint(snops_checkpoint::RetentionSpan),
100 }
104
105impl DataFormat for HeightRequest {
108 type Header = (u8, DataHeaderOf<RetentionSpan>);
109 const LATEST_HEADER: Self::Header = (1, RetentionSpan::LATEST_HEADER);
110
111 fn write_data<W: std::io::prelude::Write>(
112 &self,
113 writer: &mut W,
114 ) -> Result<usize, crate::format::DataWriteError> {
115 match self {
116 HeightRequest::Top => 0u8.write_data(writer),
117 HeightRequest::Absolute(height) => {
118 Ok(1u8.write_data(writer)? + height.write_data(writer)?)
119 }
120 HeightRequest::Checkpoint(retention) => {
121 Ok(2u8.write_data(writer)? + retention.write_data(writer)?)
122 }
123 }
124 }
125
126 fn read_data<R: std::io::prelude::Read>(
127 reader: &mut R,
128 header: &Self::Header,
129 ) -> Result<Self, DataReadError> {
130 if header.0 != Self::LATEST_HEADER.0 {
131 return Err(DataReadError::unsupported(
132 "HeightRequest",
133 Self::LATEST_HEADER.0,
134 header.0,
135 ));
136 }
137 match reader.read_data(&())? {
138 0u8 => Ok(HeightRequest::Top),
139 1u8 => Ok(HeightRequest::Absolute(reader.read_data(&())?)),
140 2u8 => Ok(HeightRequest::Checkpoint(reader.read_data(&header.1)?)),
141 n => Err(DataReadError::Custom(format!(
142 "invalid HeightRequest discrminant: {n}"
143 ))),
144 }
145 }
146}
147
148impl HeightRequest {
149 pub fn is_top(&self) -> bool {
150 *self == Self::Top
151 }
152
153 pub fn reset(&self) -> bool {
154 *self == Self::Absolute(0)
155 }
156}
157
158impl From<DocHeightRequest> for HeightRequest {
159 fn from(req: DocHeightRequest) -> Self {
160 match req {
161 DocHeightRequest::Top => Self::Top,
162 DocHeightRequest::Absolute(h) => Self::Absolute(h),
163 DocHeightRequest::Checkpoint(c) => Self::Checkpoint(c),
164 }
165 }
166}