1use anyhow::Result;
5
6use crate::act;
7
8pub use act_types::ComponentInfo;
9pub fn read_component_info(component_bytes: &[u8]) -> Result<ComponentInfo> {
12 let mut info = ComponentInfo::default();
13
14 for payload in wasmparser::Parser::new(0).parse_all(component_bytes) {
15 if let Ok(wasmparser::Payload::CustomSection(section)) = payload {
16 match section.name() {
17 act_types::constants::SECTION_ACT_COMPONENT => {
18 info = ciborium::from_reader(section.data())
19 .map_err(|e| anyhow::anyhow!("failed to decode act:component CBOR: {e}"))?;
20 }
21 "version" if info.std.version.is_empty() => {
22 info.std.version = String::from_utf8_lossy(section.data()).into_owned();
23 }
24 "description" if info.std.description.is_empty() => {
25 info.std.description = String::from_utf8_lossy(section.data()).into_owned();
26 }
27 _ => {}
28 }
29 }
30 }
31
32 if info.std.name.is_empty() {
33 info.std.name = "unknown".to_string();
34 }
35
36 Ok(info)
37}
38
39impl From<&act::core::types::LocalizedString> for act_types::types::LocalizedString {
41 fn from(ls: &act::core::types::LocalizedString) -> Self {
42 match ls {
43 act::core::types::LocalizedString::Plain(s) => Self::Plain(s.clone()),
44 act::core::types::LocalizedString::Localized(pairs) => Self::from(pairs.clone()),
45 }
46 }
47}
48
49#[derive(Debug)]
57pub enum ComponentError {
58 Tool(act::core::types::Error),
60 Internal(anyhow::Error),
62}
63
64impl std::fmt::Display for ComponentError {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 Self::Tool(e) => {
70 let message = act_types::types::LocalizedString::from(&e.message);
71 write!(f, "{}: {}", e.kind, message.any_text())
72 }
73 Self::Internal(e) => write!(f, "{e}"),
74 }
75 }
76}
77
78impl std::error::Error for ComponentError {
79 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
80 match self {
81 Self::Tool(_) => None,
82 Self::Internal(e) => Some(e.as_ref()),
83 }
84 }
85}