1 /**
2 * Copyright © DiamondMVC 2019
3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module diamond.controllers.rest.parser;
7 
8 import diamond.core.apptype;
9 
10 static if (isWeb)
11 {
12   import std..string : strip;
13   import std.array : array, split;
14   import std.algorithm : filter, map;
15 
16   import diamond.controllers.rest.routetype;
17   import diamond.controllers.rest.routedatatype;
18   import diamond.controllers.rest.routepart;
19   import diamond.errors;
20 
21   package (diamond.controllers):
22 
23   /**
24   * Parses a special route.
25   * Params:
26   *   route = The route to parse.
27   * Returns:
28   *   The parts of the route.
29   */
30   RoutePart[] parseRoute(string route)
31   {
32     if (!route || !route.strip().length) return [];
33 
34     if (route[0] == '/')
35     {
36       route = route[1 .. $];
37     }
38 
39     if (route[$-1] == '/')
40     {
41       route = route[0 .. $-1];
42     }
43 
44     auto routeData = route
45       .split("/")
46       .map!(r => r.strip())
47       .filter!(r => r.length)
48       .array;
49 
50     RoutePart[] parts;
51 
52     foreach (i; 0 .. routeData.length)
53     {
54       auto data = routeData[i];
55       auto part = new RoutePart;
56 
57       if (i == 0)
58       {
59         part.routeType = RouteType.action;
60         part.identifier = data;
61       }
62       else if (data == "*")
63       {
64         part.routeType = RouteType.wildcard;
65       }
66       else if (data[0] == '{' && data[$-1] == '}')
67       {
68         auto typeData = data[1 .. $-1].split(":");
69 
70         part.type = cast(RouteDataType)typeData[0];
71 
72         if (typeData.length == 1)
73         {
74           part.routeType = RouteType.type;
75         }
76         else if (typeData.length == 2)
77         {
78           part.routeType = RouteType.typeIdentifier;
79           part.identifier = typeData[1];
80         }
81         else
82         {
83           throw new RouteException("Invalid type identifier for route.");
84         }
85       }
86       else
87       {
88         part.identifier = data;
89         part.routeType = RouteType.identifier;
90       }
91 
92       parts ~= part;
93     }
94 
95     return parts;
96   }
97 }