2 This module contains compiler support for casting dynamic arrays
4 Copyright: Copyright Digital Mars 2000 - 2019.
5 License: Distributed under the
6 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 (See accompanying file LICENSE)
8 Source: $(DRUNTIMESRC core/internal/_array/_casting.d)
10 module core
.internal
.array
.casting
;
13 Used by `__ArrayCast` to emit a descriptive error message.
15 It is a template so it can be used by `__ArrayCast` in -betterC
16 builds. It is separate from `__ArrayCast` to minimize code
20 fromType = name of the type being cast from
21 fromSize = total size in bytes of the array being cast from
22 fromLength = length of array being cast from
23 toType = name of the type being cast to
24 toElemSize = element size of array being cast to
26 private void onArrayCastError()(string fromType
, size_t fromSize
, size_t fromLength
, string toType
, size_t toElemSize
) @trusted
28 import core
.internal
.string
: unsignedToTempString
;
29 import core
.memory
: pureMalloc
;
31 // convert discontiguous `msgComponents` to contiguous string on the C heap
32 enum msgLength
= 2048;
34 char* msg
= cast(char *)pureMalloc(msgLength
);
37 void add(const(char)[] m
)
39 import core
.stdc
.string
: memcpy
;
41 auto N
= msgLength
- 1 - index
;
44 // prevent superfluous and betterC-unfriendly checks via direct memcpy
45 memcpy(msg
+ index
, m
.ptr
, N
);
51 add("[]` of length ");
52 auto s
= unsignedToTempString(fromLength
);
54 add(" cannot be cast to `");
56 add("[]` as its length in bytes (");
57 s
= unsignedToTempString(fromSize
);
59 add(") is not a multiple of `");
62 s
= unsignedToTempString(toElemSize
);
65 msg
[index
] = '\0'; // null-termination
67 // first argument must evaluate to `false` at compile-time to maintain memory safety in release builds
68 assert(false, msg
[0 .. index
]);
72 The compiler lowers expressions of `cast(TTo[])TFrom[]` to
73 this implementation. Note that this does not detect alignment problems.
76 from = the array to reinterpret-cast
79 `from` reinterpreted as `TTo[]`
81 TTo
[] __ArrayCast(TFrom
, TTo
)(return scope TFrom
[] from
) @nogc pure @trusted
83 const fromSize
= from
.length
* TFrom
.sizeof
;
84 const toLength
= fromSize
/ TTo
.sizeof
;
86 if ((fromSize
% TTo
.sizeof
) != 0)
88 onArrayCastError(TFrom
.stringof
, fromSize
, from
.length
, TTo
.stringof
, TTo
.sizeof
);
96 auto a
= cast(Array
*)&from
;
97 a
.length
= toLength
; // jam new length
98 return *cast(TTo
[]*)a
;
101 @safe @nogc pure nothrow unittest
103 byte[int.sizeof
* 3] b
= cast(byte) 0xab;
107 i
= __ArrayCast
!(byte, int)(b
);
108 assert(i
.length
== 3);
110 assert(v
== cast(int) 0xabab_abab
);
112 s
= __ArrayCast
!(byte, short)(b
);
113 assert(s
.length
== 6);
115 assert(v
== cast(short) 0xabab);
117 s
= __ArrayCast
!(int, short)(i
);
118 assert(s
.length
== 6);
120 assert(v
== cast(short) 0xabab);
123 @system nothrow unittest
129 auto wstr
= cast(wstring
) str;
134 static immutable expected
= "`immutable(char)[]` of length 5 cannot be cast to `immutable(wchar)[]` as " ~
135 "its length in bytes (5) is not a multiple of `immutable(wchar).sizeof` (2).";
139 import core
.stdc
.stdio
;
140 printf("Expected: |%.*s|\n", cast(int) expected
.length
, expected
.ptr
);
141 printf("Actual : |%.*s|\n", cast(int) msg
.length
, msg
.ptr
);