All files main.js

98.04% Statements 201/205
89.18% Branches 33/37
100% Functions 1/1
98.04% Lines 201/205

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 2062x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 247x 247x 247x 247x 247x 247x 247x 247x 20x 20x 247x 2x 2x 247x 21x 21x 247x 74x 26x 26x 74x 178x 247x 60x 60x 247x 102x 14x 14x 247x 10x 16x 3x 3x 247x 22x 22x 247x 34x 34x 35x 35x 35x 247x 247x 247x 247x   247x   35x 35x 35x 247x     25x 25x 21x 21x 4x 247x 2x 2x 2x 2x 2x  
/**
* @license Apache-2.0
*
* Copyright (c) 2026 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
'use strict';
 
// MODULES //
 
var isCollection = require( '@stdlib/assert/is-collection' );
var isArrayBuffer = require( '@stdlib/assert/is-arraybuffer' );
var isNonNegativeIntegerArray = require( '@stdlib/assert/is-nonnegative-integer-array' ).primitives;
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
var isIntegerArray = require( '@stdlib/assert/is-integer-array' ).primitives;
var isOrder = require( '@stdlib/ndarray/base/assert/is-order' );
var isDataType = require( '@stdlib/ndarray/base/assert/is-data-type' );
var isGenericDataType = require( '@stdlib/ndarray/base/assert/is-generic-data-type' );
var isBinaryDataType = require( '@stdlib/ndarray/base/assert/is-binary-data-type' );
var isStructDataType = require( '@stdlib/ndarray/base/assert/is-struct-data-type' );
var isBufferLengthCompatible = require( '@stdlib/ndarray/base/assert/is-buffer-length-compatible' );
var numel = require( '@stdlib/ndarray/base/numel' );
var minmaxViewBufferIndex = require( '@stdlib/ndarray/base/minmax-view-buffer-index' );
var strides2offset = require( '@stdlib/ndarray/base/strides2offset' );
var ndarray = require( '@stdlib/ndarray/ctor' );
var arraybuffer2buffer = require( '@stdlib/buffer/from-arraybuffer' );
var typedarray = require( '@stdlib/array/typed' );
var structFactory = require( '@stdlib/array/struct-factory' );
var format = require( '@stdlib/string/format' );
 
 
// MAIN //
 
/**
* Creates an ndarray from an ArrayBuffer.
*
* @param {*} dtype - data type
* @param {ArrayBuffer} buffer - ArrayBuffer
* @param {NonNegativeIntegerArray} shape - array shape
* @param {IntegerArray} strides - array strides
* @param {NonNegativeInteger} byteOffset - byte offset
* @param {string} order - memory layout (either row-major or column-major)
* @param {Options} [options] - function options
* @param {boolean} [options.readonly=false] - boolean indicating whether to return a read-only ndarray
* @param {string} [options.mode='throw'] - specifies how to handle indices which exceed ndarray dimensions
* @param {StringArray} [options.submode=[options.mode]] - specifies how to handle subscripts which exceed array dimensions on a per dimension basis
* @throws {TypeError} `dtype` argument must be a supported ndarray data type
* @throws {TypeError} `buffer` argument must be an ArrayBuffer
* @throws {TypeError} `shape` argument must be an array-like object containing nonnegative integers
* @throws {TypeError} `strides` argument must be an array-like object containing integers
* @throws {Error} `strides` argument length must equal the number of dimensions (except for zero-dimensional arrays; in which case, the `strides` argument length must be equal to `1`)
* @throws {Error} for zero-dimensional ndarrays, the `strides` argument must contain a single element equal to `0`
* @throws {TypeError} `byteOffset` argument must be a nonnegative integer
* @throws {TypeError} `order` argument must be a supported ndarray order
* @throws {Error} `buffer` argument must be compatible with specified meta data
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @throws {RangeError} too many dimensions
* @returns {ndarray} ndarray
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 32 );
* var v = arraybuffer2ndarray( 'float64', buf, [ 2, 2 ], [ 2, 1 ], 0, 'row-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 4
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 32 );
* var v = arraybuffer2ndarray( 'float32', buf, [ 4, 2 ], [ 2, 1 ], 0, 'row-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 8
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 32 );
* var v = arraybuffer2ndarray( 'float64', buf, [ 2, 2 ], [ -2, -1 ], 0, 'row-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 4
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 32 );
* var v = arraybuffer2ndarray( 'float64', buf, [ 2, 2 ], [ -1, -2 ], 0, 'column-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 4
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 64 );
* var v = arraybuffer2ndarray( 'float64', buf, [ 2, 2, 2 ], [ 2, -4, 1 ], 0, 'row-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 8
*
* @example
* var numel = require( '@stdlib/ndarray/numel' );
* var ArrayBuffer = require( '@stdlib/array/buffer' );
*
* var buf = new ArrayBuffer( 32 );
* var v = arraybuffer2ndarray( 'float64', buf, [ 1, 2 ], [ -2, -1 ], 8, 'row-major' );
* // returns <ndarray>
*
* var N = numel( v );
* // returns 2
*/
function arraybuffer2ndarray( dtype, buffer, shape, strides, byteOffset, order, options ) { // eslint-disable-line max-len
	var offset;
	var ndims;
	var buf;
	var idx;
	var N;
 
	if ( !isDataType( dtype ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be a supported ndarray data type. Value: `%s`.', dtype ) );
	}
	if ( isGenericDataType( dtype ) ) {
		throw new TypeError( format( 'invalid argument. ArrayBuffer is incompatible with the specified data type. Value: `%s`.', dtype ) );
	}
	if ( !isArrayBuffer( buffer ) ) {
		throw new TypeError( format( 'invalid argument. Second argument must be an ArrayBuffer. Value: `%s`.', buffer ) );
	}
	if ( !isNonNegativeIntegerArray( shape ) ) {
		if ( !isCollection( shape ) || shape.length > 0 ) {
			throw new TypeError( format( 'invalid argument. Third argument must be an array-like object containing nonnegative integers. Value: `%s`.', shape ) );
		}
	}
	ndims = shape.length;
	if ( !isIntegerArray( strides ) ) {
		throw new TypeError( format( 'invalid argument. Fourth argument must be an array-like object containing integers. Value: `%s`.', strides ) );
	}
	if ( ndims > 0 ) {
		if ( strides.length !== ndims ) {
			throw new RangeError( format( 'invalid argument. Fourth argument length must match the number of dimensions. Expected number of dimensions: `%u`. Strides length: `%u`.', ndims, strides.length ) );
		}
	} else if ( strides.length !== 1 ) {
		throw new RangeError( 'invalid argument. Fourth argument length must be equal to 1 when creating a zero-dimensional ndarray.' );
	} else if ( strides[ 0 ] !== 0 ) {
		throw new RangeError( format( 'invalid argument. Fourth argument must contain a single element equal to 0. Value: `%d`.', strides[ 0 ] ) );
	}
	if ( !isNonNegativeInteger( byteOffset ) ) {
		throw new TypeError( format( 'invalid argument. Fifth argument must be a nonnegative integer. Value: `%s`.', byteOffset ) );
	}
	if ( !isOrder( order ) ) {
		throw new TypeError( format( 'invalid argument. Sixth argument must be a supported order. Value: `%s`.', order ) );
	}
	// Compute the number of underlying elements across which the ndarray view will span:
	offset = strides2offset( shape, strides );
	idx = minmaxViewBufferIndex( shape, strides, offset );
	N = ( numel( shape ) === 0 ) ? 0 : idx[ 1 ] - idx[ 0 ] + 1;
 
	// Create the underlying ndarray buffer:
	if ( isBinaryDataType( dtype ) ) {
		buf = arraybuffer2buffer( buffer, byteOffset, N );
	} else if ( isStructDataType( dtype ) ) {
		buf = structFactory( dtype )( buffer, byteOffset, N );
	} else {
		buf = typedarray( buffer, byteOffset, N, dtype );
	}
	if ( ndims > 0 && !isBufferLengthCompatible( buf.length, shape, strides, offset ) && numel( shape ) > 0 ) { // eslint-disable-line max-len
		throw new Error( 'invalid arguments. Input buffer is incompatible with the specified meta data. Ensure that the offset is valid with regard to the strides array and that the buffer has enough elements to satisfy the desired array shape.' );
	}
	// Return a new ndarray instance:
	if ( arguments.length > 6 ) {
		return new ndarray( dtype, buf, shape, strides, offset, order, options ); // eslint-disable-line max-len
	}
	return new ndarray( dtype, buf, shape, strides, offset, order );
}
 
 
// EXPORTS //
 
module.exports = arraybuffer2ndarray;