workspacer_crate/
crate_handle_serde.rs1crate::ix!();
3
4impl ::serde::Serialize for CrateHandle {
5 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
6 where
7 S: ::serde::Serializer,
8 {
9 use ::serde::ser::SerializeStruct;
10 use tracing::{trace, debug, error};
11
12 trace!("Serializing CrateHandle");
13
14 let cargo_toml_handle = self.cargo_toml_handle().clone();
16
17 let cargo_toml_raw = sync_run_async(async move {
18 trace!("Locking cargo_toml_handle in async block for serialization");
19 let guard = cargo_toml_handle.lock().await;
20 match toml::to_string(&*guard) {
21 Ok(s) => {
22 debug!("Converted CargoToml to raw TOML string successfully for serialization");
23 s
24 }
25 Err(e) => {
26 error!("Failed to convert CargoToml to TOML string: {:?}", e);
27 String::new()
29 }
30 }
31 });
32
33 let mut state = serializer.serialize_struct("CrateHandle", 2)?;
34 state.serialize_field("crate_path", &self.crate_path())?;
35 state.serialize_field("cargo_toml_raw", &cargo_toml_raw)?;
36 state.end()
37 }
38}
39
40impl<'de> ::serde::Deserialize<'de> for CrateHandle {
41 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42 where
43 D: ::serde::Deserializer<'de>,
44 {
45 use std::fmt;
46 use tracing::{trace, debug, error};
47
48 struct CrateHandleVisitor;
49
50 impl<'de> ::serde::de::Visitor<'de> for CrateHandleVisitor {
51 type Value = CrateHandle;
52
53 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
54 formatter.write_str("struct CrateHandle with fields crate_path and cargo_toml_raw")
55 }
56
57 fn visit_map<V>(self, mut map: V) -> Result<CrateHandle, V::Error>
58 where
59 V: ::serde::de::MapAccess<'de>,
60 {
61 let mut crate_path_opt: Option<PathBuf> = None;
62 let mut cargo_toml_raw_opt: Option<String> = None;
63
64 while let Some(key) = map.next_key::<String>()? {
65 match key.as_str() {
66 "crate_path" => {
67 crate_path_opt = Some(map.next_value()?);
68 }
69 "cargo_toml_raw" => {
70 cargo_toml_raw_opt = Some(map.next_value()?);
71 }
72 _ => {
73 let _ignored: ::serde::de::IgnoredAny = map.next_value()?;
74 }
75 }
76 }
77
78 let crate_path = crate_path_opt
79 .ok_or_else(|| ::serde::de::Error::missing_field("crate_path"))?;
80 let cargo_toml_raw = cargo_toml_raw_opt
81 .ok_or_else(|| ::serde::de::Error::missing_field("cargo_toml_raw"))?;
82
83 trace!("Deserializing raw TOML into CargoToml synchronously");
84 let cargo_toml: CargoToml = toml::from_str(&cargo_toml_raw).map_err(|e| {
85 error!("Failed to parse cargo_toml_raw: {:?}", e);
86 ::serde::de::Error::custom(format!("Could not parse cargo_toml_raw: {e}"))
87 })?;
88
89 debug!("Successfully reconstructed CargoToml from raw TOML");
90 let cargo_toml_handle = Arc::new(AsyncMutex::new(cargo_toml));
91
92 Ok(CrateHandleBuilder::default()
93 .crate_path(crate_path)
94 .cargo_toml_handle(cargo_toml_handle)
95 .build()
96 .unwrap()
97 )
98 }
99 }
100
101 deserializer.deserialize_struct(
102 "CrateHandle",
103 &["crate_path", "cargo_toml_raw"],
104 CrateHandleVisitor,
105 )
106 }
107}
108
109#[cfg(test)]
110mod test_crate_handle_serde {
111 use super::*;
112 use serde_json;
113
114 #[traced_test]
115 fn test_serialize_deserialize_crate_handle() {
116 use std::io::Write;
117 use tempfile::tempdir;
118
119 let tmp_dir = tempdir().unwrap();
121 let cargo_toml_path = tmp_dir.path().join("Cargo.toml");
122 let cargo_toml_content = r#"
123 [package]
124 name = "some_crate"
125 version = "0.1.2"
126 authors = ["Someone <someone@example.com>"]
127 license = "MIT"
128 "#;
129
130 {
131 let mut f = std::fs::File::create(&cargo_toml_path)
132 .expect("Failed to create Cargo.toml");
133 f.write_all(cargo_toml_content.as_bytes())
134 .expect("Failed to write Cargo.toml");
135 }
136
137 let cargo_toml = CargoToml::new_sync(cargo_toml_path)
139 .expect("Failed to load test Cargo.toml via new_sync");
140
141 let cargo_toml_handle = Arc::new(AsyncMutex::new(cargo_toml));
143
144 let handle = CrateHandleBuilder::default()
146 .crate_path(tmp_dir.path().to_path_buf())
147 .cargo_toml_handle(cargo_toml_handle)
148 .build()
149 .unwrap();
150
151 let json_str = serde_json::to_string_pretty(&handle)
153 .expect("CrateHandle should serialize to JSON successfully");
154 trace!("Serialized JSON:\n{}", json_str);
155
156 let handle2: CrateHandle = serde_json::from_str(&json_str)
158 .expect("Deserialization of CrateHandle from JSON should succeed");
159
160 assert_eq!(handle2.name(), "some_crate");
162 let ver = handle2.version().expect("Should retrieve version from reloaded CargoToml");
163 assert_eq!(ver.to_string(), "0.1.2");
164 }
165}