1 // Copyright © 2017-2021 Rémi Thebault
2 /// bindings to wayland-util.h
3 module wayland.native.util;
4 
5 // Wayland util copyright:
6 /*
7  * Copyright © 2008 Kristian Høgsberg
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice (including the
18  * next paragraph) shall be included in all copies or substantial
19  * portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  */
30 
31 import core.stdc.stdarg : va_list;
32 
33 extern(C) nothrow
34 {
35     /**
36     * Protocol message signature
37     *
38     * A wl_message describes the signature of an actual protocol message, such as a
39     * request or event, that adheres to the Wayland protocol wire format. The
40     * protocol implementation uses a wl_message within its demarshal machinery for
41     * decoding messages between a compositor and its clients. In a sense, a
42     * wl_message is to a protocol message like a class is to an object.
43     *
44     * The `name` of a wl_message is the name of the corresponding protocol message.
45     * The `signature` is an ordered list of symbols representing the data types
46     * of message arguments and, optionally, a protocol version and indicators for
47     * nullability. A leading integer in the `signature` indicates the _since_
48     * version of the protocol message. A `?` preceding a data type symbol indicates
49     * that the following argument type is nullable. When no arguments accompany a
50     * message, `signature` is an empty string.
51     *
52     * * `i`: int
53     * * `u`: uint
54     * * `f`: fixed
55     * * `s`: string
56     * * `o`: object
57     * * `n`: new_id
58     * * `a`: array
59     * * `h`: fd
60     * * `?`: following argument is nullable
61     *
62     * While demarshaling primitive arguments is straightforward, when demarshaling
63     * messages containing `object` or `new_id` arguments, the protocol
64     * implementation often must determine the type of the object. The `types` of a
65     * wl_message is an array of wl_interface references that correspond to `o` and
66     * `n` arguments in `signature`, with `NULL` placeholders for arguments with
67     * non-object types.
68     *
69     * Consider the protocol event wl_display `delete_id` that has a single `uint`
70     * argument. The wl_message is:
71     *
72     * \code
73     * { "delete_id", "u", [NULL] }
74     * \endcode
75     *
76     * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the
77     * argument `types` is `[NULL]`, indicating that the `uint` argument has no
78     * corresponding wl_interface since it is a primitive argument.
79     *
80     * In contrast, consider a `wl_foo` interface supporting protocol request `bar`
81     * that has existed since version 2, and has two arguments: a `uint` and an
82     * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message`
83     * might be:
84     *
85     * \code
86     * { "bar", "2u?o", [NULL, &wl_baz_interface] }
87     * \endcode
88     *
89     * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice
90     * how the `2` indicates the protocol version, the `u` indicates the first
91     * argument type is `uint`, and the `?o` indicates that the second argument
92     * is an object that may be `NULL`. Lastly, the argument `types` array indicates
93     * that no wl_interface corresponds to the first argument, while the type
94     * `wl_baz_interface` corresponds to the second argument.
95     *
96     * \sa wl_argument
97     * \sa wl_interface
98     * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Wire-Format">Wire Format</a>
99     */
100     struct wl_message
101     {
102         /** Message name */
103         const(char)* name;
104         /** Message signature */
105         const(char)* signature;
106         /** Object argument interfaces */
107         const(wl_interface*)* types;
108     }
109 
110     /**
111     * Protocol object interface
112     *
113     * A wl_interface describes the API of a protocol object defined in the Wayland
114     * protocol specification. The protocol implementation uses a wl_interface
115     * within its marshalling machinery for encoding client requests.
116     *
117     * The `name` of a wl_interface is the name of the corresponding protocol
118     * interface, and `version` represents the version of the interface. The members
119     * `method_count` and `event_count` represent the number of `methods` (requests)
120     * and `events` in the respective wl_message members.
121     *
122     * For example, consider a protocol interface `foo`, marked as version `1`, with
123     * two requests and one event.
124     *
125     * \code
126     * <interface name="foo" version="1">
127     *   <request name="a"></request>
128     *   <request name="b"></request>
129     *   <event name="c"></event>
130     * </interface>
131     * \endcode
132     *
133     * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface
134     * for `foo` might be:
135     *
136     * \code
137     * struct wl_interface foo_interface = {
138     *         "foo", 1,
139     *         2, foo_requests,
140     *         1, foo_events
141     * };
142     * \endcode
143     *
144     * \note The server side of the protocol may define interface <em>implementation
145     *       types</em> that incorporate the term `interface` in their name. Take
146     *       care to not confuse these server-side `struct`s with a wl_interface
147     *       variable whose name also ends in `interface`. For example, while the
148     *       server may define a type `struct wl_foo_interface`, the client may
149     *       define a `struct wl_interface wl_foo_interface`.
150     *
151     * \sa wl_message
152     * \sa wl_proxy
153     * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Interfaces">Interfaces</a>
154     * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning">Versioning</a>
155     */
156     struct wl_interface
157     {
158         /** Interface name */
159         const(char)* name;
160         /** Interface version */
161         int version_;
162         /** Number of methods (requests) */
163         int method_count;
164         /** Method (request) signatures */
165         const(wl_message)* methods;
166         /** Number of events */
167         int event_count;
168         /** Event signatures */
169         const(wl_message)* events;
170     }
171 
172     /** \class wl_list
173     *
174     * \brief Doubly-linked list
175     *
176     * On its own, an instance of `struct wl_list` represents the sentinel head of
177     * a doubly-linked list, and must be initialized using wl_list_init().
178     * When empty, the list head's `next` and `prev` members point to the list head
179     * itself, otherwise `next` references the first element in the list, and `prev`
180     * refers to the last element in the list.
181     *
182     * Use the `struct wl_list` type to represent both the list head and the links
183     * between elements within the list. Use wl_list_empty() to determine if the
184     * list is empty in O(1).
185     *
186     * All elements in the list must be of the same type. The element type must have
187     * a `struct wl_list` member, often named `link` by convention. Prior to
188     * insertion, there is no need to initialize an element's `link` - invoking
189     * wl_list_init() on an individual list element's `struct wl_list` member is
190     * unnecessary if the very next operation is wl_list_insert(). However, a
191     * common idiom is to initialize an element's `link` prior to removal - ensure
192     * safety by invoking wl_list_init() before wl_list_remove().
193     *
194     * Consider a list reference `struct wl_list foo_list`, an element type as
195     * `struct element`, and an element's link member as `struct wl_list link`.
196     *
197     * The following code initializes a list and adds three elements to it.
198     *
199     * \code
200     * struct wl_list foo_list;
201     *
202     * struct element {
203     *         int foo;
204     *         struct wl_list link;
205     * };
206     * struct element e1, e2, e3;
207     *
208     * wl_list_init(&foo_list);
209     * wl_list_insert(&foo_list, &e1.link);   // e1 is the first element
210     * wl_list_insert(&foo_list, &e2.link);   // e2 is now the first element
211     * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2
212     * \endcode
213     *
214     * The list now looks like <em>[e2, e3, e1]</em>.
215     *
216     * The `wl_list` API provides some iterator macros. For example, to iterate
217     * a list in ascending order:
218     *
219     * \code
220     * struct element *e;
221     * wl_list_for_each(e, foo_list, link) {
222     *         do_something_with_element(e);
223     * }
224     * \endcode
225     *
226     * See the documentation of each iterator for details.
227     * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h
228     */
229     struct wl_list
230     {
231         /** Previous list element */
232         wl_list *prev;
233         /** Next list element */
234         wl_list *next;
235     }
236 }
237 /**
238  * Retrieves a pointer to a containing struct, given a member name.
239  *
240  * This macro allows "conversion" from a pointer to a member to its containing
241  * struct. This is useful if you have a contained item like a wl_list,
242  * wl_listener, or wl_signal, provided via a callback or other means, and would
243  * like to retrieve the struct that contains it.
244  *
245  * To demonstrate, the following example retrieves a pointer to
246  * `example_container` given only its `destroy_listener` member:
247  *
248  * \code
249  * struct example_container {
250  *         struct wl_listener destroy_listener;
251  *         // other members...
252  * };
253  *
254  * void example_container_destroy(struct wl_listener *listener, void *data)
255  * {
256  *         struct example_container *ctr;
257  *
258  *         ctr = wl_container_of(listener, ctr, destroy_listener);
259  *         // destroy ctr...
260  * }
261  * \endcode
262  *
263  * \note `sample` need not be a valid pointer. A null or uninitialised pointer
264  *       is sufficient.
265  *
266  * \param ptr Valid pointer to the contained member
267  * \param sample Pointer to a struct whose type contains \p ptr
268  * \param member Named location of \p ptr within the \p sample type
269  *
270  * \return The container for the specified pointer
271  */
272 template wl_container_of(alias member)
273 {
274     static ParentOf!member* wl_container_of(T)(T* ptr)
275     {
276         return cast(ParentOf!member*)(cast(ptrdiff_t)(ptr)-member.offsetof);
277     }
278 }
279 
280 ///
281 unittest {
282 
283     struct S {
284         string foo;
285         int bar;
286     }
287 
288     S s;
289     assert(wl_container_of!(S.bar)(&s.bar) == &s);
290 }
291 
292 /// Returns a range that iterates over a wl_list.
293 /// The member alias and the passed list is the wl_list member in a container
294 /// struct, and the front type of the range is the container itself.
295 template wl_range(alias member)
296 {
297     static WlListRange!member wl_range(wl_list *head)
298     {
299         return WlListRange!member(head);
300     }
301 }
302 
303 ///
304 unittest
305 {
306     struct Item
307     {
308         int num;
309         wl_list link;
310 
311         this(int num) { this.num = num; }
312     }
313     auto i1 = Item(1);
314     auto i2 = Item(2);
315     auto i3 = Item(3);
316 
317     wl_list lst;
318     wl_list_init(&lst);
319     wl_list_insert(&lst, &i1.link);
320     wl_list_insert(&lst, &i2.link);
321     wl_list_insert(&i2.link, &i3.link);
322 
323     int[] forw_arr;
324     foreach(it; wl_range!(Item.link)(&lst)) {
325         forw_arr ~= it.num;
326     }
327     assert(forw_arr == [2, 3, 1]);
328 
329     int[] back_arr;
330     foreach_reverse(it; wl_range!(Item.link)(&lst)) {
331         back_arr ~= it.num;
332     }
333     assert(back_arr == [1, 3, 2]);
334 }
335 
336 
337 
338 // TODO: check if the following are needed given the wl_range functions
339 // /**
340 //  * Iterates over a list.
341 //  *
342 //  * This macro expresses a for-each iterator for wl_list. Given a list and
343 //  * wl_list link member name (often named `link` by convention), this macro
344 //  * assigns each element in the list to \p pos, which can then be referenced in
345 //  * a trailing code block. For example, given a wl_list of `struct message`
346 //  * elements:
347 //  *
348 //  * \code
349 //  * struct message {
350 //  *         char *contents;
351 //  *         wl_list link;
352 //  * };
353 //  *
354 //  * struct wl_list *message_list;
355 //  * // Assume message_list now "contains" many messages
356 //  *
357 //  * struct message *m;
358 //  * wl_list_for_each(m, message_list, link) {
359 //  *         do_something_with_message(m);
360 //  * }
361 //  * \endcode
362 //  *
363 //  * \param pos Cursor that each list element will be assigned to
364 //  * \param head Head of the list to iterate over
365 //  * \param member Name of the link member within the element struct
366 //  *
367 //  * \relates wl_list
368 //  */
369 // #define wl_list_for_each(pos, head, member)				\
370 // 	for (pos = wl_container_of((head)->next, pos, member);	\
371 // 	     &pos->member != (head);					\
372 // 	     pos = wl_container_of(pos->member.next, pos, member))
373 //
374 // /**
375 //  * Iterates over a list, safe against removal of the list element.
376 //  *
377 //  * \note Only removal of the current element, \p pos, is safe. Removing
378 //  *       any other element during traversal may lead to a loop malfunction.
379 //  *
380 //  * \sa wl_list_for_each()
381 //  *
382 //  * \param pos Cursor that each list element will be assigned to
383 //  * \param tmp Temporary pointer of the same type as \p pos
384 //  * \param head Head of the list to iterate over
385 //  * \param member Name of the link member within the element struct
386 //  *
387 //  * \relates wl_list
388 //  */
389 // #define wl_list_for_each_safe(pos, tmp, head, member)			\
390 // 	for (pos = wl_container_of((head)->next, pos, member),		\
391 // 	     tmp = wl_container_of((pos)->member.next, tmp, member);	\
392 // 	     &pos->member != (head);					\
393 // 	     pos = tmp,							\
394 // 	     tmp = wl_container_of(pos->member.next, tmp, member))
395 //
396 // /**
397 //  * Iterates backwards over a list.
398 //  *
399 //  * \sa wl_list_for_each()
400 //  *
401 //  * \param pos Cursor that each list element will be assigned to
402 //  * \param head Head of the list to iterate over
403 //  * \param member Name of the link member within the element struct
404 //  *
405 //  * \relates wl_list
406 //  */
407 // #define wl_list_for_each_reverse(pos, head, member)			\
408 // 	for (pos = wl_container_of((head)->prev, pos, member);	\
409 // 	     &pos->member != (head);					\
410 // 	     pos = wl_container_of(pos->member.prev, pos, member))
411 //
412 // /**
413 //  * Iterates backwards over a list, safe against removal of the list element.
414 //  *
415 //  * \note Only removal of the current element, \p pos, is safe. Removing
416 //  *       any other element during traversal may lead to a loop malfunction.
417 //  *
418 //  * \sa wl_list_for_each()
419 //  *
420 //  * \param pos Cursor that each list element will be assigned to
421 //  * \param tmp Temporary pointer of the same type as \p pos
422 //  * \param head Head of the list to iterate over
423 //  * \param member Name of the link member within the element struct
424 //  *
425 //  * \relates wl_list
426 //  */
427 // #define wl_list_for_each_reverse_safe(pos, tmp, head, member)		\
428 // 	for (pos = wl_container_of((head)->prev, pos, member),	\
429 // 	     tmp = wl_container_of((pos)->member.prev, tmp, member);	\
430 // 	     &pos->member != (head);					\
431 // 	     pos = tmp,							\
432 // 	     tmp = wl_container_of(pos->member.prev, tmp, member))
433 
434 
435 
436 /**
437  * \class wl_array
438  *
439  * Dynamic array
440  *
441  * A wl_array is a dynamic array that can only grow until released. It is
442  * intended for relatively small allocations whose size is variable or not known
443  * in advance. While construction of a wl_array does not require all elements to
444  * be of the same size, wl_array_for_each() does require all elements to have
445  * the same type and size.
446  *
447  */
448 extern(C)
449 struct wl_array
450 {
451 	/** Array size */
452 	size_t size;
453 	/** Allocated space */
454 	size_t alloc;
455 	/** Array data */
456 	void *data;
457 }
458 
459 
460 
461 /// Returns a range that iterates over a wl_array.
462 template wl_range(T)
463 {
464     static WlArrayRange!T wl_range(wl_array *arr)
465     {
466         return WlArrayRange!T(arr);
467     }
468 }
469 
470 ///
471 unittest
472 {
473     wl_array arr;
474     wl_array_init(&arr);
475 
476     foreach(i; 0..1342) {
477         int *ptr = cast(int*)wl_array_add(&arr, int.sizeof);
478         *ptr = i*12 - 15;
479 
480     }
481 
482     int ind=0;
483     foreach(pi; wl_range!(int)(&arr)) {
484         assert(*pi == ind++*12-15);
485     }
486     assert(ind==1342);
487 
488     wl_array_release(&arr);
489 }
490 
491 
492 
493 // TODO: check if the following are needed given the wl_range functions
494 
495 // /**
496 //  * Iterates over an array.
497 //  *
498 //  * This macro expresses a for-each iterator for wl_array. It assigns each
499 //  * element in the array to \p pos, which can then be referenced in a trailing
500 //  * code block. \p pos must be a pointer to the array element type, and all
501 //  * array elements must be of the same type and size.
502 //  *
503 //  * \param pos Cursor that each array element will be assigned to
504 //  * \param array Array to iterate over
505 //  *
506 //  * \relates wl_array
507 //  * \sa wl_list_for_each()
508 //  */
509 // #define wl_array_for_each(pos, array)					\
510 //  	for (pos = (array)->data;					\
511 //  	     (const char *) pos < ((const char *) (array)->data + (array)->size); \
512 //  	     (pos)++)
513 
514 
515 /**
516  * Fixed-point number
517  *
518  * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits
519  * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t`
520  * as an opaque struct with methods that facilitate conversion to and from
521  * `double` and `int` types.
522  */
523 alias wl_fixed_t = uint;
524 
525 
526 /**
527  * Converts a fixed-point number to a floating-point number.
528  *
529  * \param f Fixed-point number to convert
530  *
531  * \return Floating-point representation of the fixed-point argument
532  */
533 double wl_fixed_to_double (wl_fixed_t f)
534 {
535     union di {
536         double d;
537         long i;
538     }
539     di u;
540 
541     u.i = ((1023L + 44L) << 52) + (1L << 51) + f;
542 
543     return u.d - (3L << 43);
544 }
545 
546 
547 /**
548  * Converts a floating-point number to a fixed-point number.
549  *
550  * \param d Floating-point number to convert
551  *
552  * \return Fixed-point representation of the floating-point argument
553  */
554 wl_fixed_t wl_fixed_from_double(double d)
555 {
556     union di {
557         double d;
558         long i;
559     }
560     di u;
561 
562     u.d = d + (3L << (51 - 8));
563 
564     return cast(wl_fixed_t)u.i;
565 }
566 
567 
568 
569 /**
570  * Converts a fixed-point number to an integer.
571  *
572  * \param f Fixed-point number to convert
573  *
574  * \return Integer component of the fixed-point argument
575  */
576 int wl_fixed_to_int(wl_fixed_t f)
577 {
578     return f / 256;
579 }
580 
581 /**
582  * Converts an integer to a fixed-point number.
583  *
584  * \param i Integer to convert
585  *
586  * \return Fixed-point representation of the integer argument
587  */
588 wl_fixed_t wl_fixed_from_int(int i)
589 {
590     return i * 256;
591 }
592 
593 // wl_object resides in wayland-server.h, but referenced in wl_argument.
594 ///
595 extern(C)
596 struct wl_object;
597 
598 /**
599  * Protocol message argument data types
600  *
601  * This union represents all of the argument types in the Wayland protocol wire
602  * format. The protocol implementation uses wl_argument within its marshalling
603  * machinery for dispatching messages between a client and a compositor.
604  *
605  * \sa wl_message
606  * \sa wl_interface
607  * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-wire-Format">Wire Format</a>
608  */
609 extern(C)
610 union wl_argument
611 {
612 	int i;           /**< `int`    */
613 	uint u;          /**< `uint`   */
614 	wl_fixed_t f;        /**< `fixed`  */
615 	const(char) *s;       /**< `string` */
616 	wl_object *o;        /**< `object` */
617 	uint n;          /**< `new_id` */
618 	wl_array *a;         /**< `array`  */
619 	int h;           /**< `fd`     */
620 }
621 
622 extern(C) nothrow
623 {
624     /**
625     * Dispatcher function type alias
626     *
627     * A dispatcher is a function that handles the emitting of callbacks in client
628     * code. For programs directly using the C library, this is done by using
629     * libffi to call function pointers. When binding to languages other than C,
630     * dispatchers provide a way to abstract the function calling process to be
631     * friendlier to other function calling systems.
632     *
633     * A dispatcher takes five arguments: The first is the dispatcher-specific
634     * implementation associated with the target object. The second is the object
635     * upon which the callback is being invoked (either wl_proxy or wl_resource).
636     * The third and fourth arguments are the opcode and the wl_message
637     * corresponding to the callback. The final argument is an array of arguments
638     * received from the other process via the wire protocol.
639     *
640     * \param "const void *" Dispatcher-specific implementation data
641     * \param "void *" Callback invocation target (wl_proxy or `wl_resource`)
642     * \param uint32_t Callback opcode
643     * \param "const struct wl_message *" Callback message signature
644     * \param "union wl_argument *" Array of received arguments
645     *
646     * \return 0 on success, or -1 on failure
647     */
648     alias wl_dispatcher_func_t = int function (
649                 const(void)* impl,
650                 void* target,
651                 uint opcode,
652                 const(wl_message)* msg,
653                 wl_argument* args);
654 
655     /**
656     * Log function type alias
657     *
658     * The C implementation of the Wayland protocol abstracts the details of
659     * logging. Users may customize the logging behavior, with a function conforming
660     * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and
661     * `wl_log_set_handler_server`.
662     *
663     * A `wl_log_func_t` must conform to the expectations of `vprintf`, and
664     * expects two arguments: a string to write and a corresponding variable
665     * argument list. While the string to write may contain format specifiers and
666     * use values in the variable argument list, the behavior of any `wl_log_func_t`
667     * depends on the implementation.
668     *
669     * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which
670     *       is a specific server-side logger for requests and events.
671     *
672     * \param "const char *" String to write to the log, containing optional format
673     *                       specifiers
674     * \param "va_list" Variable argument list
675     *
676     * \sa wl_log_set_handler_client
677     * \sa wl_log_set_handler_server
678     */
679     alias wl_log_func_t = void function(const(char)*, va_list);
680 
681 }
682 /**
683  * Return value of an iterator function
684  *
685  * \sa wl_client_for_each_resource_iterator_func_t
686  * \sa wl_client_for_each_resource
687  */
688 extern(C) enum wl_iterator_result
689 {
690 	/** Stop the iteration */
691 	WL_ITERATOR_STOP,
692 	/** Continue the iteration */
693 	WL_ITERATOR_CONTINUE
694 }
695 
696 
697 version(WlDynamic)
698 {
699     extern(C) nothrow
700     {
701         alias da_wl_list_init = void function (wl_list* list);
702 
703         alias da_wl_list_insert = void function (wl_list* list, wl_list* elm);
704 
705         alias da_wl_list_remove = void function (wl_list* elm);
706 
707         alias da_wl_list_length = int function (const(wl_list)* list);
708 
709         alias da_wl_list_empty = int function (const(wl_list)* list);
710 
711         alias da_wl_list_insert_list = void function (wl_list* list, wl_list* other);
712 
713         alias da_wl_array_init = void function (wl_array* array);
714 
715         alias da_wl_array_release = void function (wl_array* array);
716 
717         alias da_wl_array_add = void* function (wl_array* array, size_t size);
718 
719         alias da_wl_array_copy = int function (wl_array* array, wl_array* source);
720     }
721 
722     __gshared
723     {
724         da_wl_list_init wl_list_init;
725 
726         da_wl_list_insert wl_list_insert;
727 
728         da_wl_list_remove wl_list_remove;
729 
730         da_wl_list_length wl_list_length;
731 
732         da_wl_list_empty wl_list_empty;
733 
734         da_wl_list_insert_list wl_list_insert_list;
735 
736         da_wl_array_init wl_array_init;
737 
738         da_wl_array_release wl_array_release;
739 
740         da_wl_array_add wl_array_add;
741 
742         da_wl_array_copy wl_array_copy;
743     }
744 }
745 
746 version(WlStatic)
747 {
748     extern(C) nothrow
749     {
750         void wl_list_init(wl_list* list);
751 
752         void wl_list_insert(wl_list* list, wl_list* elm);
753 
754         void wl_list_remove(wl_list* elm);
755 
756         int wl_list_length(const(wl_list)* list);
757 
758         int wl_list_empty(const(wl_list)* list);
759 
760         void wl_list_insert_list(wl_list* list, wl_list* other);
761 
762         void wl_array_init(wl_array* array);
763 
764         void wl_array_release(wl_array* array);
765 
766         void* wl_array_add(wl_array* array, size_t size);
767 
768         int wl_array_copy(wl_array* array, wl_array* source);
769     }
770 }
771 
772 
773 private {
774 
775     import std.range : isBidirectionalRange, isRandomAccessRange;
776 
777     template Id(alias a) { alias Id = a; }
778 
779     template ParentOf(alias member)
780     {
781         alias ParentOf = Id!(__traits(parent, member));
782     }
783 
784     struct WlListRange(alias member)
785     {
786         wl_list *head;
787         wl_list *fpos;
788         wl_list *bpos;
789 
790         alias ElType = ParentOf!member;
791 
792         this(wl_list *head)
793         {
794             this.head = head;
795             fpos = head.next;
796             bpos = head.prev;
797         }
798 
799         // input
800 
801         @property bool empty() const {
802             return fpos == head || bpos == head;
803         }
804 
805         @property ElType *front() {
806             return wl_container_of!member(fpos);
807         }
808 
809         void popFront() {
810             fpos = fpos.next;
811         }
812 
813         // forward
814 
815         @property WlListRange!member save() {
816             return this;
817         }
818 
819         // bidirectional
820 
821         @property ElType *back() {
822             return wl_container_of!member(bpos);
823         }
824 
825         void popBack() {
826             bpos = bpos.prev;
827         }
828     }
829 
830 
831     struct Item
832     {
833         int num;
834         wl_list link;
835 
836         this(int num) { this.num = num; }
837     }
838 
839     static assert(isBidirectionalRange!(WlListRange!(Item.link)));
840 
841 
842     struct WlArrayRange(T)
843     {
844         wl_array *arr;
845         size_t fpos;
846         size_t bpos;
847 
848         this (wl_array *arr)
849         {
850             assert(arr.size % T.sizeof == 0);
851             this.arr = arr;
852             fpos = 0;
853             bpos = arr.size / T.sizeof;
854         }
855 
856         // input
857 
858         @property bool empty() const {
859             return fpos == bpos;
860         }
861 
862         @property inout(T)* front() inout {
863             return cast(inout(T)*)(arr.data + fpos*T.sizeof);
864         }
865 
866         void popFront() {
867             ++fpos;
868         }
869 
870 
871         // forward
872 
873         @property WlArrayRange!T save() {
874             return this;
875         }
876 
877 
878         // bidirectional
879 
880         @property inout(T)* back() inout {
881             return cast(inout(T)*)(arr.data + bpos*T.sizeof);
882         }
883 
884         void popBack() {
885             --bpos;
886         }
887 
888 
889         // random access
890 
891         @property size_t length() const {
892             return bpos - fpos;
893         }
894 
895         inout(T)* opIndex(size_t n) inout {
896             return cast(inout(T)*)(arr.data + (fpos+n)*T.sizeof);
897         }
898 
899     }
900 
901     static assert(isRandomAccessRange!(WlArrayRange!int));
902 
903 }