1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Exported `unit` type for generic type conversions within
//! [Tasks], [Inputs], and around [Invocations].
//!
//! [Tasks]: crate::Task
//! [Inputs]: crate::task::instruction::Input
//! [Invocations]: crate::Invocation

use crate::{
    error::InputParseError,
    task::instruction::{Args, Input, Parse, Parsed},
    Error,
};
use libipld::Ipld;
use serde::{Deserialize, Serialize};

/// Unit type, which allows only one value (and thusly holds
/// no information). Essentially a wrapper over `()`, but one we control.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Unit;

impl From<Unit> for Ipld {
    fn from(_unit: Unit) -> Self {
        Ipld::Null
    }
}

impl From<Ipld> for Unit {
    fn from(_ipld: Ipld) -> Self {
        Unit
    }
}

// Default implementation.
impl Parse<Unit> for Input<Unit> {
    fn parse(&self) -> Result<Parsed<Unit>, InputParseError<Unit>> {
        let args = match Ipld::from(self.to_owned()) {
            Ipld::List(v) => Ipld::List(v).try_into()?,
            ipld => Args::new(vec![ipld.try_into()?]),
        };

        Ok(Parsed::with(args))
    }
}

impl From<Error<String>> for InputParseError<Unit> {
    fn from(err: Error<String>) -> Self {
        InputParseError::Invocation(err.into())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn ser_de() {
        let unit = Unit;
        let ser = serde_json::to_string(&unit).unwrap();
        let de = serde_json::from_str(&ser).unwrap();

        assert_eq!(unit, de);
    }
}