1 /*
2  *Copyright (C) 2018 Laurent Tréguier
3  *
4  *This file is part of DLS.
5  *
6  *DLS is free software: you can redistribute it and/or modify
7  *it under the terms of the GNU General Public License as published by
8  *the Free Software Foundation, either version 3 of the License, or
9  *(at your option) any later version.
10  *
11  *DLS is distributed in the hope that it will be useful,
12  *but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *GNU General Public License for more details.
15  *
16  *You should have received a copy of the GNU General Public License
17  *along with DLS.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 module dls.protocol.state;
22 
23 import dls.protocol.interfaces : InitializeParams;
24 
25 private InitializeParams _initState;
26 private InitializeParams.InitializationOptions _commandLineOptions;
27 
28 static this()
29 {
30     _initState = new InitializeParams();
31     _commandLineOptions = new InitializeParams.InitializationOptions();
32 }
33 
34 @property InitializeParams initState()
35 {
36     return _initState;
37 }
38 
39 @property void initState(InitializeParams params)
40 {
41     import dls.protocol.logger : logger;
42     import dls.util.disposable_fiber : DisposableFiber;
43 
44     assert(params !is null);
45     _initState = params;
46 
47     if (!params.trace.isNull)
48     {
49         logger.trace = params.trace;
50     }
51 
52     if (_initState.initializationOptions.isNull)
53     {
54         _initState.initializationOptions = _commandLineOptions;
55     }
56     else
57     {
58         merge(params.initializationOptions.get(), _commandLineOptions);
59     }
60 
61     DisposableFiber.safeMode = initOptions.safeMode;
62 }
63 
64 @property InitializeParams.InitializationOptions initOptions()
65 {
66     return initState.initializationOptions.isNull ? _commandLineOptions
67         : _initState.initializationOptions;
68 }
69 
70 @property void initOptions(InitializeParams.InitializationOptions options)
71 {
72     assert(options !is null);
73     _commandLineOptions = options;
74 }
75 
76 private void merge(T)(ref T options, const T addins)
77 {
78     import std.meta : Alias;
79     import std.traits : isSomeFunction, isType;
80     import dls.protocol.logger : logger;
81 
82     static if (is(T == class))
83     {
84         immutable reference = new T();
85     }
86     else
87     {
88         immutable reference = T.init;
89     }
90 
91     foreach (member; __traits(allMembers, T))
92     {
93         alias m = Alias!(__traits(getMember, T, member));
94         alias optionsMember = Alias!(mixin("options." ~ member));
95         alias addinsMember = Alias!(mixin("addins." ~ member));
96 
97         static if (__traits(getProtection, m) != "public" || isType!m || isSomeFunction!m)
98         {
99             continue;
100         }
101         else static if (is(typeof(m) == class))
102         {
103             merge(mixin("options." ~ member), mixin("addins." ~ member));
104         }
105         else
106         {
107             if (mixin("options." ~ member) == mixin("reference." ~ member))
108             {
109                 mixin("options." ~ member) = mixin("addins." ~ member);
110             }
111         }
112     }
113 }