1#[cfg(doctest)]
19#[macro_use]
20extern crate doc_comment;
21
22#[cfg(doctest)]
23doc_comment! {
24 include_str!("../README.md")
25}
26
27#[cfg(any(
28 feature = "serde",
29 feature = "bincode_1_3",
30 feature = "bincode_2",
31 feature = "postcard_1_0",
32 feature = "rmp_serde_1_3",
33 doc
34))]
35mod codec;
36
37#[cfg(any(
38 feature = "serde",
39 feature = "bincode_1_3",
40 feature = "bincode_2",
41 feature = "postcard_1_0",
42 feature = "rmp_serde_1_3",
43 doc
44))]
45pub use codec::*;
46mod header;
47pub mod wrapper;
48
49pub use native_model_macro::*;
51
52use wrapper::*;
53
54use thiserror::Error;
55
56pub type Result<T> = std::result::Result<T, Error>;
57
58#[derive(Error, Debug)]
59pub enum Error {
60 #[error("Invalid header")]
61 InvalidHeader,
62 #[error("Failed to decode native model")]
63 DecodeError,
64 #[error(transparent)]
65 DecodeBodyError(#[from] DecodeBodyError),
66 #[error(transparent)]
67 EncodeBodyError(#[from] EncodeBodyError),
68 #[error(transparent)]
69 UpgradeError(#[from] UpgradeError),
70 #[error("Upgrade from {} to {} is not supported", from, to)]
71 UpgradeNotSupported { from: u32, to: u32 },
72 #[error(transparent)]
73 DowngradeError(#[from] DowngradeError),
74 #[error("Downgrade from {} to {} is not supported", from, to)]
75 DowngradeNotSupported { from: u32, to: u32 },
76 #[error("Wrong type id expected: {}, actual: {}", expected, actual)]
77 WrongTypeId { expected: u32, actual: u32 },
78}
79
80pub type DecodeResult<T> = std::result::Result<T, DecodeBodyError>;
81
82#[derive(Error, Debug)]
83#[error("Decode body error: {msg}")]
84pub enum DecodeBodyError {
85 #[error("Mismatched model id")]
86 MismatchedModelId,
87 #[error("Decode error: {msg}")]
88 DecodeError {
89 msg: String,
90 #[source]
91 source: anyhow::Error,
92 },
93}
94
95pub type EncodeResult<T> = std::result::Result<T, EncodeBodyError>;
96
97#[derive(Error, Debug)]
98#[error("Encode body error: {msg}")]
99pub struct EncodeBodyError {
100 pub msg: String,
101 #[source]
102 pub source: anyhow::Error,
103}
104
105#[derive(Error, Debug)]
106#[error("Upgrade error: {msg}")]
107pub struct UpgradeError {
108 pub msg: String,
109 #[source]
110 pub source: anyhow::Error,
111}
112
113#[derive(Error, Debug)]
114#[error("Downgrade error: {msg}")]
115pub struct DowngradeError {
116 pub msg: String,
117 #[source]
118 pub source: anyhow::Error,
119}
120
121pub fn encode<T: crate::Model>(model: &T) -> Result<Vec<u8>> {
132 T::native_model_encode(model)
133}
134
135pub fn encode_downgrade<T: crate::Model>(model: T, version: u32) -> Result<Vec<u8>> {
140 T::native_model_encode_downgrade(model, version)
141}
142
143pub fn decode<T: crate::Model>(data: Vec<u8>) -> Result<(T, u32)> {
153 T::native_model_decode(data)
154}
155
156pub trait Model: Sized {
157 fn native_model_id() -> u32;
158 fn native_model_id_str() -> &'static str;
159 fn native_model_version() -> u32;
160 fn native_model_version_str() -> &'static str;
161
162 fn native_model_decode_body(data: Vec<u8>, id: u32) -> DecodeResult<Self>;
164
165 fn native_model_decode_upgrade_body(data: Vec<u8>, id: u32, version: u32) -> Result<Self>;
166
167 fn native_model_decode(data: impl AsRef<[u8]>) -> Result<(Self, u32)> {
168 let native_model = crate::Wrapper::deserialize(data.as_ref()).unwrap();
169 let source_id = native_model.get_id();
170 let source_version = native_model.get_version();
171 let result = Self::native_model_decode_upgrade_body(
172 native_model.value().to_vec(),
173 source_id,
174 source_version,
175 )?;
176 Ok((result, source_version))
177 }
178
179 fn native_model_encode_body(&self) -> EncodeResult<Vec<u8>>;
182
183 fn native_model_encode_downgrade_body(self, version: u32) -> Result<Vec<u8>>;
184
185 fn native_model_encode(&self) -> Result<Vec<u8>> {
186 let mut data = self.native_model_encode_body()?;
187 let data = crate::native_model_encode(
188 &mut data,
189 Self::native_model_id(),
190 Self::native_model_version(),
191 );
192 Ok(data)
193 }
194
195 fn native_model_encode_downgrade(self, version: u32) -> Result<Vec<u8>> {
196 let mut data = self.native_model_encode_downgrade_body(version)?;
197 let data = crate::native_model_encode(&mut data, Self::native_model_id(), version);
198 Ok(data)
199 }
200}