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
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#![crate_name = "typify_gostruct"]

use interpreters::ToInterpreter;
use scanner::Input;

mod ast;
mod interpreters;
mod parser;
mod scanner;

/// The source holds the go-lang struct(s) that you want to transform
pub struct Source<S>(S);

impl<I> Source<I>
where
    I: Input + Copy,
{
    /// Returns a new Source which can then be transfomed.
    /// # Arguments
    ///
    /// * `input` - Anything that implements the Input trait. (by default this either a `String` or `&str`)
    ///
    /// # Examples
    /// ```
    /// use typify_gostruct;
    /// let input = r#"
    /// type Region struct {
    /// Country string `json:"country" binding:"required"`
    /// State string
    /// }"#;
    /// let source = typify_gostruct::Source::new(input);
    ///
    /// ```
    pub fn new(input: I) -> Self {
        Self(input)
    }
    /// Returns the transformed go-lang struct.
    /// # Arguments
    ///
    /// * `target` - Target represents the target interpreter that will be used for the transformation. This can be anything that implements the `TargetIntepreter` Trait. By default this can be a `String` or `&str`
    ///
    ///
    /// * #### N/B: The targets that can be used as of now are, "flow" & "typescript" (more to come...).
    /// # Examples
    /// ```
    /// use typify_gostruct;
    /// let input = r#"
    /// type Region struct {
    /// Country string `json:"country" binding:"required"`
    /// State string
    /// }"#;
    /// let source = typify_gostruct::Source::new(input);
    /// let result = source.transform_to("flow").expect("The struct should be transformed without an issue");
    /// assert!(result.contains("// @flow"))
    ///
    /// ```
    pub fn transform_to<T>(&self, target: T) -> Result<String, Vec<String>>
    where
        T: ToInterpreter,
    {
        let tokens = scanner::scan(self.0)?;
        let parsed_result = parser::parse(&tokens)?;
        let interpreter = target.convert()?;
        interpreter
            .interpret(parsed_result)
            .map_err(|err| err.into())
    }
}

mod tests {

    #[test]
    fn should_transform_struct_with_flow_interpeter_successfully() {
        let input = r#"
            type Region struct {
            Country string `json:"country" binding:"required"`
            State string
        }"#;
        let source = super::Source::new(input);
        let result = source
            .transform_to("flow")
            .expect("The struct should be transformed without an issue");
        assert!(result.contains("// @flow"));
        assert!(result.contains("country : string"));
        assert!(result.contains("State : string"))
    }

    #[test]
    fn should_transform_struct_with_typescript_interpeter_successfully() {
        let input = r#"
            type Region struct {
            Country string `json:"country" binding:"required"`
            State string
        }"#;
        let source = super::Source::new(input);
        let result = source
            .transform_to("typescript")
            .expect("The struct should be transformed without an issue");
        assert!(result.contains("export interface Region"));
        assert!(result.contains("country : string"));
        assert!(result.contains("State : string"))
    }

    #[test]
    #[should_panic]
    fn should_return_error_if_struct_isnt_valid() {
        let input = r#"
            type Region struct {
            Country string `json:"country" binding:"required"`
            State string
        "#;
        let source = super::Source::new(input);
        source
            .transform_to("typescript")
            .expect("The struct has a missing right brace and so it should fail to parse");
    }

    #[test]
    fn should_return_error() {
        let input = r#"
        person struct {
            name string
            age  int
        }
        "#;
        let source = super::Source::new(input);

        source.transform_to("typescript");
    }
}