notation_dsl/fretted/
shape.rs

1use fehler::throws;
2use notation_proto::prelude::{FrettedEntry4, FrettedEntry6, HandShape4, HandShape6};
3use notation_proto::proto_entry::ProtoEntry;
4use proc_macro2::TokenStream;
5use quote::{quote, ToTokens};
6use syn::parse::{Error, Parse, ParseStream};
7use syn::{parenthesized, token, LitInt, Token};
8
9use crate::context::Context;
10use crate::core::duration::DurationTweakDsl;
11
12pub struct ShapeDsl {
13    pub barre: Option<u8>,
14    pub frets: Vec<Option<u8>>,
15    pub duration_tweak: Option<DurationTweakDsl>,
16}
17
18impl Parse for ShapeDsl {
19    #[throws(Error)]
20    fn parse(input: ParseStream) -> Self {
21        let mut frets = vec![];
22        if input.peek(token::Paren) {
23            let content;
24            parenthesized!(content in input);
25            while content.peek(LitInt) || content.peek(Token![_]) {
26                if content.peek(LitInt) {
27                    frets.push(Some(content.parse::<LitInt>()?.base10_parse::<u8>()?));
28                } else {
29                    content.parse::<Token![_]>()?;
30                    frets.push(None);
31                }
32            }
33            frets.reverse();
34        }
35        let mut barre = None;
36        if input.peek(Token![+]) {
37            input.parse::<Token![+]>()?;
38            barre = Some(input.parse::<LitInt>()?.base10_parse::<u8>()?);
39        }
40
41        let duration_tweak = DurationTweakDsl::try_parse(input);
42        ShapeDsl {
43            barre,
44            frets,
45            duration_tweak,
46        }
47    }
48}
49
50impl ToTokens for ShapeDsl {
51    fn to_tokens(&self, tokens: &mut TokenStream) {
52        let ShapeDsl {
53            barre,
54            frets,
55            duration_tweak,
56        } = self;
57        //let string_num = Context::fretted().string_num;
58        let mut frets_quote: Vec<TokenStream> = vec![];
59        let mut fingers_quote: Vec<TokenStream> = vec![];
60        for fret in frets {
61            frets_quote.push(match fret {
62                Some(fret) => quote! { Some(#fret) },
63                None => quote! { None },
64            });
65            fingers_quote.push(quote! { None });
66        }
67        let duration_quote = Context::duration_quote(duration_tweak);
68        let fretted_entry_quote = Context::fretted().fretted_entry_quote();
69        let hand_shape_quote = Context::fretted().hand_shape_quote();
70        let barre = barre.unwrap_or(0);
71        tokens.extend(quote! {
72            ProtoEntry::from(#fretted_entry_quote::from(
73                (#hand_shape_quote::new_barre(
74                    #barre, [
75                    #(#frets_quote),*
76                ], [
77                    #(#fingers_quote),*
78                ]), #duration_quote)
79            ))
80        });
81    }
82}
83
84impl ShapeDsl {
85    pub fn to_proto(&self) -> ProtoEntry {
86        let ShapeDsl {
87            barre,
88            frets: _,
89            duration_tweak,
90        } = self;
91        let barre = barre.unwrap_or(0);
92        let duration = Context::tweaked_duration(duration_tweak);
93        match Context::fretted().string_num {
94            4 => {
95                let mut frets = [None; 4];
96                for i in 0..4 {
97                    frets[i] = self.frets.get(i).unwrap().clone();
98                }
99                let fingers = [None; 4];
100                ProtoEntry::from(FrettedEntry4::from((
101                    HandShape4::new_barre(barre, frets, fingers),
102                    duration,
103                )))
104            }
105            _ => {
106                let mut frets = [None; 6];
107                for i in 0..6 {
108                    frets[i] = self.frets.get(i).unwrap().clone();
109                }
110                let fingers = [None; 6];
111                ProtoEntry::from(FrettedEntry6::from((
112                    HandShape6::new_barre(barre, frets, fingers),
113                    duration,
114                )))
115            }
116        }
117    }
118}