/* jshint esversion: 2024, module: true */ import { InterfaceState } from './enums.js'; /** * Static utility functions * @module Utils */ class Utils { /** * Convert byte array to MAC address * @static * @param {Array} bytes - Byte array * @returns {string} MAC address */ static arrayToMac(bytes) { if (!Array.isArray(bytes)) return ''; return bytes.map(byte => byte.toString(16).padStart(2, '0')).join(':'); } /** * Convert byte array to IP address * @static * @param {Array|Object} obj - IP data * @returns {string} IP address */ static ipFromArray(obj) { let bytes = null; if (Array.isArray(obj)) { bytes = obj; } else if (obj?.Address && Array.isArray(obj.Address)) { bytes = obj.Address; } else { return ''; } // IPv4 if (bytes.length === 4) { return bytes.join('.'); } // IPv6 if (bytes.length === 16) { const parts = []; for (let i = 0; i < 16; i += 2) { parts.push(((bytes[i] << 8) | bytes[i + 1]).toString(16)); } return parts.join(':').replace(/(^|:)0+/g, '$1').replace(/:{3,}/, '::'); } return ''; } /** * Convert route object to string * @static * @param {Object} route - Route object * @returns {string} Route string */ static routeToString(route) { if (!route) return ''; const destination = route.Destination ? Utils.ipFromArray(route.Destination) : 'default'; const gateway = route.Gateway ? Utils.ipFromArray(route.Gateway) : ''; return gateway ? `${destination} → ${gateway}` : destination; } /** * Get interface state from interface object * @static * @param {Object} iface - Interface object * @returns {Symbol} Interface state */ static getInterfaceState(iface) { const state = iface.OperationalState ?? iface.AdministrativeState ?? iface.State ?? ''; const stateLower = state.toLowerCase(); if (stateLower.includes('up') || stateLower.includes('routable') || stateLower.includes('configured')) { return InterfaceState.UP; } else if (stateLower.includes('down') || stateLower.includes('off')) { return InterfaceState.DOWN; } else { return InterfaceState.UNKNOWN; } } /** * Get CSS class for interface state * @static * @param {Symbol} state - Interface state * @returns {string} CSS class */ static getStateClass(state) { switch (state) { case InterfaceState.UP: return 'state-up'; case InterfaceState.DOWN: return 'state-down'; default: return 'state-unknown'; } } /** * Get display text for interface state * @static * @param {Object} iface - Interface object * @returns {string} State text */ static getStateText(iface) { return iface.OperationalState ?? iface.AdministrativeState ?? iface.State ?? 'unknown'; } /** * Sanitize HTML string * @static * @param {string} str - String to sanitize * @returns {string} Sanitized string */ static sanitizeHTML(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } /** * Create DOM element from HTML string * @static * @param {string} html - HTML string * @returns {HTMLElement} DOM element */ static createElementFromHTML(html) { const template = document.createElement('template'); template.innerHTML = html.trim(); return template.content.firstElementChild; } /** * Debounce function * @static * @param {Function} func - Function to debounce * @param {number} wait - Wait time in ms * @returns {Function} Debounced function */ static debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } } export { Utils };