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