'use strict'; const moment = require("moment"); const bufferReaderFactory = require("../buffer-reader"); const decode = require("./decode"); const removeRightPadding = require("../remove-right-padding"); function offsetInMinutes(value) { /* "Time zone offset from GMT in 15 minute intervals, starting at interval -48 (west) and running up to interval 52 (east). * So value 0 indicates interval -48 which equals GMT-12 hours, and value 100 indicates interval 52 which equals GMT+13 hours." * * ref: http://wiki.osdev.org/ISO_9660#Date.2Ftime_format */ return (value - 48) * 15; } module.exports = function createReader(buffer, {encoding} = {encoding: "ascii"}) { let bufferReaderRules = { /* String types */ strA: { decode: function parseStrA(buffer) { return removeRightPadding(decode(buffer, "ascii")); } }, strD: { decode: function parseStrD(buffer) { return bufferReaderRules.strA.decode(buffer); } }, strA1: { decode: function parseStrA(buffer) { return removeRightPadding(decode(buffer, encoding)); } }, strD1: { decode: function parseStrD(buffer) { return bufferReaderRules.strA1.decode(buffer); } }, strFilename: { decode: function parseStrFilename(buffer) { let decodedString = decode(buffer, encoding); let [filename, version] = decodedString.split(";"); return {filename, version}; } }, /* 8-bit integers */ int8: { length: 1, decode: function parseInt8(buffer) { return buffer.readUInt8(0); } }, sint8: { length: 1, decode: function parseSInt8(buffer) { return buffer.readInt8(0); } }, /* 16-bit integers */ int16_LSB: { length: 2, decode: function parseInt16_LSB(buffer) { return buffer.readUInt16LE(0); } }, int16_MSB: { length: 2, decode: function parseInt16_LSB(buffer) { return buffer.readUInt16BE(0); } }, int16_LSB_MSB: { length: 4, decode: function parseInt16_LSB(buffer) { return bufferReaderRules.int16_LSB.decode(buffer.slice(0, 2)); } }, sint16_LSB: { length: 2, decode: function parseSInt16_LSB(buffer) { return buffer.readInt16LE(0); } }, sint16_MSB: { length: 2, decode: function parseSInt16_LSB(buffer) { return buffer.readInt16BE(0); } }, sint16_LSB_MSB: { length: 4, decode: function parseSInt16_LSB(buffer) { return bufferReaderRules.sint16_LSB.decode(buffer.slice(0, 2)); } }, /* 32-bit integers */ int32_LSB: { length: 4, decode: function parseInt32_LSB(buffer) { return buffer.readUInt32LE(0); } }, int32_MSB: { length: 4, decode: function parseInt32_LSB(buffer) { return buffer.readUInt32BE(0); } }, int32_LSB_MSB: { length: 8, decode: function parseInt32_LSB(buffer) { return bufferReaderRules.int32_LSB.decode(buffer.slice(0, 4)); } }, sint32_LSB: { length: 4, decode: function parseSInt32_LSB(buffer) { return buffer.readInt32LE(0); } }, sint32_MSB: { length: 4, decode: function parseSInt32_LSB(buffer) { return buffer.readInt32BE(0); } }, sint32_LSB_MSB: { length: 8, decode: function parseSInt32_LSB(buffer) { return bufferReaderRules.sint32_LSB.decode(buffer.slice(0, 4)); } }, /* Date/time */ decDatetime: { length: 17, decode: function parseDecDatetime(buffer) { let year = parseInt(bufferReaderRules.strD.decode(buffer.slice(0, 4))); let month = parseInt(bufferReaderRules.strD.decode(buffer.slice(4, 6))) - 1; // "Note that like moment(Array) and new Date(year, month, date), months are 0 indexed." let day = parseInt(bufferReaderRules.strD.decode(buffer.slice(6, 8))); let hour = parseInt(bufferReaderRules.strD.decode(buffer.slice(8, 10))); let minute = parseInt(bufferReaderRules.strD.decode(buffer.slice(10, 12))); let second = parseInt(bufferReaderRules.strD.decode(buffer.slice(12, 14))); let centisecond = parseInt(bufferReaderRules.strD.decode(buffer.slice(14, 16))); let timezoneOffset = bufferReaderRules.int8.decode(buffer.slice(16, 17)); if (year === 0 && month === 0 && day === 0 && hour === 0 && minute === 0 && second === 0 && centisecond === 0 && timezoneOffset === 0) { return null; } else { return moment({ year, month, day, hour, minute, second, millisecond: centisecond * 10, }).utcOffset(offsetInMinutes(timezoneOffset)); } } }, directoryDatetime: { length: 7, decode: function parseDirectoryDatetime(buffer) { return moment({ year: 1900 + bufferReaderRules.int8.decode(buffer.slice(0, 0 + 1)), month: bufferReaderRules.int8.decode(buffer.slice(1, 1 + 1)) - 1, day: bufferReaderRules.int8.decode(buffer.slice(2, 2 + 1)), hour: bufferReaderRules.int8.decode(buffer.slice(3, 3 + 1)), minute: bufferReaderRules.int8.decode(buffer.slice(4, 4 + 1)), second: bufferReaderRules.int8.decode(buffer.slice(5, 5 + 1)), }).utcOffset(offsetInMinutes(bufferReaderRules.int8.decode(buffer.slice(6, 6 + 1)))); } } } return bufferReaderFactory(bufferReaderRules)(buffer); };