1 /*
2  * hunt-proton: AMQP Protocol library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 
13 module hunt.proton.codec.transport.DispositionType;
14 
15 import hunt.collection.AbstractList;
16 import hunt.collection.List;
17 import hunt.proton.amqp.Symbol;
18 import hunt.proton.amqp.UnsignedInteger;
19 import hunt.proton.amqp.UnsignedLong;
20 import hunt.proton.amqp.transport.DeliveryState;
21 import hunt.proton.amqp.transport.Disposition;
22 import hunt.proton.amqp.transport.Role;
23 import hunt.proton.codec.AbstractDescribedType;
24 import hunt.proton.codec.DecodeException;
25 import hunt.proton.codec.Decoder;
26 import hunt.proton.codec.DescribedTypeConstructor;
27 import hunt.proton.codec.EncoderImpl;
28 import std.concurrency : initOnce;
29 import hunt.Boolean;
30 import hunt.logging;
31 
32 class DispositionWrapper : AbstractList!Object
33 {
34 
35     private Disposition _disposition;
36 
37     this(Disposition disposition)
38     {
39         _disposition = disposition;
40     }
41 
42     override
43     public Object get(int index)
44     {
45 
46         switch(index)
47         {
48             case 0:
49             return new Boolean( _disposition.getRole().getValue());
50             case 1:
51             return _disposition.getFirst();
52             case 2:
53             return _disposition.getLast();
54             case 3:
55             return _disposition.getSettled();
56             case 4:
57             return  cast(Object)(_disposition.getState());
58             case 5:
59             return _disposition.getBatchable();
60             default:
61             return null;
62         }
63 
64         // throw new IllegalStateException("Unknown index " ~ index);
65 
66     }
67 
68     override
69     public int size()
70     {
71         return _disposition.getBatchable().booleanValue()
72         ? 6
73         : _disposition.getState() !is null
74         ? 5
75         : _disposition.getSettled().booleanValue()
76         ? 4
77         : _disposition.getLast() !is null
78         ? 3
79         : 2;
80 
81     }
82 }
83 
84 class DispositionType : AbstractDescribedType!(Disposition,List!Object) , DescribedTypeConstructor!(Disposition)
85 {
86     //private static Object[] DESCRIPTORS =
87     //{
88     //    UnsignedLong.valueOf(0x0000000000000015L), Symbol.valueOf("amqp:disposition:list"),
89     //};
90     //
91     //private static UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000015L);
92 
93     static Object[]  DESCRIPTORS() {
94         __gshared Object[]  inst;
95         return initOnce!inst([UnsignedLong.valueOf(0x0000000000000015L), Symbol.valueOf("amqp:disposition:list")]);
96     }
97 
98          static UnsignedLong  DESCRIPTOR() {
99              __gshared UnsignedLong  inst;
100              return initOnce!inst(UnsignedLong.valueOf(0x0000000000000015L));
101          }
102 
103     this(EncoderImpl encoder)
104     {
105         super(encoder);
106     }
107 
108     override
109     public UnsignedLong getDescriptor()
110     {
111         return DESCRIPTOR;
112     }
113 
114     override
115     protected List!Object wrap(Disposition val)
116     {
117         return new DispositionWrapper(val);
118     }
119 
120 
121 
122 
123         public Disposition newInstance(Object described)
124         {
125             List!Object l = cast(List!Object) described;
126 
127             Disposition o = new Disposition();
128 
129             if(l.isEmpty())
130             {
131                // throw new DecodeException("The first field cannot be omitted");
132                 logError("The first field cannot be omitted");
133                 return null;
134             }
135 
136             switch(6 - l.size())
137             {
138 
139                 case 0:
140                     Boolean batchable = cast(Boolean) l.get(5);
141                     o.setBatchable(batchable is null ? null : batchable);
142                     goto case;
143                 case 1:
144                     o.setState( cast(DeliveryState) l.get( 4 ) );
145                     goto case;
146                 case 2:
147                     Boolean settled = cast(Boolean) l.get(3);
148                     o.setSettled(settled is null ? null : settled);
149                     goto case;
150                 case 3:
151                     o.setLast( cast(UnsignedInteger) l.get( 2 ) );
152                     goto case;
153                 case 4:
154                     o.setFirst( cast(UnsignedInteger) l.get( 1 ) );
155                     goto case;
156                 case 5:
157                     Boolean tmp =  cast(Boolean) l.get( 0 );
158                     o.setRole( tmp.booleanValue() ? Role.RECEIVER : Role.SENDER );
159                     break;
160                 default:
161                     break;
162             }
163 
164 
165             return o;
166         }
167 
168         public TypeInfo getTypeClass()
169         {
170             return typeid(Disposition);
171         }
172 
173 
174 
175 
176     public static void register(Decoder decoder, EncoderImpl encoder)
177     {
178         DispositionType type = new DispositionType(encoder);
179         foreach(Object descriptor ; DESCRIPTORS)
180         {
181             decoder.registerDynamic(descriptor, type);
182         }
183         encoder.register(type);
184     }
185 
186 
187 }