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
use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{Ident, TypePath};

use util::{parse_eq, unknown_attribute, BELONGS_TO_NOTE};

enum Attr {
    ForeignKey(Ident, Ident),
}

impl Parse for Attr {
    fn parse(input: ParseStream) -> Result<Self> {
        let name: Ident = input.parse()?;
        let name_str = name.to_string();

        match &*name_str {
            "foreign_key" => Ok(Attr::ForeignKey(name, parse_eq(input, BELONGS_TO_NOTE)?)),

            _ => unknown_attribute(&name, &["foreign_key"]),
        }
    }
}

pub struct BelongsTo {
    pub parent: TypePath,
    pub foreign_key: Option<Ident>,
}

impl Parse for BelongsTo {
    fn parse(input: ParseStream) -> Result<Self> {
        let parent = input.parse()?;

        if !input.is_empty() {
            input.parse::<Comma>()?;
        }

        let mut foreign_key = None;

        for attr in Punctuated::<Attr, Comma>::parse_terminated(input)? {
            match attr {
                Attr::ForeignKey(_, value) => foreign_key = Some(value),
            }
        }

        Ok(BelongsTo {
            parent,
            foreign_key,
        })
    }
}