1 module osc.typetag;
2 
3 import std.algorithm;
4 import std.array;
5 import std.conv;
6 import std.datetime;
7 
8 
9 alias TypeTagString = string;
10 
11 
12 /// Type tag for each supported tags.
13 ///
14 enum TypeTag : char
15 {
16 	Integer = 'i',
17 	Float = 'f',
18 	String = 's',
19 	Blob = 'b',
20 	True = 'T',
21 	False = 'F',
22 	Null = 'N',
23 	Impulse = 'I',
24 	TimeTag = 't',
25 }
26 
27 
28 /// Constructs a TypeTag string using a list of types.
29 ///
30 TypeTagString build( T... )( )
31 {
32 	TypeTagString res;
33 
34 	foreach( t; T )
35 	{
36 		static if( is(t == int) )
37 			res = res.add!int;
38 		else static if( is(t == float) )
39 			res = res.add!float;
40 		else static if( is(t == string) )
41 			res = res.add!string;
42 		else static if( is(t == ubyte[]) )
43 			res = res.add!(ubyte[]);
44 		else static if( is(typeof(t) == typeof(null)) )
45 			res = res.addNull;
46 		else static if( is(typeof(t) == bool) )
47 			res = res.add!bool( t );
48 		else static if( is(typeof(t) == char) && t is 'I' )
49 			res = res.addImpulse;
50 		else static if( is(t == SysTime) )
51 			res = res.add!SysTime;
52 		else
53 			static assert( 0, "Invalid type." );
54 	}
55 
56 	return res;
57 }
58 
59 
60 /// Adds an integer type tag.
61 ///
62 TypeTagString add(T:int)(TypeTagString str)
63 {
64 	return str ~ TypeTag.Integer;
65 }
66 
67 /// Adds a float type tag.
68 ///
69 TypeTagString add(T:float)(TypeTagString str)
70 {
71 	return str ~ TypeTag.Float;
72 }
73 
74 /// Adds a string type tag.
75 ///
76 TypeTagString add(T:string)(TypeTagString str)
77 {
78 	return str ~ TypeTag.String;
79 }
80 
81 /// Adds a blob type tag.
82 ///
83 TypeTagString add(T:ubyte[])(TypeTagString str)
84 {
85 	return str ~ TypeTag.Blob;
86 }
87 
88 /// Adds a bool type tag.
89 ///
90 TypeTagString add(T:bool)(TypeTagString str, T v)
91 {
92 	if( v )
93 		return str ~ TypeTag.True;
94 	else
95 		return str ~ TypeTag.False;
96 }
97 
98 /// Adds a null type tag.
99 ///
100 TypeTagString addNull(TypeTagString str)
101 {
102 	return str ~ TypeTag.Null;
103 }
104 
105 /// Adds an impulse type tag.
106 ///
107 TypeTagString addImpulse(TypeTagString str)
108 {
109 	return str ~ TypeTag.Impulse;
110 }
111 
112 /// Adds a timetag type tag.
113 ///
114 TypeTagString add(T:SysTime)(TypeTagString str)
115 {
116 	return str ~ TypeTag.TimeTag;
117 }
118 
119 
120 
121 unittest
122 {
123 	TypeTagString str;
124 
125 	str = str.add!int
126 		.add!float
127 		.add!string
128 		.add!(ubyte[])
129 		.add!bool(true)
130 		.add!bool(false)
131 		.addNull
132 		.addImpulse
133 		.add!SysTime;
134 	
135 	assert( str == "ifsbTFNIt" );
136 }
137 
138 unittest
139 {
140 	TypeTagString str = build!( int, float, string, ubyte[], true, false, null, 
141 		'I', SysTime)();
142 
143 	assert( str == "ifsbTFNIt" );
144 }