1 /******************************************************************************
2 
3     Collection of common utilities built on top of (de)serializer
4 
5     Copyright:
6         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
7         All rights reserved.
8 
9     License:
10         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
11         Alternatively, this file may be distributed under the terms of the Tango
12         3-Clause BSD License (see LICENSE_BSD.txt for details).
13 
14 *******************************************************************************/
15 
16 module ocean.util.serialize.contiguous.Util;
17 
18 
19 import ocean.util.serialize.contiguous.Contiguous;
20 import ocean.util.serialize.contiguous.Serializer;
21 import ocean.util.serialize.contiguous.Deserializer;
22 
23 import ocean.meta.types.Qualifiers;
24 import ocean.core.Test;
25 
26 /*******************************************************************************
27 
28     Copies struct data to other chunk and adjusts all internal pointers
29     to reference new buffer.
30 
31     Params:
32         src = source struct (must be already contiguous)
33         dst = target struct chunk to copy data to. Will grow if current
34             length is smaller than src.data.length
35 
36     Returns:
37         `dst` by value
38 
39     Throws:
40         DeserializationException if src is not well-formed
41 
42 /******************************************************************************/
43 
44 public Contiguous!(S) copy(S) ( in Contiguous!(S) src, ref Contiguous!(S) dst )
45 {
46     // We have to cast away `const` here since the `ptr`
47     // method does not support it.  We are not modifying
48     // anything so we do not break the `in` promise of
49     // the function signature.
50     if ((cast(Contiguous!(S)) src).ptr is null)
51     {
52         dst.reset();
53     }
54     else
55     {
56         Deserializer.deserialize(src.data, dst);
57     }
58 
59     return dst;
60 }
61 
62 /*******************************************************************************
63 
64     Deep copies any struct to its contiguous representation. Effectively does
65     serialization and deserialization in one go.
66 
67     Params:
68         src = any struct instance
69         dst = contiguous struct to be filled with same values as src
70 
71     Returns:
72         `dst` by value
73 
74 *******************************************************************************/
75 
76 public Contiguous!(S) copy(S) ( ref const S src, ref Contiguous!(S) dst )
77 {
78     Serializer.serialize(src, dst.data);
79     dst = Deserializer.deserialize!(S)(dst.data);
80     return dst;
81 }
82 
83 unittest
84 {
85     struct Test
86     {
87         int[] arr;
88     }
89 
90     Test t; t.arr = [ 1, 2, 3 ];
91 
92     Contiguous!(Test) one, two;
93 
94     copy(t, one);
95 
96     test!("==")(one.ptr.arr, t.arr);
97     one.enforceIntegrity();
98 
99     copy(one, two);
100 
101     test!("==")(two.ptr.arr, t.arr);
102     two.enforceIntegrity();
103 
104     one.reset();
105     test!("is")(one.ptr, null);
106     test!("!is")(two.ptr, null);
107 
108     copy(one, two);
109     test!("is")(two.ptr, null);
110 }
111 
112 unittest
113 {
114     struct Test
115     {
116         int[] arr;
117     }
118 
119     const(Test) t = Test([ 1, 2, 3 ]);
120     Contiguous!(Test) dst;
121     copy(t, dst);
122     test!("==")(dst.ptr.arr, t.arr);
123 }
124 
125 /*******************************************************************************
126 
127     Simple wrapper on top of (de)serializer which allows to deep copy
128     a given struct by storing all indirections in contiguous buffer. Most
129     commonly used in tests - performance-critical applications should store
130     `Contiguous!(S)` instead and copy it as it is much faster.
131 
132     Params:
133         dst = resizable buffer used to serialize `src`
134         src = struct to copy
135 
136     Returns:
137         new struct instance stored in `dst` cast to S
138 
139 *******************************************************************************/
140 
141 public S deepCopy (S) (  ref S src, ref void[] dst )
142 {
143     Serializer.serialize(src, dst);
144     return *Deserializer.deserialize!(S)(dst).ptr;
145 }
146 
147 /*******************************************************************************
148 
149     Ditto, but allocates new buffer each time called
150 
151 *******************************************************************************/
152 
153 public S deepCopy (S) ( ref S src )
154 {
155     void[] empty;
156     return deepCopy(src, empty);
157 }
158 
159 ///
160 unittest
161 {
162     struct Test
163     {
164         int[] arr;
165     }
166 
167     auto s1 = Test([ 1, 2, 3 ]);
168     auto s2 = deepCopy(s1);
169 
170     test!("==")(s1.arr, s2.arr);
171     test!("!is")(s1.arr.ptr, s2.arr.ptr);
172 }