Skip to main content

cards2pack_core/
parse.rs

1//! Parse `contents_json` payload into `Vec<CardEntry>`.
2
3use crate::errors::ConvertError;
4use crate::types::{CardEntry, CardKind, HttpConfig};
5use serde::Deserialize;
6
7#[derive(Debug, Deserialize)]
8struct RawEntry {
9    id: String,
10    json: serde_json::Value,
11}
12
13pub fn parse_cards(contents_json: &str) -> Result<Vec<CardEntry>, ConvertError> {
14    let raw: Vec<RawEntry> =
15        serde_json::from_str(contents_json).map_err(|e| ConvertError::Parse(e.to_string()))?;
16
17    let mut out = Vec::with_capacity(raw.len());
18    for entry in raw {
19        let kind = classify(&entry)?;
20        out.push(CardEntry { id: entry.id, kind });
21    }
22    Ok(out)
23}
24
25fn classify(entry: &RawEntry) -> Result<CardKind, ConvertError> {
26    let ty = entry
27        .json
28        .get("type")
29        .and_then(|v| v.as_str())
30        .unwrap_or("");
31    if ty == "http" {
32        let config_value = entry
33            .json
34            .get("config")
35            .cloned()
36            .unwrap_or(serde_json::json!({}));
37        let cfg: HttpConfig =
38            serde_json::from_value(config_value).map_err(|e| ConvertError::InvalidHttp {
39                id: entry.id.clone(),
40                msg: e.to_string(),
41            })?;
42        Ok(CardKind::Http(cfg))
43    } else {
44        Ok(CardKind::AdaptiveCard(entry.json.clone()))
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn parses_mixed_card_and_http() {
54        let raw = r#"[
55            {"id":"welcome","json":{"type":"AdaptiveCard","version":"1.5"}},
56            {"id":"api_x","json":{"type":"http","config":{"url":"http://x","method":"GET","next_entry_id":"after"}}}
57        ]"#;
58        let cards = parse_cards(raw).unwrap();
59        assert_eq!(cards.len(), 2);
60        assert_eq!(cards[0].id, "welcome");
61        assert!(matches!(cards[0].kind, CardKind::AdaptiveCard(_)));
62        assert!(matches!(cards[1].kind, CardKind::Http(_)));
63    }
64
65    #[test]
66    fn rejects_invalid_http_config() {
67        let raw = r#"[{"id":"bad","json":{"type":"http","config":{"url":42}}}]"#;
68        let err = parse_cards(raw).unwrap_err();
69        assert_eq!(err.code(), "E_INVALID_HTTP");
70    }
71
72    #[test]
73    fn rejects_invalid_json() {
74        let err = parse_cards("not json").unwrap_err();
75        assert_eq!(err.code(), "E_PARSE");
76    }
77}