Add encode subcommand
Wraps gid.encodeGid, prints the packed-u32 as decimal on stdout, emits usage on stderr on bad arity, and a labelled error on out-of-range or non-integer input.
This commit is contained in:
@@ -30,7 +30,7 @@ function run(argv, { out, err }) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const handlers = {
|
const handlers = {
|
||||||
// populated in subsequent tasks
|
encode: require('./commands/encode'),
|
||||||
};
|
};
|
||||||
const handler = handlers[head];
|
const handler = handlers[head];
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
|
|||||||
32
src/commands/encode.js
Normal file
32
src/commands/encode.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { encodeGid } = require('../gid');
|
||||||
|
|
||||||
|
const USAGE = 'usage: sporel-mapper encode <atlas_idx> <tile_id> [rotation]\n';
|
||||||
|
|
||||||
|
function parseIntStrict(s, field) {
|
||||||
|
if (!/^-?\d+$/.test(s)) {
|
||||||
|
throw new RangeError(`${field} '${s}' is not an integer`);
|
||||||
|
}
|
||||||
|
return parseInt(s, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run(args, { out, err }) {
|
||||||
|
if (args.length < 2 || args.length > 3) {
|
||||||
|
err.write(USAGE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const atlas = parseIntStrict(args[0], 'atlas');
|
||||||
|
const tile = parseIntStrict(args[1], 'tile');
|
||||||
|
const rotation = args.length === 3 ? parseIntStrict(args[2], 'rotation') : 0;
|
||||||
|
const gid = encodeGid(atlas, tile, rotation);
|
||||||
|
out.write(`${gid}\n`);
|
||||||
|
return 0;
|
||||||
|
} catch (e) {
|
||||||
|
err.write(`error: ${e.message}\n`);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { run };
|
||||||
54
tests/encode.test.js
Normal file
54
tests/encode.test.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const test = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const { run } = require('../src/cli');
|
||||||
|
|
||||||
|
class Sink {
|
||||||
|
constructor() { this.chunks = []; }
|
||||||
|
write(s) { this.chunks.push(s); }
|
||||||
|
get text() { return this.chunks.join(''); }
|
||||||
|
}
|
||||||
|
|
||||||
|
test('encode: (0,12,1) prints 196 with trailing newline, exit 0', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode', '0', '12', '1'], { out, err });
|
||||||
|
assert.equal(code, 0);
|
||||||
|
assert.equal(out.text, '196\n');
|
||||||
|
assert.equal(err.text, '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('encode: rotation defaults to 0', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode', '0', '12'], { out, err });
|
||||||
|
assert.equal(code, 0);
|
||||||
|
assert.equal(out.text, '192\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('encode: no args prints usage to stderr, exit 1', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode'], { out, err });
|
||||||
|
assert.equal(code, 1);
|
||||||
|
assert.match(err.text, /usage: sporel-mapper encode/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('encode: too many args prints usage, exit 1', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode', '0', '0', '0', '0'], { out, err });
|
||||||
|
assert.equal(code, 1);
|
||||||
|
assert.match(err.text, /usage/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('encode: out-of-range tile prints error, exit 1', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode', '0', '99999999', '0'], { out, err });
|
||||||
|
assert.equal(code, 1);
|
||||||
|
assert.match(err.text, /error: tile/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('encode: non-integer arg prints error, exit 1', () => {
|
||||||
|
const out = new Sink(); const err = new Sink();
|
||||||
|
const code = run(['encode', '0', 'abc', '0'], { out, err });
|
||||||
|
assert.equal(code, 1);
|
||||||
|
assert.match(err.text, /error/i);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user