1 /**
2  * Copyright: Copyright Jason White, 2016
3  * License:   MIT
4  * Authors:   Jason White
5  */
6 module button.deps;
7 
8 import button.resource;
9 
10 /**
11  * Format for dependencies received from a task over a pipe.
12  */
13 align(4) struct Dependency
14 {
15     /**
16      * Status of the resource.
17      *
18      * Can be:
19      *  0: Status is unknown.
20      *  1: Resource does not exist.
21      *  2: The resource is a file.
22      *  3: The resource is a directory.
23      */
24     uint status;
25 
26     /**
27      * SHA-256 checksum of the contents of the resource. If unknown or not
28      * computed, this should be set to 0. In such a case, the parent build
29      * system will compute the value when needed.
30      *
31      * For files, this is the checksum of the file contents. For directories,
32      * this is the checksum of the paths in the sorted directory listing.
33      */
34     ubyte[32] checksum;
35 
36     /**
37      * Length of the name.
38      */
39     uint length;
40 
41     /**
42      * Name of the resource that can be used to lookup the data. Length is given
43      * by the length member.
44      *
45      * This is usually a file or directory path. The path does not need to be
46      * normalized. The path is assumed to be relative to the associated task's
47      * working directory.
48      */
49     char[0] name;
50 }
51 
52 unittest
53 {
54     static assert(Dependency.sizeof == 40);
55 }
56 
57 /**
58  * Range of resources received from a child process.
59  */
60 struct Deps
61 {
62     private
63     {
64         immutable(void)[] buf;
65 
66         Resource _current;
67         bool _empty;
68     }
69 
70     this(immutable(void)[] buf)
71     {
72         this.buf = buf;
73         popFront();
74     }
75 
76     Resource front() inout
77     {
78         return _current;
79     }
80 
81     bool empty() const pure nothrow
82     {
83         return _empty;
84     }
85 
86     void popFront()
87     {
88         import std.datetime : SysTime;
89 
90         if (buf.length == 0)
91         {
92             _empty = true;
93             return;
94         }
95 
96         if (buf.length < Dependency.sizeof)
97             throw new Exception("Received partial dependency buffer");
98 
99         auto dep = *cast(Dependency*)buf[0 .. Dependency.sizeof];
100 
101         immutable totalSize = Dependency.sizeof + dep.length;
102 
103         string name = cast(string)buf[Dependency.sizeof .. totalSize];
104 
105         _current = Resource(
106             name,
107             cast(Resource.Status)dep.status,
108             dep.checksum
109             );
110 
111         buf = buf[totalSize .. $];
112     }
113 }
114 
115 /**
116  * Convenience function for returning a range of resources.
117  */
118 Deps deps(immutable(void)[] buf)
119 {
120     return Deps(buf);
121 }