alpkit 0.1.0-pre.2

A library for reading metadata from the APKv2 package format and APKBUILD.
Documentation
use std::num;

use indoc::indoc;
use serde::{Deserialize, Serialize};

use super::*;
use crate::internal::serde_key_value;
use crate::internal::test_utils::assert;

#[derive(Debug, Eq, PartialEq, Serialize)]
struct Pair {
    name: String,
    value: u64,
}

impl<'de> Deserialize<'de> for Pair {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        if let Some((key, value)) = s.split_once('=') {
            Ok(Pair {
                name: key.to_owned(),
                value: value.parse().map_err(de::Error::custom)?,
            })
        } else {
            Err(de::Error::custom("expected key=value"))
        }
    }
}

impl<'a> KeyValueLike<'a> for Pair {
    type Key = &'a str;
    type Value = String;
    type Err = num::ParseIntError;

    fn from_key_value(key: Self::Key, value: Self::Value) -> Result<Self, Self::Err> {
        Ok(Self {
            name: key.to_owned(),
            value: value.parse()?,
        })
    }

    fn to_key_value(&'a self) -> (Self::Key, Self::Value) {
        (&self.name, self.value.to_string())
    }
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Pairs {
    #[serde(with = "self")]
    pairs: Vec<Pair>,
}

fn fixture_struct() -> Pairs {
    Pairs {
        pairs: vec![
            Pair {
                name: "foo".into(),
                value: 42,
            },
            Pair {
                name: "bar".into(),
                value: 55,
            },
        ],
    }
}

#[test]
fn deserialize_json_map() {
    let json = indoc!(
        r#"
        {
            "pairs": {
                "foo": "42",
                "bar": "55"
            }
        }
    "#
    );
    let expected = fixture_struct();

    assert!(serde_json::from_str::<Pairs>(json).unwrap() == expected);
}

#[test]
fn deserialize_json_seq() {
    let json = indoc!(
        r#"
        {
            "pairs": [
                "foo=42",
                "bar=55"
            ]
        }
    "#
    );
    let expected = fixture_struct();

    assert!(serde_json::from_str::<Pairs>(json).unwrap() == expected);
}

#[test]
fn deserialize_key_value_seq() {
    let input = vec![("pairs", "foo=42"), ("pairs", "bar=55")];
    let expected = fixture_struct();
    assert!(
        serde_key_value::from_pairs::<Pairs>(input).unwrap() == expected,
        "multiple elements"
    );

    let input = vec![("pairs", "foo=42")];
    let expected = Pairs {
        pairs: vec![Pair {
            name: "foo".to_owned(),
            value: 42,
        }],
    };
    assert!(
        serde_key_value::from_pairs::<Pairs>(input).unwrap() == expected,
        "single element"
    );
}

#[test]
fn serialize_map() {
    let input = fixture_struct();

    assert!(&serde_json::to_string(&input).unwrap() == r#"{"pairs":{"foo":"42","bar":"55"}}"#);
}